Nux

Merge lp:~smspillaz/nux/nux.fix_1091589 into lp:nux

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/nux/nux.fix_1091589
Merge into: lp:nux
Diff against target: 1657 lines (+1069/-119)
15 files modified
Nux/BaseWindow.cpp (+40/-0)
Nux/BaseWindow.h (+12/-0)
Nux/View.cpp (+7/-4)
Nux/WindowCompositor.cpp (+172/-49)
Nux/WindowCompositor.h (+13/-3)
Nux/WindowThread.cpp (+110/-8)
Nux/WindowThread.h (+50/-1)
NuxGraphics/GLDeviceFrameBufferObject.cpp (+20/-5)
NuxGraphics/GpuDevice.cpp (+7/-1)
NuxGraphics/GpuDeviceTexture.cpp (+7/-1)
NuxGraphics/IOpenGLFrameBufferObject.cpp (+7/-1)
configure.ac (+1/-1)
tests/gtest-nux-windowcompositor.cpp (+110/-44)
tests/gtest-nux-windowthread.cpp (+496/-0)
tests/gtest-nuxgraphics-texture.cpp (+17/-1)
To merge this branch: bzr merge lp:~smspillaz/nux/nux.fix_1091589
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Unity Team Pending
Review via email: mp+147543@code.launchpad.net

This proposal supersedes a proposal from 2013-02-10.

This proposal has been superseded by a proposal from 2013-05-26.

Commit message

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)

Description of the change

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)

Both APIs are fully tested.

Update: test results here: http://www.ucc.asn.au/~smspillaz/phoronix-test-suite/composite.xml

I was careful to modify phoronix-test-suite to run tests in windowed mode only, and those were the only three tests I was able to get to run in windowed mode. Of particular interest was the fact that the unigine demos had a 5x performance improvement, probably because the driver was spending less time filling redundant pixels from the compositor. In other areas we had a roughly 5FPS boost.

Compiz framerate graph:

http://www.ucc.asn.au/~smspillaz/compiz-perf-graph.png

You'll see that especially on the last test, it drops off quite a bit on the non buffer_age case, and is generally speaking lower across the board.

To post a comment you must log in.
lp:~smspillaz/nux/nux.fix_1091589 updated
752. By Sam Spilsbury

Merge lp:nux

753. By Sam Spilsbury

Don't hold on to the input focus reference to a hidden window

754. By Sam Spilsbury

Also track the last presented geometry so that we damage both sets
the next time the embedded painter asks for the damage set

Revision history for this message
Andrea Azzarone (azzar1) wrote :

39 + void BaseWindow::WasPresentedInEmbeddedMode()
40 + {
41 + _present_in_embedded_mode = false;
42 + _last_presented_geometry_in_embedded_mode = GetAbsoluteGeometry();
43 + }

Can we try to find a better name for this function? WasPresented* suggests me that the function should return a bool value.

45 + nux::Geometry const& BaseWindow::LastPresentedGeometryInEmbeddedMode()
46 + {
47 + return _last_presented_geometry_in_embedded_mode;
48 + }
49 +
50 + bool BaseWindow::AllowPresentationInEmbeddedMode()
51 + {
52 + return _present_in_embedded_mode;
53 + }

Can these methods be const?

 + for (WindowList::iterator it = _view_window_list.begin();
145 + it != _view_window_list.end();
146 + ++it)
147 + {
148 + if (it->IsValid())
149 + func (*it);
150 + }

Why not a range-based for loop? :)

206 + void WindowCompositor::SetReferenceFramebuffer(unsigned int draw_fbo_object,
207 + unsigned int read_fbo_object,
208 + Geometry fbo_geometry)

Geometry const& fbo... ?

374 + WindowCompositor::WeakBaseWindowPtr ptr;
375 + window_compositor_->OnAllBaseWindows(std::bind(AssignWeakBaseWindowMatchingRaw, _1, bw, &ptr));

It took me a while to understand what this code was for, maybe we can make it more readable.

406 + for (std::vector<WindowCompositor::WeakBaseWindowPtr>::iterator it =
407 + m_presentation_list_embedded.begin();
408 + it != m_presentation_list_embedded.end();
409 + ++it)
410 + {

For range-based loop... :)

Btw logic looks good to me.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Agree with all points. Will fix later today
On 26/03/2013 8:50 AM, "Andrea Azzarone" <email address hidden> wrote:

> 39 + void BaseWindow::WasPresentedInEmbeddedMode()
> 40 + {
> 41 + _present_in_embedded_mode = false;
> 42 + _last_presented_geometry_in_embedded_mode =
> GetAbsoluteGeometry();
> 43 + }
>
> Can we try to find a better name for this function? WasPresented* suggests
> me that the function should return a bool value.
>
> 45 + nux::Geometry const&
> BaseWindow::LastPresentedGeometryInEmbeddedMode()
> 46 + {
> 47 + return _last_presented_geometry_in_embedded_mode;
> 48 + }
> 49 +
> 50 + bool BaseWindow::AllowPresentationInEmbeddedMode()
> 51 + {
> 52 + return _present_in_embedded_mode;
> 53 + }
>
> Can these methods be const?
>
> + for (WindowList::iterator it = _view_window_list.begin();
> 145 + it != _view_window_list.end();
> 146 + ++it)
> 147 + {
> 148 + if (it->IsValid())
> 149 + func (*it);
> 150 + }
>
> Why not a range-based for loop? :)
>
> 206 + void WindowCompositor::SetReferenceFramebuffer(unsigned int
> draw_fbo_object,
> 207 + unsigned int
> read_fbo_object,
> 208 + Geometry
> fbo_geometry)
>
> Geometry const& fbo... ?
>
> 374 + WindowCompositor::WeakBaseWindowPtr ptr;
> 375 +
> window_compositor_->OnAllBaseWindows(std::bind(AssignWeakBaseWindowMatchingRaw,
> _1, bw, &ptr));
>
> It took me a while to understand what this code was for, maybe we can make
> it more readable.
>
> 406 + for
> (std::vector<WindowCompositor::WeakBaseWindowPtr>::iterator it =
> 407 + m_presentation_list_embedded.begin();
> 408 + it != m_presentation_list_embedded.end();
> 409 + ++it)
> 410 + {
>
> For range-based loop... :)
>
> Btw logic looks good to me.
> --
> https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589/+merge/147543
> You are the owner of lp:~smspillaz/nux/nux.fix_1091589.
>

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Just the only points warranting some discussion:

On Tue, Mar 26, 2013 at 8:50 AM, Andrea Azzarone <email address hidden> wrote:
> 39 + void BaseWindow::WasPresentedInEmbeddedMode()
> 40 + {
> 41 + _present_in_embedded_mode = false;
> 42 + _last_presented_geometry_in_embedded_mode = GetAbsoluteGeometry();
> 43 + }
>
> Can we try to find a better name for this function? WasPresented* suggests me that the function should return a bool value.

Yeah, I remember when I read through this code later I was suprised it didn't.

How about OnPresentedInEmbeddedMode (); ?

>
> 374 + WindowCompositor::WeakBaseWindowPtr ptr;
> 375 + window_compositor_->OnAllBaseWindows(std::bind(AssignWeakBaseWindowMatchingRaw, _1, bw, &ptr));
>
> It took me a while to understand what this code was for, maybe we can make it more readable.
>
>

Yeah, it could get a bit like that for a codebase that's not really
designed around callbacks. It might actually make sense to wrap this
up in a helper function:

nux::WindowCompositor::WeakBaseWindowPtr const&
nux::WindowCompositor::FindWeakBaseWindowPtrForRawPtr (nux::BaseWindow
*);

Then the helper function could look something like:

window_compositor_->OnAllBaseWindows(std::bind(AssignWeakBaseWindowPtrIfMatchesRawPtr,
_1, bw, &ptr));

Its basically a glorified:

nux::WindowCompositor::WeakBaseWindowPtr weak;

for (nux::WeakBaseWindowPtr const& ptr : weak_base_window)
    if (ptr.get () == raw)
    {
        weak = ptr;
        break;
    }

Having it this way would have been preferable, but then it would have
meant exposing the internals of WindowCompositor to BaseWindow, which
was something I wanted to avoid (nux already exposes too many
internals to clients).

What do you think?

--
Sam Spilsbury

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> Just the only points warranting some discussion:
>
> On Tue, Mar 26, 2013 at 8:50 AM, Andrea Azzarone <email address hidden> wrote:
> > 39 + void BaseWindow::WasPresentedInEmbeddedMode()
> > 40 + {
> > 41 + _present_in_embedded_mode = false;
> > 42 + _last_presented_geometry_in_embedded_mode =
> GetAbsoluteGeometry();
> > 43 + }
> >
> > Can we try to find a better name for this function? WasPresented* suggests
> me that the function should return a bool value.
>
> Yeah, I remember when I read through this code later I was suprised it didn't.
>
> How about OnPresentedInEmbeddedMode (); ?

Yeah sounds good to me.

>
> >
> > 374 + WindowCompositor::WeakBaseWindowPtr ptr;
> > 375 + window_compositor_->OnAllBaseWindows(std::bind(AssignWeakBaseWi
> ndowMatchingRaw, _1, bw, &ptr));
> >
> > It took me a while to understand what this code was for, maybe we can make
> it more readable.
> >
> >
>
> Yeah, it could get a bit like that for a codebase that's not really
> designed around callbacks. It might actually make sense to wrap this
> up in a helper function:
>
> nux::WindowCompositor::WeakBaseWindowPtr const&
> nux::WindowCompositor::FindWeakBaseWindowPtrForRawPtr (nux::BaseWindow
> *);
>
> Then the helper function could look something like:
>
> window_compositor_->OnAllBaseWindows(std::bind(AssignWeakBaseWindowPtrIfMatche
> sRawPtr,
> _1, bw, &ptr));
>
> Its basically a glorified:
>
> nux::WindowCompositor::WeakBaseWindowPtr weak;
>
> for (nux::WeakBaseWindowPtr const& ptr : weak_base_window)
> if (ptr.get () == raw)
> {
> weak = ptr;
> break;
> }
>
> Having it this way would have been preferable, but then it would have
> meant exposing the internals of WindowCompositor to BaseWindow, which
> was something I wanted to avoid (nux already exposes too many
> internals to clients).
>
> What do you think?
>

