~3v1n0/nux/check-dnd_area-trusty

« back to all changes in this revision

Viewing changes to Nux/WindowCompositor.cpp

  • Committer: Tarmac
  • Author(s): Sam Spilsbury, Marco Trevisan (Treviño), Chris Townsend
  • Date: 2013-11-05 20:23:53 UTC
  • mfrom: (791.2.28 nux)
  • Revision ID: tarmac-20131105202353-58aojyevtnonqavv
Allow embedded clients to specify which windows should be redrawn.

Added some new API to nux to allow embedded clients (eg, compiz) to specify which BaseWindows should be redrawn on a frame. This is done by passing a list of rectangles to nux which represent the redraw region, and nux will mark all intersecting windows as needing re-presenting to the screen. This means that we aren't re-presenting every window to the screen on every frame (bad for performance, and also doesn't work correctly in the buffer-swap case).

Also added API to allow nux to tell the difference between draw and read framebuffers when it plays around with the framebuffer object binding. This is necessary in case the embedded client expects the read framebuffer binding to remain defined even after nux has changed the draw framebuffer binding.

(LP: #1091589). Fixes: https://bugs.launchpad.net/bugs/1091589.

Approved by PS Jenkins bot, Stephen M. Webb, Brandon Schaefer, Christopher Townsend.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
DECLARE_LOGGER(logger, "nux.window");
42
42
 
43
43
  WindowCompositor::WindowCompositor(WindowThread* window_thread)
44
 
  : reference_fbo_(0)
 
44
  : draw_reference_fbo_(0)
 
45
  , read_reference_fbo_(0)
45
46
  , window_thread_(window_thread)
 
47
  , currently_rendering_windows_(nullptr)
 
48
  , current_global_clip_rect_(nullptr)
46
49
  {
47
50
    m_OverlayWindow             = NULL;
48
51
    _tooltip_window             = NULL;
135
138
                                   _view_window_list.end(), window);
136
139
    if (it == _view_window_list.end())
137
140
    {
138
 
      _view_window_list.push_front(ObjectWeakPtr<BaseWindow>(window));
 
141
      _view_window_list.push_front(WeakBaseWindowPtr(window));
139
142
 
140
143
      RenderTargetTextures rt;
141
144
 
192
195
                                           NuxEventType event_type,
193
196
                                           ObjectWeakPtr<InputArea>& area_under_mouse_pointer)
194
197
  {
195
 
    ObjectWeakPtr<BaseWindow> window;
 
198
    WeakBaseWindowPtr window;
196
199
    GetAreaUnderMouse(mouse_position, event_type, area_under_mouse_pointer, window);
197
200
  }
198
201
 
199
202
  void WindowCompositor::GetAreaUnderMouse(const Point& mouse_position,
200
203
                                           NuxEventType event_type,
201
204
                                           ObjectWeakPtr<InputArea>& area_under_mouse_pointer,
202
 
                                           ObjectWeakPtr<BaseWindow>& window)
 
205
                                           WeakBaseWindowPtr& window)
203
206
  {
204
207
    window = NULL;
205
208
    area_under_mouse_pointer = NULL;
206
209
 
207
210
    // Go through the list of BaseWindo and find the first area over which the
208
211
    // mouse pointer is.
209
 
    WindowList::iterator window_it;
210
 
    for (window_it = _view_window_list.begin(); window_it != _view_window_list.end(); ++window_it)
 
212
    for (auto const& window_it : _view_window_list)
211
213
    {
212
 
      if ((*window_it).IsValid() && (*window_it)->IsVisible())
 
214
      // Since the mouse is really an input-level thing, we want to know
 
215
      // if the underlying input window is enabled or if the window is
 
216
      // visible
 
217
 
 
218
      if (!window_it.IsValid())
 
219
        continue;
 
220
 
 
221
      if (window_it->InputWindowEnabled() || window_it->IsVisible())
213
222
      {
214
 
        Area* area = (*window_it)->FindAreaUnderMouse(mouse_position, event_type);
 
223
        Area* area = window_it->FindAreaUnderMouse(mouse_position, event_type);
215
224
        if (area)
216
225
        {
217
226
          area_under_mouse_pointer = static_cast<InputArea*>(area);
218
 
          window = *window_it;
 
227
          window = window_it;
219
228
          return;
220
229
        }
221
230
      }
890
899
    unsigned int key_symbol,
891
900
    unsigned int special_keys_state,
892
901
    ObjectWeakPtr<InputArea>& key_focus_area,
893
 
    ObjectWeakPtr<BaseWindow>& window)
 
902
    WeakBaseWindowPtr& window)
894
903
  {
895
904
    key_focus_area = NULL;
896
905
    window = NULL;
897
906
 
898
907
    // Go through the list of BaseWindos and find the first area over which the mouse pointer is.
899
 
    WindowList::iterator window_it;
900
 
    window_it = _view_window_list.begin();
901
 
    while (!key_focus_area.IsValid() && window_it != _view_window_list.end())
 
908
    for (auto const& window_it : _view_window_list)
902
909
    {
903
 
      if ((*window_it).IsValid() && (*window_it)->IsVisible())
 
910
      if (window_it.IsValid() && window_it->IsVisible())
904
911
      {
905
 
        key_focus_area = NUX_STATIC_CAST(InputArea*, (*window_it)->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
 
912
        key_focus_area = NUX_STATIC_CAST(InputArea*, window_it->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
906
913
        if (key_focus_area.IsValid())
907
914
        {
908
915
          // We have found an area. We are going to exit the while loop.
909
 
          window = *window_it;
 
916
          window = window_it;
 
917
          break;
910
918
        }
911
919
      }
912
 
      ++window_it;
913
920
    }
914
921
 
915
922
    // If key_focus_area is NULL, then try the main window layout.
928
935
    unsigned int special_keys_state,
929
936
    InputArea* root_search_area,
930
937
    ObjectWeakPtr<InputArea>& key_focus_area,
931
 
    ObjectWeakPtr<BaseWindow>& window)
 
938
    WeakBaseWindowPtr& window)
932
939
  {
933
940
    key_focus_area = NULL;
934
941
    window = NULL;
975
982
    InputArea* keyboard_event_grab_view = GetKeyboardGrabArea();
976
983
 
977
984
    ObjectWeakPtr<InputArea> focus_area;   // The view under the mouse
978
 
    ObjectWeakPtr<BaseWindow> base_window; // The BaseWindow below the mouse pointer.
 
985
    WeakBaseWindowPtr base_window; // The BaseWindow below the mouse pointer.
979
986
 
980
987
    if (keyboard_event_grab_view)
981
988
    {
1173
1180
    inside_event_cycle_ = false;
1174
1181
  }
1175
1182
 
1176
 
  void WindowCompositor::StartModalWindow(ObjectWeakPtr<BaseWindow> window)
 
1183
  void WindowCompositor::StartModalWindow(WeakBaseWindowPtr window)
1177
1184
  {
1178
1185
    if (window == 0)
1179
1186
      return;
1186
1193
    }
1187
1194
  }
1188
1195
 
1189
 
  void WindowCompositor::StopModalWindow(ObjectWeakPtr<BaseWindow> window)
 
1196
  void WindowCompositor::StopModalWindow(WeakBaseWindowPtr window)
1190
1197
  {
1191
1198
    if (!_modal_view_window_list.empty())
1192
1199
    {
1206
1213
    if (it != _view_window_list.end())
1207
1214
    {
1208
1215
      _view_window_list.erase(it);
1209
 
      _view_window_list.push_front(ObjectWeakPtr<BaseWindow> (window));
 
1216
      _view_window_list.push_front(WeakBaseWindowPtr(window));
1210
1217
    }
1211
1218
 
1212
1219
    EnsureAlwaysOnFrontWindow();
1226
1233
    if (it != _view_window_list.end())
1227
1234
    {
1228
1235
      _view_window_list.erase(it);
1229
 
      _view_window_list.push_back(ObjectWeakPtr<BaseWindow> (window));
 
1236
      _view_window_list.push_back(WeakBaseWindowPtr(window));
1230
1237
    }
1231
1238
 
1232
1239
    EnsureAlwaysOnFrontWindow();
1273
1280
    if ((top_pos < bot_pos) && (strict == false))
1274
1281
    {
1275
1282
      _view_window_list.erase(it_top);
1276
 
      _view_window_list.insert(it_bot, ObjectWeakPtr<BaseWindow> (top_floating_view));
 
1283
      _view_window_list.insert(it_bot, WeakBaseWindowPtr(top_floating_view));
1277
1284
    }
1278
1285
 
1279
1286
    EnsureAlwaysOnFrontWindow();
1281
1288
 
1282
1289
  void WindowCompositor::SetAlwaysOnFrontWindow(BaseWindow* window)
1283
1290
  {
1284
 
    _always_on_front_window = ObjectWeakPtr<BaseWindow> (window);
 
1291
    _always_on_front_window = WeakBaseWindowPtr(window);
1285
1292
 
1286
1293
    EnsureAlwaysOnFrontWindow();
1287
1294
  }
1341
1348
    }
1342
1349
  }
1343
1350
 
 
1351
  namespace
 
1352
  {
 
1353
    void AssignWeakBaseWindowMatchingRaw(WindowCompositor::WeakBaseWindowPtr const& w, BaseWindow* bw, WindowCompositor::WeakBaseWindowPtr *ptr)
 
1354
    {
 
1355
      if (w.IsValid() && w.GetPointer() == bw)
 
1356
        *ptr = w;
 
1357
    }
 
1358
  }
 
1359
 
 
1360
  void WindowCompositor::ForEachBaseWindow(ForEachBaseWindowFunc const& func)
 
1361
  {
 
1362
    for (auto const& window : _view_window_list)
 
1363
    {
 
1364
      if (window.IsValid())
 
1365
        func(window);
 
1366
    }
 
1367
 
 
1368
    for (auto const& window : _modal_view_window_list)
 
1369
    {
 
1370
      if (window.IsValid())
 
1371
        func(window);
 
1372
    }
 
1373
 
 
1374
    if (m_MenuWindow.IsValid())
 
1375
      func(m_MenuWindow);
 
1376
 
 
1377
    if (_tooltip_window.IsValid())
 
1378
      func(_tooltip_window);
 
1379
 
 
1380
    if (m_OverlayWindow.IsValid())
 
1381
      func(m_OverlayWindow);
 
1382
  }
 
1383
 
1344
1384
  void WindowCompositor::Draw(bool SizeConfigurationEvent, bool force_draw)
1345
1385
  {
1346
1386
    inside_rendering_cycle_ = true;
1414
1454
  void WindowCompositor::DrawMenu(bool force_draw)
1415
1455
  {
1416
1456
#if !defined(NUX_MINIMAL)
1417
 
    ObjectWeakPtr<BaseWindow> window = m_MenuWindow;
 
1457
    WeakBaseWindowPtr window(m_MenuWindow);
1418
1458
 
1419
1459
    if (window.IsValid())
1420
1460
    {
1443
1483
 
1444
1484
  void WindowCompositor::DrawOverlay(bool /* force_draw */)
1445
1485
  {
1446
 
    ObjectWeakPtr<BaseWindow> window = m_OverlayWindow;
1447
1486
    int buffer_width = window_thread_->GetGraphicsEngine().GetWindowWidth();
1448
1487
    int buffer_height = window_thread_->GetGraphicsEngine().GetWindowHeight();
1449
1488
 
1450
 
    if (window.IsValid())
 
1489
    if (m_OverlayWindow.IsValid())
1451
1490
    {
1452
1491
      //window_thread_->GetGraphicsEngine().SetContext(x, y, buffer_width, buffer_height);
1453
1492
      window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
1468
1507
 
1469
1508
  void WindowCompositor::DrawTooltip(bool /* force_draw */)
1470
1509
  {
1471
 
    ObjectWeakPtr<BaseWindow> window = _tooltip_window;
1472
1510
    int buffer_width = window_thread_->GetGraphicsEngine().GetWindowWidth();
1473
1511
    int buffer_height = window_thread_->GetGraphicsEngine().GetWindowHeight();
1474
1512
 
1475
 
    if (window.IsValid())
 
1513
    if (_tooltip_window.IsValid())
1476
1514
    {
1477
1515
      //window_thread_->GetGraphicsEngine().SetContext(x, y, buffer_width, buffer_height);
1478
1516
      window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
1501
1539
    GetPainter().EmptyBackgroundStack();
1502
1540
  }
1503
1541
 
 
1542
  void WindowCompositor::PresentAnyReadyWindows()
 
1543
  {
 
1544
    if (!currently_rendering_windows_ || !current_global_clip_rect_)
 
1545
      return;
 
1546
 
 
1547
    GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
 
1548
 
 
1549
    // Present all buffers to the screen
 
1550
    graphics_engine.ApplyClippingRectangle();
 
1551
    CHECKGL(glDepthMask(GL_FALSE));
 
1552
 
 
1553
    WindowList &windows = *currently_rendering_windows_;
 
1554
    Geometry   &global_clip_rect = *current_global_clip_rect_;
 
1555
 
 
1556
    for (auto const& window_ptr : windows)
 
1557
    {
 
1558
      if (window_ptr.IsNull())
 
1559
        continue;
 
1560
 
 
1561
      BaseWindow* window = window_ptr.GetPointer();
 
1562
 
 
1563
      if (window->IsVisible())
 
1564
      {
 
1565
        auto const& win_geo = window->GetGeometry();
 
1566
 
 
1567
        if (!global_clip_rect.IsIntersecting(win_geo))
 
1568
        {
 
1569
          // The global clipping area can be seen as a per monitor clipping
 
1570
          // region. It is mostly used in embedded mode with compiz.  If we
 
1571
          // get here, it means that the BaseWindow we want to render is not
 
1572
          // in area of the monitor that compiz is currently rendering. So
 
1573
          // skip it.
 
1574
          continue;
 
1575
        }
 
1576
 
 
1577
        RenderTargetTextures& rt = GetWindowBuffer(window);
 
1578
 
 
1579
        if (rt.color_rt.IsValid())
 
1580
        {
 
1581
          /* Already been presented */
 
1582
          if (!window->_contents_ready_for_presentation)
 
1583
            continue;
 
1584
 
 
1585
          /* Caller doesn't want us to render this yet */
 
1586
          if (window_thread_->IsEmbeddedWindow() && !window->AllowPresentationInEmbeddedMode())
 
1587
            continue;
 
1588
 
 
1589
          // Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
 
1590
          // has cancelled any opengl framebuffer object that was set.
 
1591
          PresentBufferToScreen(rt.color_rt, win_geo.x, win_geo.y, false, false, window->GetOpacity(), window->premultiply());
 
1592
 
 
1593
          window->_contents_ready_for_presentation = false;
 
1594
        }
 
1595
      }
 
1596
    }
 
1597
  }
 
1598
 
1504
1599
  void WindowCompositor::RenderTopViews(bool force_draw,
1505
1600
                                        WindowList& windows_to_render,
1506
1601
                                        bool drawModal)
1512
1607
    GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
1513
1608
    unsigned int window_width = graphics_engine.GetWindowWidth();
1514
1609
    unsigned int window_height = graphics_engine.GetWindowHeight();
1515
 
    GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
1516
1610
    graphics_engine.SetViewport(0, 0, window_width, window_height);
1517
1611
    graphics_engine.EmptyClippingRegion();
1518
1612
 
1519
1613
    Geometry global_clip_rect = graphics_engine.GetScissorRect();
1520
1614
    global_clip_rect.y = window_height - global_clip_rect.y - global_clip_rect.height;
1521
1615
 
 
1616
    current_global_clip_rect_ = &global_clip_rect;
 
1617
 
 
1618
    // We don't need to restore framebuffers if we didn't update any windows
 
1619
    bool updated_any_windows = false;
 
1620
 
1522
1621
    // Always make a copy of the windows to render.  We have no control over
1523
1622
    // the windows we are actually drawing.  It has been observed that some
1524
1623
    // windows modify the windows stack during the draw process.
1530
1629
    // list, lets reverse it as we are constructing, as we want to draw the
1531
1630
    // windows from back to front.
1532
1631
    WindowList windows(windows_to_render.rbegin(), windows_to_render.rend());
1533
 
    for (WindowList::iterator it = windows.begin(), end = windows.end(); it != end; ++it)
 
1632
 
 
1633
    currently_rendering_windows_ = &windows;
 
1634
 
 
1635
    for (auto const& window_ptr : windows)
1534
1636
    {
1535
 
      WeakBaseWindowPtr& window_ptr = *it;
1536
1637
      if (window_ptr.IsNull())
1537
1638
        continue;
1538
1639
 
1539
1640
      BaseWindow* window = window_ptr.GetPointer();
 
1641
 
1540
1642
      if (!drawModal && window->IsModal())
1541
1643
        continue;
1542
1644
 
1543
1645
      if (window->IsVisible())
1544
1646
      {
1545
 
        if (global_clip_rect.Intersect(window->GetGeometry()).IsNull())
 
1647
        auto const& win_geo = window->GetGeometry();
 
1648
        if (!global_clip_rect.IsIntersecting(win_geo))
1546
1649
        {
1547
1650
          // The global clipping area can be seen as a per monitor clipping
1548
1651
          // region. It is mostly used in embedded mode with compiz.  If we
1586
1689
          }
1587
1690
          else
1588
1691
          {
1589
 
            int x = window->GetBaseX();
1590
 
            int y = window->GetBaseY();
1591
1692
            Matrix4 mat;
1592
 
            mat.Translate(x, y, 0);
 
1693
            mat.Translate(win_geo.x, win_geo.y, 0);
1593
1694
            graphics_engine.SetOrthographicProjectionMatrix(window_width, window_height);
1594
1695
          }
1595
1696
 
1596
1697
          RenderTopViewContent(window, force_draw);
1597
 
        }
1598
1698
 
1599
 
        if (rt.color_rt.IsValid())
1600
 
        {
1601
1699
          m_FrameBufferObject->Deactivate();
1602
 
 
1603
 
          // Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
1604
 
          // has cancelled any opengl framebuffer object that was set.
1605
 
 
1606
 
          CHECKGL(glDepthMask(GL_FALSE));
1607
 
          {
1608
 
            graphics_engine.ApplyClippingRectangle();
1609
 
            PresentBufferToScreen(rt.color_rt, window->GetBaseX(), window->GetBaseY(), false, false, window->GetOpacity(), window->premultiply());
1610
 
          }
1611
1700
          CHECKGL(glDepthMask(GL_TRUE));
1612
1701
          graphics_engine.GetRenderStates().SetBlend(false);
 
1702
          updated_any_windows = true;
1613
1703
        }
1614
1704
 
1615
1705
        window->_child_need_redraw = false;
 
1706
        window->_contents_ready_for_presentation = true;
1616
1707
      }
1617
1708
      else
1618
1709
      {
1622
1713
      }
1623
1714
    }
1624
1715
 
1625
 
    m_FrameBufferObject->Deactivate();
 
1716
    /* If any windows were updated, then we need to rebind our
 
1717
     * reference framebuffer */
 
1718
    if (updated_any_windows)
 
1719
    {
 
1720
      if (GetWindowThread()->IsEmbeddedWindow())
 
1721
      {
 
1722
        // Restore the reference framebuffer
 
1723
        if (!RestoreReferenceFramebuffer())
 
1724
        {
 
1725
          LOG_DEBUG(logger) << "RenderTopViews: Setting the Reference fbo has failed.";
 
1726
        }
 
1727
      }
 
1728
      else
 
1729
      {
 
1730
        GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
 
1731
      }
 
1732
    }
 
1733
 
 
1734
    /* Present any windows which haven't yet been presented */
 
1735
    PresentAnyReadyWindows();
 
1736
 
 
1737
    currently_rendering_windows_ = nullptr;
 
1738
    current_global_clip_rect_ = nullptr;
1626
1739
  }
1627
1740
 
1628
1741
  void WindowCompositor::RenderMainWindowComposition(bool force_draw)
1720
1833
      m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
1721
1834
      m_FrameBufferObject->Activate();
1722
1835
    }
1723
 
    else
1724
 
    {
1725
 
      if (GetWindowThread()->IsEmbeddedWindow() && reference_fbo_)
1726
 
      {
1727
 
        // In the context of Unity, we may want Nux to restore a specific fbo and render the
1728
 
        // BaseWindow texture into it. That fbo is called a reference framebuffer object. if a
1729
 
        // Reference framebuffer object is present, Nux sets it.
1730
 
        if (!RestoreReferenceFramebuffer())
1731
 
        {
1732
 
          nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
1733
 
        }
1734
 
      }
1735
 
      else
1736
 
      {
1737
 
        GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
1738
 
      }
1739
 
    }
 
1836
 
 
1837
    // Reference framebuffer is already restored
1740
1838
 
1741
1839
    window_thread_->GetGraphicsEngine().EmptyClippingRegion();
1742
1840
    window_thread_->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, window_width, window_height);
1949
2047
    {
1950
2048
      // There is a keyboard grab pending. Only an area that is a child of the area that has
1951
2049
      // the keyboard grab can be set to receive keyboard events.
1952
 
      nuxDebugMsg("[WindowCompositor::SetKeyFocusArea] There is a keyboard grab pending. Cannot change the keyboard event receiver.");
 
2050
      LOG_DEBUG(logger) << "SetKeyFocusArea: There is a keyboard grab pending. Cannot change the keyboard event receiver.";
1953
2051
      return false;
1954
2052
    }
1955
2053
 
2047
2145
  {
2048
2146
    WindowList::iterator it;
2049
2147
 
2050
 
    for (it = _view_window_list.begin(); it != _view_window_list.end(); ++it)
 
2148
    for (auto const& win : _view_window_list)
2051
2149
    {
2052
 
      if (!(*it).IsValid())
 
2150
      if (!win.IsValid())
2053
2151
        continue;
2054
 
      if ((*it)->IsVisible())
2055
 
      {
2056
 
        (*it)->NotifyConfigurationChange(Width, Height);
2057
 
      }
 
2152
 
 
2153
      if (win->IsVisible())
 
2154
        win->NotifyConfigurationChange(Width, Height);
2058
2155
    }
2059
2156
  }
2060
2157
 
2140
2237
 
2141
2238
      nuxAssert(buffer_width >= 1);
2142
2239
      nuxAssert(buffer_height >= 1);
2143
 
      // Restore Main Frame Buffer
2144
 
      m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
2145
 
      m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
2146
 
      m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
2147
 
      m_FrameBufferObject->Activate();
 
2240
      // Restore Main Frame Buffer if not in embedded mode
 
2241
      if (!GetWindowThread()->IsEmbeddedWindow())
 
2242
      {
 
2243
        m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
 
2244
        m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
 
2245
        m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
 
2246
        m_FrameBufferObject->Activate();
 
2247
      }
 
2248
      else
 
2249
      {
 
2250
        // Restore reference framebuffer
 
2251
        RestoreReferenceFramebuffer();
 
2252
 
 
2253
        // Present any ready windows
 
2254
        PresentAnyReadyWindows();
 
2255
      }
2148
2256
 
2149
2257
      window_thread_->GetGraphicsEngine().SetViewport(0, 0, buffer_width, buffer_height);
2150
2258
      window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
2215
2323
 
2216
2324
    if (GetPointerGrabArea() == area)
2217
2325
    {
2218
 
      nuxDebugMsg("[WindowCompositor::GrabPointerAdd] The area already has the grab");
 
2326
      LOG_DEBUG(logger) << "GrabPointerAdd: The area already has the grab";
2219
2327
      return result;
2220
2328
    }
2221
2329
 
2282
2390
 
2283
2391
    if (GetKeyboardGrabArea() == area)
2284
2392
    {
2285
 
      nuxDebugMsg("[WindowCompositor::GrabKeyboardAdd] The area already has the grab");
 
2393
      LOG_DEBUG(logger) << "GrabKeyboardAdd: The area already has the grab";
2286
2394
      return result;
2287
2395
    }
2288
2396
 
2429
2537
    return (*keyboard_grab_stack_.begin());
2430
2538
  }
2431
2539
 
2432
 
  void WindowCompositor::SetReferenceFramebuffer(unsigned int fbo_object, Geometry fbo_geometry)
 
2540
  void WindowCompositor::SetReferenceFramebuffer(unsigned int draw_fbo_object, unsigned int read_fbo_object, Geometry const& fbo_geometry)
2433
2541
  {
2434
 
    reference_fbo_ = fbo_object;
 
2542
    draw_reference_fbo_ = draw_fbo_object;
 
2543
    read_reference_fbo_ = read_fbo_object;
2435
2544
    reference_fbo_geometry_ = fbo_geometry;
2436
2545
  }
2437
2546
 
2497
2606
      return ok;
2498
2607
    }
2499
2608
 
2500
 
    void SetReferenceFramebufferViewport (const nux::Geometry &reference_fbo_geometry_)
 
2609
    void SetReferenceFramebufferViewport(const nux::Geometry &reference_fbo_geometry_)
2501
2610
    {
2502
2611
      CHECKGL(glViewport(reference_fbo_geometry_.x,
2503
2612
        reference_fbo_geometry_.y,
2508
2617
 
2509
2618
  bool WindowCompositor::RestoreReferenceFramebuffer()
2510
2619
  {
2511
 
    if (!reference_fbo_)
2512
 
      return false;
2513
 
 
2514
2620
    // It is assumed that the reference fbo contains valid textures.
2515
2621
    // Nux does the following:
2516
2622
    //    - Bind the reference fbo (reference_fbo_)
2517
2623
    //    - Call glDrawBuffer with GL_COLOR_ATTACHMENT0
2518
2624
    //    - Set the opengl viewport size (reference_fbo_geometry_)
2519
2625
 
2520
 
    CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, reference_fbo_));
2521
 
#ifndef NUX_OPENGLES_20
2522
 
    CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
2523
 
    CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
2524
 
#endif
2525
 
 
2526
 
    SetReferenceFramebufferViewport (reference_fbo_geometry_);
2527
 
 
2528
 
    return CheckExternalFramebufferStatus (GL_FRAMEBUFFER_EXT);
 
2626
#ifndef NUX_OPENGLES_20
 
2627
    CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, draw_reference_fbo_));
 
2628
    CHECKGL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, read_reference_fbo_));
 