Ok just never mind. That comment was/is not blocking the MP ;)

>
>
> --
> Sam Spilsbury

lp:~smspillaz/nux/nux.fix_1091589 updated
755. By Sam Spilsbury

Cleanup - Use range based for, clarify names, add wrapper func

756. By Sam Spilsbury

Use the input visiblity to determine if the window is a mouse-under candidate

757. By Sam Spilsbury

Allow the area under the mouse to be found if it is visible but the input window isn't enabled either

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Okay, so I've talked to Didier about this and we've come up with a small plan of action. We'll need to give this a week solid of QA at the beginning of the S cycle and then make sure that we don't have any AP regressions. That'll happen in about two weeks.

lp:~smspillaz/nux/nux.fix_1091589 updated
758. By Sam Spilsbury

Merge lp:nux

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~smspillaz/nux/nux.fix_1091589 updated
759. By Sam Spilsbury

Make OnAllBaseWindows public

760. By Sam Spilsbury

Merge lp:nux

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~smspillaz/nux/nux.fix_1091589 updated
761. By Sam Spilsbury

Merge lp:nux

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~smspillaz/nux/nux.fix_1091589 updated
762. By Sam Spilsbury

Merge lp:nux

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~smspillaz/nux/nux.fix_1091589 updated
763. By Sam Spilsbury

Split the window update and window present stage, remove redundant
framebuffer binds

764. By Sam Spilsbury

Remove commented code

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Nux/BaseWindow.cpp'
2--- Nux/BaseWindow.cpp 2013-04-08 14:02:32 +0000
3+++ Nux/BaseWindow.cpp 2013-05-08 10:59:39 +0000
4@@ -47,6 +47,7 @@
5 : View(NUX_FILE_LINE_PARAM)
6 , _paint_layer(new ColorLayer(Color(0xFF707070)))
7 , _opacity(1.0f)
8+ , _present_in_embedded_mode(false)
9 {
10 premultiply = true;
11 _name = WindowName;
12@@ -397,6 +398,8 @@
13 }
14 else
15 {
16+ SetEnterFocusInputArea(NULL);
17+
18 _entering_hidden_state = true;
19 sigHidden.emit(this);
20 GetWindowThread()->GetWindowCompositor().sigHiddenViewWindow.emit(this);
21@@ -490,6 +493,43 @@
22 return GetWindowThread()->GetWindowCompositor().GetBackupTextureData(this, width, height, format);
23 }
24
25+ void BaseWindow::PresentInEmbeddedModeOnThisFrame(bool force)
26+ {
27+ nuxAssertMsg (GetWindowThread()->IsEmbeddedWindow(),
28+ "[BaseWindow::PresentInEmbeddedModeOnThisFrame] only "
29+ "supported in embdded mode");
30+
31+ /* Invisible windows are never presented */
32+ if (!IsVisible())
33+ return;
34+
35+ if (nux::GetWindowThread()->AddToPresentationList(this, force))
36+ _present_in_embedded_mode = true;
37+ }
38+
39+ void BaseWindow::OnPresentedInEmbeddedMode()
40+ {
41+ _present_in_embedded_mode = false;
42+ _last_presented_geometry_in_embedded_mode = GetAbsoluteGeometry();
43+ }
44+
45+ nux::Geometry const& BaseWindow::LastPresentedGeometryInEmbeddedMode() const
46+ {
47+ return _last_presented_geometry_in_embedded_mode;
48+ }
49+
50+ bool BaseWindow::AllowPresentationInEmbeddedMode() const
51+ {
52+ return _present_in_embedded_mode;
53+ }
54+
55+ void BaseWindow::PrepareParentRedirectedView()
56+ {
57+ Area::PrepareParentRedirectedView();
58+ if (GetWindowThread()->IsEmbeddedWindow())
59+ PresentInEmbeddedModeOnThisFrame();
60+ }
61+
62 void BaseWindow::SetEnterFocusInputArea(InputArea *input_area)
63 {
64 if (_enter_focus_input_area)
65
66=== modified file 'Nux/BaseWindow.h'
67--- Nux/BaseWindow.h 2012-11-12 20:59:56 +0000
68+++ Nux/BaseWindow.h 2013-05-08 10:59:39 +0000
69@@ -188,6 +188,13 @@
70 return _name;
71 }
72
73+ void PresentInEmbeddedModeOnThisFrame(bool force = false);
74+ void OnPresentedInEmbeddedMode();
75+ bool AllowPresentationInEmbeddedMode() const;
76+ nux::Geometry const& LastPresentedGeometryInEmbeddedMode() const;
77+
78+ void PrepareParentRedirectedView();
79+
80 #ifdef NUX_GESTURES_SUPPORT
81 virtual Area* GetInputAreaHitByGesture(const nux::GestureEvent &event);
82 #endif
83@@ -261,6 +268,11 @@
84 bool _child_need_redraw; //!<True is there is a child of the BaseWindow that needs to be redrawn;
85 float _opacity;
86
87+ bool _present_in_embedded_mode; //!<True if we should draw this window's
88+ // backing texture to the screen on the
89+ // next frame
90+ nux::Geometry _last_presented_geometry_in_embedded_mode;
91+
92 friend class PopUpWindow;
93
94 friend class WindowThread;
95
96=== modified file 'Nux/View.cpp'
97--- Nux/View.cpp 2013-04-08 14:02:32 +0000
98+++ Nux/View.cpp 2013-05-08 10:59:39 +0000
99@@ -425,6 +425,13 @@
100
101 void View::QueueDraw()
102 {
103+ // Report to a parent view with redirect_rendering_to_texture_ set to true that one of its children
104+ // needs to be redrawn.
105+ //
106+ // We should always do this, as the conditions for parent rendering may have
107+ // changed between child QueueDraw calls (eg window visibility)
108+ PrepareParentRedirectedView();
109+
110 if (draw_cmd_queued_)
111 return;
112
113@@ -435,10 +442,6 @@
114 application->RequestRedraw();
115 }
116
117- // Report to a parent view with redirect_rendering_to_texture_ set to true that one of its children
118- // needs to be redrawn.
119- PrepareParentRedirectedView();
120-
121 if (view_layout_)
122 {
123 // If this view has requested a draw, then all of it children in the view_layout_
124
125=== modified file 'Nux/WindowCompositor.cpp'
126--- Nux/WindowCompositor.cpp 2013-05-07 00:11:34 +0000
127+++ Nux/WindowCompositor.cpp 2013-05-08 10:59:39 +0000
128@@ -41,7 +41,8 @@
129 DECLARE_LOGGER(logger, "nux.window");
130
131 WindowCompositor::WindowCompositor(WindowThread* window_thread)
132- : reference_fbo_(0)
133+ : draw_reference_fbo_(0)
134+ , read_reference_fbo_(0)
135 , window_thread_(window_thread)
136 {
137 m_OverlayWindow = NULL;
138@@ -209,7 +210,17 @@
139 WindowList::iterator window_it;
140 for (window_it = _view_window_list.begin(); window_it != _view_window_list.end(); ++window_it)
141 {
142- if ((*window_it).IsValid() && (*window_it)->IsVisible())
143+ // Since the mouse is really an input-level thing, we want to know
144+ // if the underlying input window is enabled or if the window is
145+ // visible
146+
147+ if (!window_it->IsValid())
148+ continue;
149+
150+ bool visible_or_input_enabled = (*window_it)->InputWindowEnabled() ||
151+ (*window_it)->IsVisible();
152+
153+ if (visible_or_input_enabled)
154 {
155 Area* area = (*window_it)->FindAreaUnderMouse(mouse_position, event_type);
156 if (area)
157@@ -1340,6 +1351,50 @@
158 }
159 }
160
161+ namespace
162+ {
163+ void
164+ AssignWeakBaseWindowMatchingRaw(WindowCompositor::WeakBaseWindowPtr const& w,
165+ BaseWindow* bw,
166+ WindowCompositor::WeakBaseWindowPtr *ptr)
167+ {
168+ if (w.IsValid() &&
169+ w.GetPointer() == bw)
170+ *ptr = w;
171+ }
172+ }
173+
174+ WindowCompositor::WeakBaseWindowPtr WindowCompositor::FindWeakBaseWindowPtrForRawPtr(nux::BaseWindow *raw)
175+ {
176+ using namespace std::placeholders;
177+
178+ WeakBaseWindowPtr weak;
179+ OnAllBaseWindows(std::bind (AssignWeakBaseWindowMatchingRaw, _1, raw, &weak));
180+ return weak;
181+ }
182+
183+ void WindowCompositor::OnAllBaseWindows(const WindowMutatorFunc &func)
184+ {
185+ for (WeakBaseWindowPtr const& ptr : _view_window_list)
186+ {
187+ if (ptr.IsValid())
188+ func (ptr);
189+ }
190+
191+ for (WeakBaseWindowPtr const& ptr : _view_window_list)
192+ if (ptr.IsValid())
193+ func (ptr);
194+
195+ if (m_MenuWindow.IsValid())
196+ func (m_MenuWindow);
197+
198+ if (_tooltip_window.IsValid())
199+ func (_tooltip_window);
200+
201+ if (m_OverlayWindow.IsValid())
202+ func (m_OverlayWindow);
203+ }
204+
205 void WindowCompositor::Draw(bool SizeConfigurationEvent, bool force_draw)
206 {
207 inside_rendering_cycle_ = true;
208@@ -1511,13 +1566,15 @@
209 GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
210 unsigned int window_width = graphics_engine.GetWindowWidth();
211 unsigned int window_height = graphics_engine.GetWindowHeight();
212- GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
213 graphics_engine.SetViewport(0, 0, window_width, window_height);
214 graphics_engine.EmptyClippingRegion();
215
216 Geometry global_clip_rect = graphics_engine.GetScissorRect();
217 global_clip_rect.y = window_height - global_clip_rect.y - global_clip_rect.height;
218
219+ // We don't need to restore framebuffers if we didn't update any windows
220+ bool updated_any_windows = false;
221+
222 // Always make a copy of the windows to render. We have no control over
223 // the windows we are actually drawing. It has been observed that some
224 // windows modify the windows stack during the draw process.
225@@ -1536,6 +1593,7 @@
226 continue;
227
228 BaseWindow* window = window_ptr.GetPointer();
229+
230 if (!drawModal && window->IsModal())
231 continue;
232
233@@ -1593,22 +1651,11 @@
234 }
235
236 RenderTopViewContent(window, force_draw);
237- }
238-
239- if (rt.color_rt.IsValid())
240- {
241- m_FrameBufferObject->Deactivate();
242-
243- // Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
244- // has cancelled any opengl framebuffer object that was set.
245-
246- CHECKGL(glDepthMask(GL_FALSE));
247- {
248- graphics_engine.ApplyClippingRectangle();
249- PresentBufferToScreen(rt.color_rt, window->GetBaseX(), window->GetBaseY(), false, false, window->GetOpacity(), window->premultiply());
250- }
251+
252+ m_FrameBufferObject->Deactivate ();
253 CHECKGL(glDepthMask(GL_TRUE));
254 graphics_engine.GetRenderStates().SetBlend(false);
255+ updated_any_windows = true;
256 }
257
258 window->_child_need_redraw = false;
259@@ -1621,7 +1668,61 @@
260 }
261 }
262
263- m_FrameBufferObject->Deactivate();
264+ if (updated_any_windows)
265+ {
266+ if (GetWindowThread ()->IsEmbeddedWindow())
267+ {
268+ // Restore the reference framebuffer
269+ if (!RestoreReferenceFramebuffer())
270+ {
271+ nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
272+ }
273+ }
274+ else
275+ GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
276+ }
277+
278+ // Present all buffers to the screen
279+ graphics_engine.ApplyClippingRectangle();
280+ CHECKGL(glDepthMask(GL_FALSE));
281+ for (WindowList::iterator it = windows.begin(), end = windows.end(); it != end; ++it)
282+ {
283+ WeakBaseWindowPtr& window_ptr = *it;
284+ if (window_ptr.IsNull())
285+ continue;
286+
287+ BaseWindow* window = window_ptr.GetPointer();
288+
289+ if (!drawModal && window->IsModal())
290+ continue;
291+
292+ if (window->IsVisible())
293+ {
294+ if (global_clip_rect.Intersect(window->GetGeometry()).IsNull())
295+ {
296+ // The global clipping area can be seen as a per monitor clipping
297+ // region. It is mostly used in embedded mode with compiz. If we
298+ // get here, it means that the BaseWindow we want to render is not
299+ // in area of the monitor that compiz is currently rendering. So
300+ // skip it.
301+ continue;
302+ }
303+
304+ RenderTargetTextures& rt = GetWindowBuffer(window);
305+
306+ if (rt.color_rt.IsValid())
307+ {
308+ /* Caller doesn't want us to render this yet */
309+ if (GetWindowThread()->IsEmbeddedWindow() &&
310+ !window->AllowPresentationInEmbeddedMode())
311+ continue;
312+
313+ // Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
314+ // has cancelled any opengl framebuffer object that was set.
315+ PresentBufferToScreen(rt.color_rt, window->GetBaseX(), window->GetBaseY(), false, false, window->GetOpacity(), window->premultiply());
316+ }
317+ }
318+ }
319 }
320
321 void WindowCompositor::RenderMainWindowComposition(bool force_draw)
322@@ -1719,23 +1820,8 @@
323 m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
324 m_FrameBufferObject->Activate();
325 }
326- else
327- {
328- if (GetWindowThread()->IsEmbeddedWindow() && reference_fbo_)
329- {
330- // In the context of Unity, we may want Nux to restore a specific fbo and render the
331- // BaseWindow texture into it. That fbo is called a reference framebuffer object. if a
332- // Reference framebuffer object is present, Nux sets it.
333- if (!RestoreReferenceFramebuffer())
334- {
335- nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
336- }
337- }
338- else
339- {
340- GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
341- }
342- }
343+
344+ // Reference framebuffer is already restored
345
346 window_thread_->GetGraphicsEngine().EmptyClippingRegion();
347 window_thread_->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, window_width, window_height);
348@@ -2139,11 +2225,19 @@
349
350 nuxAssert(buffer_width >= 1);
351 nuxAssert(buffer_height >= 1);
352- // Restore Main Frame Buffer
353- m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
354- m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
355- m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
356- m_FrameBufferObject->Activate();
357+ // Restore Main Frame Buffer if not in embedded mode
358+ if (!GetWindowThread ()->IsEmbeddedWindow ())
359+ {
360+ m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
361+ m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
362+ m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
363+ m_FrameBufferObject->Activate();
364+ }
365+ else
366+ {
367+ // Restore reference framebuffer
368+ RestoreReferenceFramebuffer();
369+ }
370
371 window_thread_->GetGraphicsEngine().SetViewport(0, 0, buffer_width, buffer_height);
372 window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
373@@ -2428,9 +2522,12 @@
374 return (*keyboard_grab_stack_.begin());
375 }
376
377- void WindowCompositor::SetReferenceFramebuffer(unsigned int fbo_object, Geometry fbo_geometry)
378+ void WindowCompositor::SetReferenceFramebuffer(unsigned int draw_fbo_object,
379+ unsigned int read_fbo_object,
380+ Geometry const& fbo_geometry)
381 {
382- reference_fbo_ = fbo_object;
383+ draw_reference_fbo_ = draw_fbo_object;
384+ read_reference_fbo_ = read_fbo_object;
385 reference_fbo_geometry_ = fbo_geometry;
386 }
387
388@@ -2507,24 +2604,50 @@
389
390 bool WindowCompositor::RestoreReferenceFramebuffer()
391 {
392- if (!reference_fbo_)
393- return false;
394-
395 // It is assumed that the reference fbo contains valid textures.
396 // Nux does the following:
397 // - Bind the reference fbo (reference_fbo_)
398 // - Call glDrawBuffer with GL_COLOR_ATTACHMENT0
399 // - Set the opengl viewport size (reference_fbo_geometry_)
400
401- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, reference_fbo_));
402 #ifndef NUX_OPENGLES_20
403- CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
404- CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
405+ CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, draw_reference_fbo_));
406+ CHECKGL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, read_reference_fbo_));
407+ if (draw_reference_fbo_)
408+ {
409+ CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
410+ }
411+ else
412+ {
413+ CHECKGL(glDrawBuffer(GL_BACK));
414+ }
415+
416+ if (read_reference_fbo_)
417+ {
418+ CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
419+ }
420+ else
421+ {
422+ CHECKGL(glReadBuffer(GL_BACK));
423+ }
424+#else
425+ nuxAssertMsg(draw_reference_fbo_ == read_reference_fbo_,
426+ "[WindowCompositor::RestoreReferenceFramebuffer]: OpenGL|ES does not"\
427+ " support separate draw and read framebuffer bindings, using the supplied"\
428+ " draw binding");
429+ CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER, draw_reference_fbo_));
430 #endif
431
432 SetReferenceFramebufferViewport (reference_fbo_geometry_);
433
434- return CheckExternalFramebufferStatus (GL_FRAMEBUFFER_EXT);
435+#ifndef NUX_OPENGLES_20
436+ return (!draw_reference_fbo_ ||
437+ CheckExternalFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT)) &&
438+ (!read_reference_fbo_ ||
439+ CheckExternalFramebufferStatus(GL_READ_FRAMEBUFFER_EXT));
440+#else
441+ return CheckExternalFramebufferStatus(GL_FRAMEBUFFER);
442+#endif
443 }
444
445 void WindowCompositor::RestoreMainFramebuffer()
446
447=== modified file 'Nux/WindowCompositor.h'
448--- Nux/WindowCompositor.h 2013-04-29 23:33:12 +0000
449+++ Nux/WindowCompositor.h 2013-05-08 10:59:39 +0000
450@@ -23,6 +23,8 @@
451 #ifndef WINDOWCOMPOSITOR_H
452 #define WINDOWCOMPOSITOR_H
453
454+#include <functional>
455+
456 #include "BaseWindow.h"
457
458 #include <sigc++/trackable.h>
459@@ -53,6 +55,7 @@
460 {
461 public:
462 typedef ObjectWeakPtr<BaseWindow> WeakBaseWindowPtr;
463+ typedef std::function <void (const WeakBaseWindowPtr &)> WindowMutatorFunc;
464
465 WindowCompositor(WindowThread* window_thread);
466 ~WindowCompositor();
467@@ -115,6 +118,8 @@
468 */
469 InputArea* GetKeyFocusArea();
470
471+ void OnAllBaseWindows(const WindowMutatorFunc &);
472+
473 //! Signal emitted when a BaseWindow becomes visible.
474 /*!
475 This signal is emitted after the BaseWindow has emitted it own sigVisible signal.
476@@ -239,10 +244,11 @@
477 restored after Nux completes it rendering. The external fbo is used only in embedded mode. \n
478 If the fbo_object parameter 0, then the reference fbo is invalid and will not be used.
479
480- @param fbo_object The opengl index of the fbo.
481+ @param draw_fbo_object The opengl index of the GL_DRAW_FRAMEBUFFER_EXT.
482+ @param read_fbo_object The opengl index of the GL_READ_FRAMEBUFFER_EXT.
483 @param fbo_geometry The geometry of the fbo.
484 */
485- void SetReferenceFramebuffer(unsigned int fbo_object, Geometry fbo_geometry);
486+ void SetReferenceFramebuffer(unsigned int draw_fbo_object, unsigned int read_fbo_object, const Geometry &fbo_geometry);
487
488 /*!
489 Bind the reference opengl framebuffer object.
490@@ -408,6 +414,9 @@
491 #endif
492
493 private:
494+
495+ WeakBaseWindowPtr FindWeakBaseWindowPtrForRawPtr (nux::BaseWindow *);
496+
497 //! Render the interface.
498 void Draw(bool SizeConfigurationEvent, bool force_draw);
499
500@@ -534,7 +543,8 @@
501 int m_TooltipY;
502
503 //! The fbo to restore after Nux rendering in embedded mode.
504- unsigned int reference_fbo_;
505+ unsigned int draw_reference_fbo_;
506+ unsigned int read_reference_fbo_;
507 Geometry reference_fbo_geometry_;
508
509 //! True if the platform has support for depth textures.
510
511=== modified file 'Nux/WindowThread.cpp'
512--- Nux/WindowThread.cpp 2013-04-13 21:21:01 +0000
513+++ Nux/WindowThread.cpp 2013-05-08 10:59:39 +0000
514@@ -19,6 +19,8 @@
515 *
516 */
517
518+#include <functional>
519+
520 #include "Nux.h"
521 #include "Layout.h"
522 #include "NuxCore/Logger.h"
523@@ -50,6 +52,7 @@
524
525 WindowThread::WindowThread(const char *WindowTitle, int width, int height, AbstractThread *Parent, bool Modal)
526 : AbstractThread(Parent)
527+ , foreign_frame_frozen_(false)
528 , window_initial_width_(width)
529 , window_initial_height_(height)
530 , window_title_(WindowTitle)
531@@ -1389,6 +1392,58 @@
532 return m_dirty_areas;
533 }
534
535+ bool WindowThread::AddToPresentationList(BaseWindow *bw,
536+ bool force = false)
537+ {
538+ RequestRedraw();
539+ WindowCompositor::WeakBaseWindowPtr ptr (window_compositor_->FindWeakBaseWindowPtrForRawPtr(bw));
540+
541+ if (!ptr.IsValid())
542+ return false;
543+
544+ if (force ||
545+ !foreign_frame_frozen_)
546+ {
547+ if (std::find (m_presentation_list_embedded.begin(),
548+ m_presentation_list_embedded.end(),
549+ ptr) != m_presentation_list_embedded.end())
550+ return true;
551+
552+ m_presentation_list_embedded.push_back(ptr);
553+ return true;
554+ }
555+ else
556+ {
557+ if (std::find (m_presentation_list_embedded_next_frame.begin(),
558+ m_presentation_list_embedded_next_frame.end(),
559+ ptr) != m_presentation_list_embedded_next_frame.end())
560+ return false;
561+
562+ m_presentation_list_embedded_next_frame.push_back(ptr);
563+ return false;
564+ }
565+ }
566+
567+ std::vector<nux::Geometry> WindowThread::GetPresentationListGeometries()
568+ {
569+ std::vector<nux::Geometry> presentation_geometries;
570+ for (WindowCompositor::WeakBaseWindowPtr const& base_window : m_presentation_list_embedded)
571+ {
572+ if (base_window.IsValid())
573+ {
574+ nux::Geometry const& abs_geom (base_window->GetAbsoluteGeometry());
575+ nux::Geometry const& last_geom (base_window->LastPresentedGeometryInEmbeddedMode());
576+ presentation_geometries.push_back(abs_geom);
577+ if (abs_geom != last_geom)
578+ {
579+ if (!last_geom.IsNull())
580+ presentation_geometries.push_back(last_geom);
581+ }
582+ }
583+ }
584+ return presentation_geometries;
585+ }
586+
587 bool WindowThread::IsEmbeddedWindow()
588 {
589 return embedded_window_;
590@@ -1529,6 +1584,32 @@
591 return request_draw_cycle_to_host_wm;
592 }
593
594+ namespace {
595+
596+ void PresentOnBaseWindowIntersectsRect(ObjectWeakPtr<BaseWindow> const& w,
597+ Geometry const& rect)
598+ {
599+ Geometry inter = rect.Intersect(w->GetAbsoluteGeometry());
600+ if (!inter.IsNull())
601+ w->PresentInEmbeddedModeOnThisFrame(true);
602+ }
603+
604+ void MarkWindowUnpresented(const ObjectWeakPtr<BaseWindow> &w)
605+ {
606+ w->OnPresentedInEmbeddedMode();
607+ }
608+
609+ }
610+
611+ void WindowThread::PresentWindowsIntersectingGeometryOnThisFrame(const Geometry &rect)
612+ {
613+ using namespace std::placeholders;
614+ nuxAssertMsg(IsEmbeddedWindow(),
615+ "[WindowThread::PresentWindowIntersectingGeometryOnThisFrame] "
616+ "can only be called inside an embedded window");
617+ window_compositor_->OnAllBaseWindows(std::bind (PresentOnBaseWindowIntersectsRect, _1, rect));
618+ }
619+
620 void WindowThread::RenderInterfaceFromForeignCmd(Geometry *clip)
621 {
622 nuxAssertMsg(IsEmbeddedWindow() == true, "[WindowThread::RenderInterfaceFromForeignCmd] You can only call RenderInterfaceFromForeignCmd if the window was created with CreateFromForeignWindow.");
623@@ -1568,17 +1649,38 @@
624
625 CHECKGL( glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
626
627- graphics_display_->GetGpuDevice()->DeactivateFrameBuffer();
628 IOpenGLShaderProgram::SetShaderTracking(false);
629-
630- if (IsEmbeddedWindow() && window_compositor_->reference_fbo_)
631+ }
632+
633+ void WindowThread::ForeignFrameEnded()
634+ {
635+ using namespace std::placeholders;
636+ nuxAssertMsg(IsEmbeddedWindow(),
637+ "[WindowThread::ForeignFrameEnded] "
638+ "can only be called inside an embedded window");
639+ window_compositor_->OnAllBaseWindows(std::bind (MarkWindowUnpresented, _1));
640+ m_presentation_list_embedded.clear();
641+
642+ foreign_frame_frozen_ = false;
643+
644+ /* Move all the BaseWindows in m_presentation_list_embedded_next_frame
645+ * to m_presentation_list_embedded and mark them for presentation
646+ */
647+ for (std::vector<WindowCompositor::WeakBaseWindowPtr>::iterator it =
648+ m_presentation_list_embedded_next_frame.begin();
649+ it != m_presentation_list_embedded_next_frame.end();
650+ ++it)
651 {
652- // Restore the reference framebuffer
653- if (!window_compositor_->RestoreReferenceFramebuffer())
654- {
655- nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
656- }
657+ if (it->IsValid())
658+ (*it)->PresentInEmbeddedModeOnThisFrame();
659 }
660+
661+ m_presentation_list_embedded_next_frame.clear();
662+ }
663+
664+ void WindowThread::ForeignFrameCutoff()
665+ {
666+ foreign_frame_frozen_ = true;
667 }
668
669 int WindowThread::InstallEventInspector(EventInspector function, void* data)
670
671=== modified file 'Nux/WindowThread.h'
672--- Nux/WindowThread.h 2013-04-10 18:56:19 +0000
673+++ Nux/WindowThread.h 2013-05-08 10:59:39 +0000
674@@ -32,6 +32,7 @@
675 namespace nux
676 {
677
678+ class BaseWindow;
679 class WindowThread;
680 class Layout;
681 class HLayout;
682@@ -227,6 +228,17 @@
683 #endif
684
685 /*!
686+ In embedded mode, allow presentation on any windows intersecting this
687+ rect. The effect of this is culmulative for the frame, so it can be
688+ called multiple times with many different rects until
689+ RenderInterfaceFromForeignCmd is called.
690+ \sa IsEmbeddedWindow
691+
692+ @param rect Region of the display to consider for presenting windows
693+ */
694+ void PresentWindowsIntersectingGeometryOnThisFrame(const Geometry &rect);
695+
696+ /*!
697 Render the interface. This command is send from the pluging when the window thread is embedded.
698 The clip region matches the surface of one single monitor screen, or a region inside that screen.
699 \sa IsEmbeddedWindow.
700@@ -235,6 +247,19 @@
701 */
702 void RenderInterfaceFromForeignCmd(Geometry *clip);
703
704+ /*!
705+ Used to mark the end of the foreign frame. All calls to PresentInEmbeddedModeOnThisFrame
706+ are now redirected to this upcoming frame where we will be called next.
707+ */
708+ void ForeignFrameEnded();
709+
710+ /*!
711+ Used to mark the cutoff point where all calls to PresentInEmbeddedModeOnThisFrame
712+ should be effective on the next frame, and not this one, because the parent context
713+ has stopped tracking damage events for this frame
714+ */
715+ void ForeignFrameCutoff();
716+
717 #if !defined(NUX_MINIMAL)
718 /*!
719 Add a timeline to our window
720@@ -319,12 +344,19 @@
721
722 bool IsRedrawNeeded() const;
723
724+ // DrawList - this is a maintained list of areas that will
725+ // be completely redraw on the next frame
726 void AddToDrawList(View *view);
727-
728 void ClearDrawList();
729
730 std::vector<Geometry> const& GetDrawList() const;
731
732+ // PresentationList - this is a maintained list of areas that
733+ // will be presented to the reference framebuffer or backbuffer
734+ // in embedded mode on the next frame
735+ bool AddToPresentationList(nux::BaseWindow *, bool force);
736+ std::vector <Geometry> GetPresentationListGeometries();
737+
738 #ifdef NUX_GESTURES_SUPPORT
739 /*!
740 Simple wrapper for ProcessEvent for connection with GeisAdapter::event_ready
741@@ -544,6 +576,23 @@
742 std::list<Area *> _queued_layout_list;
743 std::vector<Geometry> m_dirty_areas;
744
745+ typedef nux::ObjectWeakPtr<nux::BaseWindow> WCWeakBaseWindowPtr;
746+
747+ std::vector<WCWeakBaseWindowPtr> m_presentation_list_embedded;
748+
749+ /*!
750+ This list contains al lthe windows which will be presented on the next frame
751+ (eg, after ForeignFrameEnded they are moved into m_presentation_list_embedded
752+ and marked for presentation)
753+ */
754+ std::vector<WCWeakBaseWindowPtr> m_presentation_list_embedded_next_frame;
755+
756+ /*! Whether or not the current frame is "frozen" because the host WM has stopped tracking
757+ damage events. If so we should put all presentation requests on the next frame instead
758+ of this one
759+ */
760+ bool foreign_frame_frozen_;
761+
762 //! This variable is true while we are computing the layout the starting from the outmost layout(the Main Layout);
763 bool _inside_layout_cycle;
764
765
766=== modified file 'NuxGraphics/GLDeviceFrameBufferObject.cpp'
767--- NuxGraphics/GLDeviceFrameBufferObject.cpp 2011-10-19 20:32:38 +0000
768+++ NuxGraphics/GLDeviceFrameBufferObject.cpp 2013-05-08 10:59:39 +0000
769@@ -65,12 +65,22 @@
770
771 void GLFramebufferObject::Bind()
772 {
773- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
774+#ifdef NUX_OPENGLES_20
775+ GLenum binding = GL_FRAMEBUFFER;
776+#else
777+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
778+#endif
779+ CHECKGL(glBindFramebufferEXT(binding, m_fboId));
780 }
781
782 void GLFramebufferObject::Disable()
783 {
784- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
785+#ifdef NUX_OPENGLES_20
786+ GLenum binding = GL_FRAMEBUFFER;
787+#else
788+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
789+#endif
790+ CHECKGL(glBindFramebufferEXT(binding, 0));
791 }
792
793 void
794@@ -170,11 +180,11 @@
795 {
796 #ifndef NUX_OPENGLES_20
797 // Only binds if m_fboId is different than the currently bound FBO
798- CHECKGL(glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ));
799+ CHECKGL(glGetIntegerv( GL_DRAW_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ));
800
801 if (m_fboId != m_savedFboId)
802 {
803- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
804+ CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fboId));
805 }
806 #else
807 // Only binds if m_fboId is different than the currently bound FBO
808@@ -189,10 +199,15 @@
809
810 void GLFramebufferObject::_GuardedUnbind()
811 {
812+#ifdef NUX_OPENGLES_20
813+ GLenum binding = GL_FRAMEBUFFER;
814+#else
815+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
816+#endif
817 // Returns FBO binding to the previously enabled FBO
818 if (m_savedFboId != m_fboId)
819 {
820- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint) m_savedFboId));
821+ CHECKGL(glBindFramebufferEXT(binding, (GLuint) m_savedFboId));
822 }
823 }
824
825
826=== modified file 'NuxGraphics/GpuDevice.cpp'
827--- NuxGraphics/GpuDevice.cpp 2013-05-01 18:12:51 +0000
828+++ NuxGraphics/GpuDevice.cpp 2013-05-08 10:59:39 +0000
829@@ -1069,8 +1069,14 @@
830 return;
831 }
832
833+#ifdef NUX_OPENGLES_20
834+ GLenum binding = GL_FRAMEBUFFER;
835+#else
836+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
837+#endif
838+
839 active_framebuffer_object_.Release();
840- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
841+ CHECKGL(glBindFramebufferEXT(binding, 0));
842 CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
843 }
844
845
846=== modified file 'NuxGraphics/GpuDeviceTexture.cpp'
847--- NuxGraphics/GpuDeviceTexture.cpp 2012-11-16 19:11:05 +0000
848+++ NuxGraphics/GpuDeviceTexture.cpp 2013-05-08 10:59:39 +0000
849@@ -73,7 +73,7 @@
850 return result;
851 }
852
853- ObjectPtr<IOpenGLTexture2D> GpuDevice::CreateTexture2DFromID(int /* id */
854+ ObjectPtr<IOpenGLTexture2D> GpuDevice::CreateTexture2DFromID(int id
855 , int width
856 , int height
857 , int levels
858@@ -95,6 +95,12 @@
859
860 ObjectPtr<IOpenGLTexture2D> result;
861 result.Adopt(new IOpenGLTexture2D(width, height, levels, pixel_format, true, NUX_FILE_LINE_PARAM));
862+
863+ /* Assign the external id to the internal id. This allows us
864+ * to use the foreign texture as if it were a native one.
865+ *
866+ * This is really important. Don't remove it */
867+ result->_OpenGLID = id;
868 return result;
869 }
870
871
872=== modified file 'NuxGraphics/IOpenGLFrameBufferObject.cpp'
873--- NuxGraphics/IOpenGLFrameBufferObject.cpp 2013-05-01 18:13:16 +0000
874+++ NuxGraphics/IOpenGLFrameBufferObject.cpp 2013-05-08 10:59:39 +0000
875@@ -336,7 +336,13 @@
876 // Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil).
877 int IOpenGLFrameBufferObject::Deactivate()
878 {
879- CHECKGL(glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ));
880+#ifdef NUX_OPENGLES_20
881+ GLenum binding = GL_FRAMEBUFFER;
882+#else
883+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
884+#endif
885+
886+ CHECKGL(glBindFramebufferEXT( binding, 0 ));
887
888 #ifndef NUX_OPENGLES_20
889 CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
890
891=== modified file 'configure.ac'
892--- configure.ac 2013-04-10 22:42:34 +0000
893+++ configure.ac 2013-05-08 10:59:39 +0000
894@@ -23,7 +23,7 @@
895 # e.g.: december 5th, 2011 is: 20111205
896 # To make more than one API change in a day, add a number to the date. Like 20111205.xx
897
898-m4_define([nux_abi_version], [20130411.0])
899+m4_define([nux_abi_version], [20130414.0])
900
901 m4_define([nux_version],
902 [nux_major_version.nux_minor_version.nux_micro_version])
903
904=== modified file 'tests/gtest-nux-windowcompositor.cpp'
905--- tests/gtest-nux-windowcompositor.cpp 2012-11-19 22:24:05 +0000
906+++ tests/gtest-nux-windowcompositor.cpp 2013-05-08 10:59:39 +0000
907@@ -53,6 +53,7 @@
908 TestBaseWindow() : input_area(new nux::InputArea())
909 {
910 ShowWindow(true);
911+ EnableInputWindow(true);
912 }
913
914 nux::Area* FindAreaUnderMouse(const nux::Point& /* mouse_position */, nux::NuxEventType /* event_type */)
915@@ -145,82 +146,147 @@
916
917 namespace
918 {
919+ typedef void (*NGLGenFramebuffers) (GLsizei, GLuint *);
920+ typedef void (*NGLGenRenderbuffers) (GLsizei, GLuint *);
921+ typedef void (*NGLBindFramebuffer) (GLenum, GLuint);
922+ typedef void (*NGLBindRenderbuffer) (GLenum, GLuint);
923+ typedef void (*NGLRenderbufferStorage) (GLenum, GLenum, GLsizei, GLsizei);
924+ typedef void (*NGLFramebufferRenderbuffer) (GLenum, GLenum, GLenum, GLuint);
925+ typedef void (*NGLDeleteFramebuffers) (GLsizei, const GLuint *);
926+ typedef void (*NGLDeleteRenderbuffers) (GLsizei, const GLuint *);
927+
928+ #ifdef NUX_OPENGLES_20
929+ GLuint NGL_RENDERBUFFER = GL_RENDERBUFFER;
930+ /* No separate draw or read targets on OpenGL|ES */
931+ GLuint NGL_DRAW_FRAMEBUFFER = GL_FRAMEBUFFER;
932+ GLuint NGL_READ_FRAMEBUFFER = GL_FRAMEBUFFER;
933+ GLuint NGL_DRAW_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING;
934+ GLuint NGL_READ_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING;
935+ GLuint NGL_COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0;
936+ GLuint NGL_RGBA_STORAGE = GL_RGBA4;
937+ #else
938+ GLuint NGL_RENDERBUFFER = GL_RENDERBUFFER_EXT;
939+ GLuint NGL_DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER_EXT;
940+ GLuint NGL_READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER_EXT;
941+ GLuint NGL_DRAW_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING_EXT;
942+ GLuint NGL_READ_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING_EXT;
943+ GLuint NGL_COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0_EXT;
944+ GLuint NGL_RGBA_STORAGE = GL_RGBA8_EXT;
945+ #endif
946+
947 class ReferenceFramebuffer
948 {
949 public:
950
951 ReferenceFramebuffer ()
952 {
953- glGenFramebuffersEXT (1, &fboName);
954- glGenRenderbuffersEXT (1, &rbName);
955-
956- glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, rbName);
957- glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_RGBA8_EXT, 300, 200);
958- glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fboName);
959- glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rbName);
960+ #ifdef NUX_OPENGLES_20
961+ nglGenFramebuffers = &glGenFramebuffers;
962+ nglGenRenderbuffers = &glGenRenderbuffers;
963+ nglBindRenderbuffer = &glBindRenderbuffer;
964+ nglBindFramebuffer = &glBindFramebuffer;
965+ nglRenderbufferStorage = &glRenderbufferStorage;
966+ nglFramebufferRenderbuffer = &glFramebufferRenderbuffer;
967+ nglDeleteRenderbuffers = &glDeleteRenderbuffers;
968+ nglDeleteFramebuffers = &glDeleteFramebuffers;
969+ #else
970+ nglGenFramebuffers = glGenFramebuffersEXT;
971+ nglGenRenderbuffers = glGenRenderbuffersEXT;
972+ nglBindRenderbuffer = glBindRenderbufferEXT;
973+ nglBindFramebuffer = glBindFramebufferEXT;
974+ nglRenderbufferStorage = glRenderbufferStorageEXT;
975+ nglFramebufferRenderbuffer = glFramebufferRenderbufferEXT;
976+ nglDeleteRenderbuffers = glDeleteRenderbuffersEXT;
977+ nglDeleteFramebuffers = glDeleteFramebuffersEXT;
978+ #endif
979+
980+ nglGenFramebuffers (1, &fboName);
981+ nglGenRenderbuffers (1, &rbName);
982+
983+ nglBindRenderbuffer (NGL_RENDERBUFFER, rbName);
984+ nglRenderbufferStorage (NGL_RENDERBUFFER, NGL_RGBA_STORAGE, 300, 200);
985+ nglBindFramebuffer (NGL_DRAW_FRAMEBUFFER, fboName);
986+ nglBindFramebuffer (NGL_READ_FRAMEBUFFER, fboName);
987+ nglFramebufferRenderbuffer (NGL_DRAW_FRAMEBUFFER, NGL_COLOR_ATTACHMENT0, NGL_RENDERBUFFER, rbName);
988 }
989
990 ~ReferenceFramebuffer ()
991 {
992- glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
993- glDeleteRenderbuffers (1, &rbName);
994- glDeleteRenderbuffers (1, &fboName);
995+ nglBindFramebuffer (NGL_DRAW_FRAMEBUFFER, 0);
996+ nglBindFramebuffer (NGL_READ_FRAMEBUFFER, 0);
997+ nglDeleteRenderbuffers (1, &rbName);
998+ nglDeleteFramebuffers (1, &fboName);
999 }
1000
1001- GLuint fboName, rbName;
1002+ GLuint fboName, rbName;
1003+
1004+ /* Each instance of the class needs to keep its own
1005+ * copy of the extension functions as glewInit () needs
1006+ * to be called in the desktop case before they are available */
1007+
1008+ NGLGenFramebuffers nglGenFramebuffers;
1009+ NGLGenRenderbuffers nglGenRenderbuffers;
1010+ NGLBindRenderbuffer nglBindRenderbuffer;
1011+ NGLBindFramebuffer nglBindFramebuffer;
1012+ NGLRenderbufferStorage nglRenderbufferStorage;
1013+ NGLFramebufferRenderbuffer nglFramebufferRenderbuffer;
1014+ NGLDeleteRenderbuffers nglDeleteRenderbuffers;
1015+ NGLDeleteFramebuffers nglDeleteFramebuffers;
1016 };
1017 }
1018+
1019 TEST_F(TestWindowCompositor, TestRestoreReferenceFramebufferDirect)
1020 {
1021 ReferenceFramebuffer reference;
1022- GLint fbBinding;
1023-
1024- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1025-
1026- ASSERT_EQ (fbBinding, reference.fboName);
1027-
1028- wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(fbBinding, nux::Geometry (0, 0, 300, 200));
1029+ GLint dfbBinding, rfbBinding;
1030+
1031+ glGetIntegerv (NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1032+ glGetIntegerv (NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1033+
1034+ ASSERT_EQ (dfbBinding, reference.fboName);
1035+
1036+ wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(dfbBinding, rfbBinding, nux::Geometry (0, 0, 300, 200));
1037
1038 ASSERT_TRUE (wnd_thread->GetWindowCompositor().RestoreReferenceFramebuffer());
1039- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1040- ASSERT_EQ (fbBinding, reference.fboName);
1041+ glGetIntegerv (NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1042+ glGetIntegerv (NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1043+ ASSERT_EQ (dfbBinding, reference.fboName);
1044+ ASSERT_EQ (rfbBinding, reference.fboName);
1045 }
1046
1047 TEST_F(TestWindowCompositor, TestRestoreReferenceFramebufferThroughRestoreMain)
1048 {
1049 ReferenceFramebuffer reference;
1050- GLint fbBinding;
1051-
1052- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1053-
1054- ASSERT_EQ (fbBinding, reference.fboName);
1055-
1056- wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(fbBinding, nux::Geometry (0, 0, 300, 200));
1057+ GLint dfbBinding, rfbBinding;
1058+
1059+ glGetIntegerv (NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1060+ glGetIntegerv (NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1061+
1062+ ASSERT_EQ (dfbBinding, reference.fboName);
1063+
1064+ wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(dfbBinding, rfbBinding, nux::Geometry (0, 0, 300, 200));
1065 wnd_thread->GetWindowCompositor().RestoreMainFramebuffer();
1066- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1067- ASSERT_EQ (fbBinding, reference.fboName);
1068-}
1069-
1070-TEST_F(TestWindowCompositor, TestNoRestoreReferenceFramebufferDirectIfNoReferenceFramebuffer)
1071-{
1072- GLint fbBinding;
1073- ASSERT_FALSE (wnd_thread->GetWindowCompositor().RestoreReferenceFramebuffer());
1074- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1075- ASSERT_EQ (fbBinding, 0);
1076+ glGetIntegerv (NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1077+ glGetIntegerv (NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1078+ ASSERT_EQ (dfbBinding, reference.fboName);
1079+ ASSERT_EQ (rfbBinding, reference.fboName);
1080 }
1081
1082 TEST_F(TestWindowCompositor, TestRestoreBackbufferThroughRestoreMain)
1083 {
1084 ReferenceFramebuffer reference;
1085- GLint fbBinding;
1086-
1087- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1088-
1089- ASSERT_EQ (fbBinding, reference.fboName);
1090+ GLint dfbBinding, rfbBinding;
1091+
1092+ glGetIntegerv (NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1093+ glGetIntegerv (NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1094+
1095+ ASSERT_EQ (dfbBinding, reference.fboName);
1096
1097 wnd_thread->GetWindowCompositor().RestoreMainFramebuffer();
1098- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1099- ASSERT_EQ (fbBinding, 0);
1100+ glGetIntegerv (NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1101+ glGetIntegerv (NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1102+ ASSERT_EQ (dfbBinding, 0);
1103+ ASSERT_EQ (rfbBinding, 0);
1104 }
1105
1106 TEST_F(TestWindowCompositor, TestSetKeyFocusArea)
1107
1108=== modified file 'tests/gtest-nux-windowthread.cpp'
1109--- tests/gtest-nux-windowthread.cpp 2013-02-01 09:14:07 +0000
1110+++ tests/gtest-nux-windowthread.cpp 2013-05-08 10:59:39 +0000
1111@@ -8,17 +8,36 @@
1112 #include <string>
1113 #include <fstream>
1114
1115+#include <memory>
1116 #include <iostream>
1117 #include <gmock/gmock.h>
1118 #include <boost/filesystem.hpp>
1119 #include <glib.h>
1120
1121+#include <X11/X.h>
1122+
1123 #include "Nux/Nux.h"
1124+#include "Nux/View.h"
1125+#include "Nux/HLayout.h"
1126+#include "Nux/ProgramFramework/TestView.h"
1127
1128
1129 using namespace testing;
1130 using ::testing::Invoke;
1131
1132+namespace nux {
1133+ std::ostream &
1134+ operator<< (std::ostream &os, const Geometry &geo)
1135+ {
1136+ return os << "Geometry: x: " <<
1137+ geo.x << " y: " <<
1138+ geo.y << " width: " <<
1139+ geo.width << " height: " <<
1140+ geo.height << std::endl;
1141+
1142+ }
1143+}
1144+
1145 namespace {
1146
1147 class MockFdDispatch
1148@@ -278,5 +297,482 @@
1149 close (pipefd2[1]);
1150 }
1151
1152+class EmbeddedContext : public ::testing::Test
1153+{
1154+ public:
1155+
1156+ EmbeddedContext()
1157+ : _display (XOpenDisplay(NULL))
1158+ , _root (DefaultRootWindow(_display))
1159+ , _window (XCreateSimpleWindow(_display,
1160+ _root,
1161+ 0,
1162+ 0,
1163+ 300,
1164+ 200,
1165+ 0,
1166+ 0,
1167+ 0))
1168+ , _visinfo (NULL)
1169+ , _context (NULL)
1170+ {
1171+ XVisualInfo temp;
1172+ XWindowAttributes attrib;
1173+ if (!XGetWindowAttributes (_display, _window, &attrib))
1174+ throw std::runtime_error ("failed to get window attributes");
1175+
1176+ temp.visualid = XVisualIDFromVisual (attrib.visual);
1177+
1178+ int nvinfo = 0;
1179+ _visinfo = XGetVisualInfo (_display, VisualIDMask, &temp, &nvinfo);
1180+
1181+ if (!_visinfo || !nvinfo)
1182+ throw std::runtime_error ("failed to find visual");
1183+
1184+#ifndef NUX_OPENGLES_20
1185+ GLint value = 0;
1186+ glXGetConfig (_display, _visinfo, GLX_USE_GL, &value);
1187+
1188+ if (!value)
1189+ std::runtime_error ("available visual is not a gl visual");
1190+
1191+ _context = glXCreateContext(_display, _visinfo, NULL, true);
1192+ glXMakeCurrent(_display, _window, _context);
1193+#else
1194+ EGLDisplay eglDisplay = eglGetDisplay ((EGLNativeDisplayType)_display);
1195+ EGLint major, minor;
1196+ if (!eglInitialize (eglDisplay, &major, &minor))
1197+ throw std::runtime_error ("eglInitialize failed");
1198+
1199+ const EGLint config_attribs[] = {
1200+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1201+ EGL_RED_SIZE, 1,
1202+ EGL_GREEN_SIZE, 1,
1203+ EGL_BLUE_SIZE, 1,
1204+ EGL_ALPHA_SIZE, 0,
1205+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1206+ EGL_CONFIG_CAVEAT, EGL_NONE,
1207+ EGL_STENCIL_SIZE, 1,
1208+ EGL_NONE
1209+ };
1210+
1211+ const EGLint context_attribs[] = {
1212+ EGL_CONTEXT_CLIENT_VERSION, 2,
1213+ EGL_NONE
1214+ };
1215+
1216+ EGLint count, visualid;
1217+ EGLConfig configs[1024];
1218+
1219+ if (!eglChooseConfig (eglDisplay, config_attribs, configs, 1024, &count))
1220+ throw std::runtime_error("eglChooseConfig failed");
1221+
1222+ visualid = temp.visualid;
1223+ EGLConfig config = configs[0];
1224+
1225+ for (int i = 0; i < count; ++i)
1226+ {
1227+ EGLint val;
1228+ eglGetConfigAttrib (eglDisplay, configs[i], EGL_NATIVE_VISUAL_ID, &val);
1229+ if (visualid == val)
1230+ {
1231+ config = configs[i];
1232+ break;
1233+ }
1234+ }
1235+
1236+ eglBindAPI (EGL_OPENGL_ES_API);
1237+ _surface = eglCreateWindowSurface(eglDisplay, config, _window, 0);
1238+ if (_surface == EGL_NO_SURFACE)
1239+ throw std::runtime_error ("eglCreateWindowSurface failed");
1240+
1241+ _context = eglCreateContext (eglDisplay, config, EGL_NO_CONTEXT, context_attribs);
1242+ if (_context == EGL_NO_CONTEXT)
1243+ throw std::runtime_error ("eglCreateContext failed");
1244+
1245+ if (!eglMakeCurrent (eglDisplay, _surface, _surface, _context))
1246+ throw std::runtime_error ("eglMakeCurrent failed");
1247+#endif
1248+ }
1249+
1250+ MOCK_METHOD0(verifyInit, void());
1251+
1252+ static void nuxInitThreadEntry(nux::NThread *, void *user_data)
1253+ {
1254+ EmbeddedContext *context = reinterpret_cast <EmbeddedContext *> (user_data);
1255+ context->verifyInit();
1256+ }
1257+
1258+ void SetUp ()
1259+ {
1260+ EXPECT_CALL(*this, verifyInit());
1261+ nux::NuxInitialize(0);
1262+ _window_thread.reset(nux::CreateFromForeignWindow(_window,
1263+ _context,
1264+ EmbeddedContext::nuxInitThreadEntry,
1265+ this));
1266+ _window_thread->Run(NULL);
1267+ while (g_main_context_iteration(g_main_context_default(), false));
1268+ }
1269+
1270+ ~EmbeddedContext ()
1271+ {
1272+#ifndef NUX_OPENGLES_20
1273+ glXDestroyContext(_display, _context);
1274+#else
1275+ EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display);
1276+ eglDestroyContext(eglDisplay, _context);
1277+ eglDestroySurface(eglDisplay, _surface);
1278+ eglTerminate(eglDisplay);
1279+#endif
1280+ XDestroyWindow (_display, _window);
1281+ XCloseDisplay (_display);
1282+ }
1283+
1284+ const std::shared_ptr <nux::WindowThread> &
1285+ WindowThread () const
1286+ {
1287+ return _window_thread;
1288+ }
1289+
1290+ private:
1291+
1292+ Display *_display;
1293+ Window _root;
1294+ Window _window;
1295+ XVisualInfo *_visinfo;
1296+#ifndef NUX_OPENGLES_20
1297+ GLXContext _context;
1298+#else
1299+ EGLSurface _surface;
1300+ EGLContext _context;
1301+#endif
1302+
1303+ std::shared_ptr <nux::WindowThread> _window_thread;
1304+};
1305+
1306+TEST_F(EmbeddedContext, WindowThreadIsEmbedded)
1307+{
1308+ EXPECT_TRUE(WindowThread()->IsEmbeddedWindow());
1309+}
1310+
1311+/* There's not a whole lot we can do to test this at the moment
1312+ * since we can't really mock out the behaviour of GraphicsEngine
1313+ */
1314+TEST_F(EmbeddedContext, PresentViewInEmbeddedReadiesForPresentation)
1315+{
1316+ nux::ObjectPtr <nux::BaseWindow> bw(new nux::BaseWindow(TEXT("")));
1317+ bw->ShowWindow(true, false);
1318+ WindowThread()->ForeignFrameEnded();
1319+ bw->PresentInEmbeddedModeOnThisFrame();
1320+ EXPECT_TRUE(bw->AllowPresentationInEmbeddedMode());
1321+}
1322+
1323+TEST_F(EmbeddedContext, QueueDrawOnChildInEmbeddedReadiesForPresentation)
1324+{
1325+ nux::ObjectPtr <nux::BaseWindow> bw(new nux::BaseWindow(TEXT("")));
1326+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1327+ nux::View* view = new nux::TestView("");
1328+ layout->AddView(view, 1);
1329+ bw->SetLayout(layout);
1330+ bw->ShowWindow(true, false);
1331+
1332+ /* Draw command is implicitly queued by ShowWindow, remove it */
1333+ view->DoneRedraw();
1334+ WindowThread()->ForeignFrameEnded();
1335+
1336+ view->QueueDraw();
1337+ EXPECT_TRUE(bw->AllowPresentationInEmbeddedMode());
1338+}
1339+
1340+TEST_F(EmbeddedContext, DonePresentViewInEmbeddedMode)
1341+{
1342+ nux::ObjectPtr <nux::BaseWindow> bw(new nux::BaseWindow(TEXT("")));
1343+ bw->PresentInEmbeddedModeOnThisFrame();
1344+ bw->OnPresentedInEmbeddedMode();
1345+ EXPECT_FALSE(bw->AllowPresentationInEmbeddedMode());
1346+}
1347+
1348+TEST_F(EmbeddedContext, NoPresentInvisibleOnQueueDraw)
1349+{
1350+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
1351+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1352+ nux::View* view = new nux::TestView("");
1353+ layout->AddView(view, 1);
1354+ window->SetLayout(layout);
1355+ window->ShowWindow(false);
1356+ view->QueueDraw();
1357+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
1358+}
1359+
1360+TEST_F(EmbeddedContext, NoPresentInvisible)
1361+{
1362+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
1363+ window->ShowWindow(false);
1364+ window->PresentInEmbeddedModeOnThisFrame();
1365+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
1366+}
1367+
1368+TEST_F(EmbeddedContext, AllowPresentationSubsequentQueueDraw)
1369+{
1370+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
1371+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1372+ nux::View* view = new nux::TestView("");
1373+ layout->AddView(view, 1);
1374+ window->SetLayout(layout);
1375+
1376+ /* This will call QueueDraw initially and attempt to add
1377+ * the window to the presentation list */
1378+ window->SetGeometry(nux::Geometry(0, 0, 100, 100));
1379+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
1380+
1381+ /* This will call it again */
1382+ window->ShowWindow(true);
1383+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
1384+}
1385+
1386+TEST_F(EmbeddedContext, StillProcessDrawIfInvisible)
1387+{
1388+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
1389+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1390+ nux::View* view = new nux::TestView("");
1391+ layout->AddView(view, 1);
1392+ window->SetLayout(layout);
1393+ window->ShowWindow(false);
1394+ view->QueueDraw();
1395+ nux::Geometry clip(0, 0, 100, 100);
1396+ WindowThread()->RenderInterfaceFromForeignCmd(&clip);
1397+ EXPECT_FALSE(view->IsRedrawNeeded());
1398+}
1399+
1400+class EmbeddedContextWindow : public EmbeddedContext
1401+{
1402+ public:
1403+
1404+ virtual void SetUp ()
1405+ {
1406+ EmbeddedContext::SetUp();
1407+ _base_window = nux::ObjectPtr<nux::BaseWindow> (new nux::BaseWindow(TEXT("")));
1408+ _base_window->ShowWindow(true, false);
1409+
1410+ /* QueueDraw will call PresentInEmbeddedModeOnThisFrame - we
1411+ * need to unset this state in order to test it properly */
1412+ _base_window->OnPresentedInEmbeddedMode();
1413+ _base_window->DoneRedraw();
1414+ }
1415+
1416+ virtual nux::ObjectPtr <nux::BaseWindow> const &
1417+ Window()
1418+ {
1419+ return _base_window;
1420+ }
1421+
1422+ private:
1423+
1424+ nux::ObjectPtr <nux::BaseWindow> _base_window;
1425+};
1426+
1427+class RedrawRequestVerification
1428+{
1429+ public:
1430+
1431+ MOCK_METHOD0(RedrawRequested, void());
1432+};
1433+
1434+TEST_F(EmbeddedContextWindow, AllowPresentationRequestsRedraw)
1435+{
1436+ RedrawRequestVerification verification;
1437+
1438+ EXPECT_CALL (verification, RedrawRequested());
1439+ WindowThread()->RedrawRequested.connect (sigc::mem_fun (&verification,
1440+ &RedrawRequestVerification::RedrawRequested));
1441+ Window()->PresentInEmbeddedModeOnThisFrame();
1442+}
1443+
1444+TEST_F(EmbeddedContextWindow, AllowPresentationAddsToPresentationList)
1445+{
1446+ Window()->PresentInEmbeddedModeOnThisFrame();
1447+ std::vector <nux::Geometry> present_list (WindowThread()->GetPresentationListGeometries());
1448+
1449+ ASSERT_EQ(1, present_list.size());
1450+ EXPECT_EQ (present_list[0], Window()->GetAbsoluteGeometry());
1451+}
1452+
1453+TEST_F(EmbeddedContextWindow, MultipleAllowPresentationAddsToPresentationListUnique)
1454+{
1455+ Window()->PresentInEmbeddedModeOnThisFrame();
1456+ Window()->PresentInEmbeddedModeOnThisFrame();
1457+ std::vector <nux::Geometry> present_list (WindowThread()->GetPresentationListGeometries());
1458+
1459+ ASSERT_EQ(1, present_list.size());
1460+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
1461+}
1462+
1463+TEST_F(EmbeddedContextWindow, OneSetOfGeometryForRePresentOnUnchangedPosition)
1464+{
1465+ Window()->PresentInEmbeddedModeOnThisFrame();
1466+ Window()->OnPresentedInEmbeddedMode();
1467+ Window()->PresentInEmbeddedModeOnThisFrame();
1468+ std::vector <nux::Geometry> present_list (WindowThread()->GetPresentationListGeometries());
1469+
1470+ ASSERT_EQ(1, present_list.size());
1471+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
1472+}
1473+
1474+TEST_F(EmbeddedContextWindow, TwoSetsOfGeometryForRePresentOnChangedPosition)
1475+{
1476+ Window()->PresentInEmbeddedModeOnThisFrame();
1477+ Window()->OnPresentedInEmbeddedMode();
1478+ Window()->PresentInEmbeddedModeOnThisFrame();
1479+ Window()->SetBaseX(Window()->GetBaseX() + 1);
1480+ std::vector <nux::Geometry> present_list (WindowThread()->GetPresentationListGeometries());
1481+
1482+ ASSERT_EQ(2, present_list.size());
1483+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
1484+ EXPECT_EQ(present_list[1], Window()->LastPresentedGeometryInEmbeddedMode());
1485+}
1486+
1487+TEST_F(EmbeddedContextWindow, QueueDrawAddsParentToPresentationList)
1488+{
1489+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1490+ nux::View* view = new nux::TestView("");
1491+ layout->AddView(view, 1);
1492+ Window()->SetLayout(layout);
1493+ view->QueueDraw();
1494+ std::vector <nux::Geometry> present_list (WindowThread()->GetPresentationListGeometries());
1495+
1496+ ASSERT_EQ(1, present_list.size());
1497+ EXPECT_EQ (present_list[0], Window()->GetAbsoluteGeometry());
1498+}
1499+
1500+class EmbeddedContextMultiWindow : public EmbeddedContext
1501+{
1502+ public:
1503+
1504+ virtual void SetUp ()
1505+ {
1506+ EmbeddedContext::SetUp();
1507+ }
1508+
1509+ const nux::ObjectPtr<nux::BaseWindow> & SpawnWindow()
1510+ {
1511+ _base_windows.push_back(nux::ObjectPtr<nux::BaseWindow> (new nux::BaseWindow(TEXT(""))));
1512+ _base_windows.back()->ShowWindow(true, false);
1513+
1514+ /* QueueDraw will call PresentInEmbeddedModeOnThisFrame - we
1515+ * need to unset this state in order to test it properly */
1516+ _base_windows.back()->OnPresentedInEmbeddedMode();
1517+ return _base_windows.back();
1518+ }
1519+
1520+ virtual std::vector <nux::ObjectPtr <nux::BaseWindow> > const &
1521+ Windows()
1522+ {
1523+ return _base_windows;
1524+ }
1525+
1526+ private:
1527+
1528+ std::vector <nux::ObjectPtr <nux::BaseWindow> > _base_windows;
1529+};
1530+
1531+TEST_F(EmbeddedContextMultiWindow, PresentIfIntersectsRectOneWindow)
1532+{
1533+ nux::Geometry geo (0, 0, 100, 100);
1534+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
1535+ window->SetGeometry(geo);
1536+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
1537+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
1538+}
1539+
1540+TEST_F(EmbeddedContextMultiWindow, PresentOnlyOneWindow)
1541+{
1542+ nux::Geometry geo (0, 0, 100, 100);
1543+ nux::Geometry outside_geo (0, 101, 100, 100);
1544+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
1545+ nux::ObjectPtr<nux::BaseWindow> outside(SpawnWindow());
1546+ window->SetGeometry(geo);
1547+ outside->SetGeometry(outside_geo);
1548+
1549+ /* Call ForeignFrameEnded to clear the presentation list set up
1550+ * by making windows visible */
1551+ WindowThread()->ForeignFrameEnded();
1552+
1553+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
1554+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
1555+ EXPECT_FALSE(outside->AllowPresentationInEmbeddedMode());
1556+}
1557+
1558+TEST_F(EmbeddedContextMultiWindow, PresentBoth)
1559+{
1560+ nux::Geometry geo (0, 0, 100, 101);
1561+ nux::Geometry other_geo (0, 100, 100, 100);
1562+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
1563+ nux::ObjectPtr<nux::BaseWindow> other(SpawnWindow());
1564+ window->SetGeometry(geo);
1565+ other->SetGeometry(other_geo);
1566+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
1567+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
1568+ EXPECT_TRUE(other->AllowPresentationInEmbeddedMode());
1569+}
1570+
1571+TEST_F(EmbeddedContextMultiWindow, ForeignFrameEndedPresentNone)
1572+{
1573+ nux::Geometry geo (0, 0, 100, 100);
1574+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
1575+ window->SetGeometry(geo);
1576+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
1577+ WindowThread()->ForeignFrameEnded();
1578+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
1579+ EXPECT_TRUE(WindowThread()->GetPresentationListGeometries().empty());
1580+}
1581+
1582+TEST_F(EmbeddedContextMultiWindow, AddToPresentationListFailsAfterCutoff)
1583+{
1584+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
1585+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
1586+ WindowThread()->ForeignFrameEnded();
1587+ EXPECT_TRUE(WindowThread()->AddToPresentationList(windowOne.GetPointer(), false));
1588+ WindowThread()->ForeignFrameCutoff();
1589+ EXPECT_FALSE(WindowThread()->AddToPresentationList(windowTwo.GetPointer(), false));
1590+}
1591+
1592+TEST_F(EmbeddedContextMultiWindow, NoPresentInEmbeddedOnThisFrameAfterFrameCutoff)
1593+{
1594+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
1595+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
1596+ WindowThread()->ForeignFrameEnded();
1597+ windowOne->PresentInEmbeddedModeOnThisFrame();
1598+ WindowThread()->ForeignFrameCutoff();
1599+ windowTwo->PresentInEmbeddedModeOnThisFrame();
1600+ EXPECT_TRUE(windowOne->AllowPresentationInEmbeddedMode());
1601+ EXPECT_FALSE(windowTwo->AllowPresentationInEmbeddedMode());
1602+}
1603+
1604+TEST_F(EmbeddedContextMultiWindow, PresentInEmbeddedOnThisFrameAfterFrameCutoffIfForced)
1605+{
1606+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
1607+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
1608+ WindowThread()->ForeignFrameEnded();
1609+ windowOne->PresentInEmbeddedModeOnThisFrame();
1610+ WindowThread()->ForeignFrameCutoff();
1611+ windowTwo->PresentInEmbeddedModeOnThisFrame(true);
1612+ EXPECT_TRUE(windowOne->AllowPresentationInEmbeddedMode());
1613+ EXPECT_TRUE(windowTwo->AllowPresentationInEmbeddedMode());
1614+}
1615+
1616+TEST_F(EmbeddedContextMultiWindow, MoveToPresentationListAfterFrameEndedIfCaughtInCutoff)
1617+{
1618+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
1619+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
1620+ WindowThread()->ForeignFrameEnded();
1621+ windowOne->PresentInEmbeddedModeOnThisFrame();
1622+ WindowThread()->ForeignFrameCutoff();
1623+ windowTwo->PresentInEmbeddedModeOnThisFrame();
1624+ WindowThread()->ForeignFrameEnded();
1625+ EXPECT_FALSE(windowOne->AllowPresentationInEmbeddedMode());
1626+ EXPECT_TRUE(windowTwo->AllowPresentationInEmbeddedMode());
1627+}
1628+
1629
1630 }
1631
1632=== modified file 'tests/gtest-nuxgraphics-texture.cpp'
1633--- tests/gtest-nuxgraphics-texture.cpp 2012-12-03 11:44:26 +0000
1634+++ tests/gtest-nuxgraphics-texture.cpp 2013-05-08 10:59:39 +0000
1635@@ -52,4 +52,20 @@
1636 }
1637 }
1638
1639-}
1640\ No newline at end of file
1641+TEST_F(TestTextures, TestCreateTexture2DFromIDAssignemnt)
1642+{
1643+ GLuint texid;
1644+ glGenTextures(1, &texid);
1645+ glBindTexture(GL_TEXTURE_2D, texid);
1646+ nux::ObjectPtr<nux::IOpenGLTexture2D> foreign_texture_as_nux_texture
1647+ (nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(
1648+ texid,
1649+ 1, 1,
1650+ 0,
1651+ nux::BITFMT_B8G8R8A8));
1652+ EXPECT_EQ (texid, foreign_texture_as_nux_texture->GetOpenGLID());
1653+ glBindTexture(GL_TEXTURE_2D, 0);
1654+ glDeleteTextures(1, &texid);
1655+}
1656+
1657+}

Subscribers

People subscribed via source and target branches