2629
    if (draw_reference_fbo_)
 
2630
    {
 
2631
      CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
 
2632
    }
 
2633
    else
 
2634
    {
 
2635
      CHECKGL(glDrawBuffer(GL_BACK));
 
2636
    }
 
2637
 
 
2638
    if (read_reference_fbo_)
 
2639
    {
 
2640
      CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
 
2641
    }
 
2642
    else
 
2643
    {
 
2644
      CHECKGL(glReadBuffer(GL_BACK));
 
2645
    }
 
2646
#else
 
2647
    nuxAssertMsg(draw_reference_fbo_ == read_reference_fbo_,
 
2648
                 "[WindowCompositor::RestoreReferenceFramebuffer]: OpenGL|ES does not"\
 
2649
                 " support separate draw and read framebuffer bindings, using the supplied"\
 
2650
                 " draw binding");
 
2651
    CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER, draw_reference_fbo_));
 
2652
#endif
 
2653
 
 
2654
    SetReferenceFramebufferViewport(reference_fbo_geometry_);
 
2655
 
 
2656
#ifndef NUX_OPENGLES_20
 
2657
    int restore_status =
 
2658
           (!draw_reference_fbo_ ||
 
2659
            CheckExternalFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT)) &&
 
2660
           (!read_reference_fbo_ ||
 
2661
            CheckExternalFramebufferStatus(GL_READ_FRAMEBUFFER_EXT));
 
2662
#else
 
2663
    int restore_status = CheckExternalFramebufferStatus(GL_FRAMEBUFFER);
 
2664
#endif
 
2665
 
 
2666
    return restore_status;
2529
2667
  }
2530
2668
 
2531
2669
  void WindowCompositor::RestoreMainFramebuffer()
2533
2671
    // This is a bit inefficient as we unbind and then rebind
2534
2672
    nux::GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer ();
2535
2673
    RestoreReferenceFramebuffer ();
 
2674
 
 
2675
    /* Present any ready windows after restoring
 
2676
     * the reference framebuffer. This ensures that if
 
2677
     * we need to restore the reference framebuffer to
 
2678
     * get access to its contents through glCopyTexSubImage2D
 
2679
     * that it will also have any rendered views in it too
 
2680
     */
 
2681
    PresentAnyReadyWindows();
2536
2682
  }
2537
2683
 
2538
2684
#ifdef NUX_GESTURES_SUPPORT
2545
2691
  {
2546
2692
    InputArea *input_area = nullptr;
2547
2693
 
2548
 
    for (auto window : _view_window_list)
 
2694
    for (auto const& window : _view_window_list)
2549
2695
    {
2550
2696
      if (!window.IsValid())
2551
2697
        continue;