Nux

Merge lp:~unity-team/nux/nux.fix_1091589.1 into lp:nux

Proposed by Christopher Townsend
Status: Merged
Approved by: Stephen M. Webb
Approved revision: 819
Merged at revision: 828
Proposed branch: lp:~unity-team/nux/nux.fix_1091589.1
Merge into: lp:nux
Diff against target: 2558 lines (+1220/-264)
24 files modified
Nux/Area.cpp (+5/-6)
Nux/BaseWindow.cpp (+41/-0)
Nux/BaseWindow.h (+15/-0)
Nux/GridHLayout.cpp (+1/-4)
Nux/GridVLayout.cpp (+3/-10)
Nux/View.cpp (+7/-4)
Nux/WindowCompositor.cpp (+243/-97)
Nux/WindowCompositor.h (+25/-12)
Nux/WindowThread.cpp (+101/-31)
Nux/WindowThread.h (+54/-4)
NuxCore/Rect.cpp (+20/-12)
NuxCore/Rect.h (+4/-0)
NuxGraphics/GLDeviceFrameBufferObject.cpp (+20/-5)
NuxGraphics/GpuDevice.cpp (+7/-1)
NuxGraphics/GpuDeviceTexture.cpp (+7/-1)
NuxGraphics/GraphicsEngine.cpp (+14/-14)
NuxGraphics/GraphicsEngine.h (+5/-5)
NuxGraphics/IOpenGLFrameBufferObject.cpp (+14/-8)
NuxGraphics/IOpenGLFrameBufferObject.h (+1/-1)
configure.ac (+2/-3)
debian/changelog (+7/-0)
tests/gtest-nux-windowcompositor.cpp (+109/-44)
tests/gtest-nux-windowthread.cpp (+498/-1)
tests/gtest-nuxgraphics-texture.cpp (+17/-1)
To merge this branch: bzr merge lp:~unity-team/nux/nux.fix_1091589.1
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Stephen M. Webb (community) Approve
Brandon Schaefer (community) Approve
Christopher Townsend Approve
Review via email: mp+193185@code.launchpad.net

This proposal supersedes 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.
Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

> 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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

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.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

News:
http://support.amd.com/us/kbarticles/Pages/amdcatalyst13-6linbetadriver.aspx

AMD's fglrx 13.6 Beta driver now also supports GLX_EXT_buffer_age extension !!! \o/

Revision history for this message
Stephen M. Webb (bregma) wrote : Posted in a previous version of this proposal

This is (obviously) an ABI-breaking change. We need to bump the ABI string, SONAME, package version, and debian/changelog upstream package version at the same time.

This patchset should also include changing configure.ac to bump nux_micro_version to 3, nux_abi_version to, say, 20130530.0, and create a new UNRELEASED entry in debian/changelog for 4.0.3-0ubuntu1.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Okay.

I think I've been bumping the abi in configure.ac for some time now, but
I'll bump the other bits too - I'll be about 2 days with that though as uni
is keeping me busy. Is that OK?
On 29/05/2013 9:51 PM, "Stephen M. Webb" <email address hidden> wrote:

> Review: Needs Fixing
>
> This is (obviously) an ABI-breaking change. We need to bump the ABI
> string, SONAME, package version, and debian/changelog upstream package
> version at the same time.
>
> This patchset should also include changing configure.ac to bump
> nux_micro_version to 3, nux_abi_version to, say, 20130530.0, and create a
> new UNRELEASED entry in debian/changelog for 4.0.3-0ubuntu1.
>
> --
> https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589.1/+merge/165772
> You are the owner of lp:~smspillaz/nux/nux.fix_1091589.1.
>

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Thanks for the feedback, done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

I like this function :)
183 + void WindowCompositor::OnAllBaseWindows(const WindowMutatorFunc &func)

Very functional style! One suggestion would be a different name, possibly. MapFunctionOnAllBaseWindows, as what you are doing a specific higher order function. (Look up map function if yo want :)

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;

Might I suggest a simple utility function that will do this? That way you don't have to repeat your self twice and clean that up a bit...(though thats just being nit picky...)

866 + * This is really important. Don't remove it */
867 + result->_OpenGLID = id;

Thats like don't press this button! Now I want to remove it!! (joke no problem here)

No real *needs fixing* just some suggestions. Looking at actually running the branch now :)

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

On 11/06/2013 7:00 AM, "Brandon Schaefer" <email address hidden>
wrote:
>
> I like this function :)
> 183 + void WindowCompositor::OnAllBaseWindows(const WindowMutatorFunc
&func)
>
> Very functional style! One suggestion would be a different name,
possibly. MapFunctionOnAllBaseWindows, as what you are doing a specific
higher order function. (Look up map function if yo want :)

I could, although not everyone knows about map/reduce style. I think the
former is a bit clearer.

>
> 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;
>
> Might I suggest a simple utility function that will do this? That way you
don't have to repeat your self twice and clean that up a bit...(though
thats just being nit picky...)

Doable.

>
> 866 + * This is really important. Don't remove it */
> 867 + result->_OpenGLID = id;
>
> Thats like don't press this button! Now I want to remove it!! (joke no
problem here)

Someone removed it a while ago in a cleanup and cost me a day or two
debugging it. I think there's a test in place for it now.

>
> No real *needs fixing* just some suggestions. Looking at actually running
the branch now :)
>
> --
> https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589.1/+merge/165772
> You are the owner of lp:~smspillaz/nux/nux.fix_1091589.1.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

Cool, well we need to coordinate merging this at the same time as the unity branch, otherwise we are good to go on this branch. Marking as approved, but we need to wait to approved globally until the unity branch is ready :)

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:799
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~unity-team/nux/nux.fix_1091589.1/+merge/193185/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/nux-ci/79/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/nux-trusty-amd64-ci/1
    SUCCESS: http://jenkins.qa.ubuntu.com/job/nux-trusty-armhf-ci/1
    SUCCESS: http://jenkins.qa.ubuntu.com/job/nux-trusty-i386-ci/1

Click here to trigger a rebuild:
http://10.97.0.26:8080/job/nux-ci/79/rebuild

review: Needs Fixing (continuous-integration)
lp:~unity-team/nux/nux.fix_1091589.1 updated
800. By Marco Trevisan (Treviño)

Rect: implement operator<<

801. By Marco Trevisan (Treviño)

Rect: use line for operator<<

802. By Marco Trevisan (Treviño)

Rect: move operator<< definition into cpp file

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~unity-team/nux/nux.fix_1091589.1 updated
803. By Marco Trevisan (Treviño)

Area: some code cleanup into PrepareParentRedirectedView

804. By Marco Trevisan (Treviño)

BaseWindow, WindowThread: some code cleanup

Remove unnededed methods, rename to match their role and use const& in RenderInterfaceFromForeignCmd

805. By Marco Trevisan (Treviño)

Rect: add IsIntersecting method to verify if a rect is only intersecting another

Without bothering about actually computing the intersection

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~unity-team/nux/nux.fix_1091589.1 updated
806. By Marco Trevisan (Treviño)

Nux: use IsIntersecting when possible

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~unity-team/nux/nux.fix_1091589.1 updated
807. By Marco Trevisan (Treviño)

WindowCompositor: code cleanup, remove unneeded loops use foreach

808. By Marco Trevisan (Treviño)

WindowCompositor: use WeakBaseWindowPtr everywhere

809. By Marco Trevisan (Treviño)

WindowCompositor: get rid of FindWeakBaseWindowPtrForRawPtr

We don't really need this as each base window has its own reference into the
object itself, also all the BaseWindows are added to the WindowThread as soon
as they are created.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~unity-team/nux/nux.fix_1091589.1 updated
810. By Marco Trevisan (Treviño)

WindowThread: use lambdas in ForEachBaseWindow

811. By Marco Trevisan (Treviño)

WindowCompositor: use nux::Logger

812. By Marco Trevisan (Treviño)

NuxGraphics: use some more Rect const&

813. By Marco Trevisan (Treviño)

WindowCompositor: continue optimizing...

814. By Marco Trevisan (Treviño)

GraphicsEngine: use const& for returning rect when possible

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:~unity-team/nux/nux.fix_1091589.1 updated
815. By Marco Trevisan (Treviño)

WindowThread: use proper names for internal variables

816. By Marco Trevisan (Treviño)

TestWindowThread: fix compilation issue

817. By Marco Trevisan (Treviño)

WindowThread: use nicer code path to add the window to present to the proper list

818. By Marco Trevisan (Treviño)

TestWindowThread: add more tests

819. By Marco Trevisan (Treviño)

TestBaseWindow: don't enable the input window or it will cause crashes

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

Works fine for me. +1

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

LGTM

review: Approve
Revision history for this message
Stephen M. Webb (bregma) wrote :

ABI bump is OK

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Nux/Area.cpp'
2--- Nux/Area.cpp 2013-03-21 12:47:33 +0000
3+++ Nux/Area.cpp 2013-10-31 01:12:55 +0000
4@@ -1126,7 +1126,7 @@
5 return;
6 }
7
8- if ((redirect_rendering_to_texture_ == false) && redirect)
9+ if (!redirect_rendering_to_texture_ && redirect)
10 {
11 update_backup_texture_ = true;
12 }
13@@ -1169,15 +1169,14 @@
14
15 while (parent)
16 {
17- if (parent->RedirectRenderingToTexture() && (parent->UpdateBackupTextureForChildRendering() == false))
18+ if (parent->RedirectRenderingToTexture())
19 {
20+ if (parent->UpdateBackupTextureForChildRendering())
21+ break;
22+
23 parent->SetUpdateBackupTextureForChildRendering(true);
24 parent->PrepareParentRedirectedView();
25 }
26- else if (parent->RedirectRenderingToTexture() && (parent->UpdateBackupTextureForChildRendering() == true))
27- {
28- break;
29- }
30 else
31 {
32 parent->PrepareParentRedirectedView();
33
34=== modified file 'Nux/BaseWindow.cpp'
35--- Nux/BaseWindow.cpp 2013-04-08 14:02:32 +0000
36+++ Nux/BaseWindow.cpp 2013-10-31 01:12:55 +0000
37@@ -47,6 +47,8 @@
38 : View(NUX_FILE_LINE_PARAM)
39 , _paint_layer(new ColorLayer(Color(0xFF707070)))
40 , _opacity(1.0f)
41+ , _present_in_embedded_mode(false)
42+ , _contents_ready_for_presentation(false)
43 {
44 premultiply = true;
45 _name = WindowName;
46@@ -397,6 +399,8 @@
47 }
48 else
49 {
50+ SetEnterFocusInputArea(NULL);
51+
52 _entering_hidden_state = true;
53 sigHidden.emit(this);
54 GetWindowThread()->GetWindowCompositor().sigHiddenViewWindow.emit(this);
55@@ -490,6 +494,43 @@
56 return GetWindowThread()->GetWindowCompositor().GetBackupTextureData(this, width, height, format);
57 }
58
59+ void BaseWindow::PresentInEmbeddedModeOnThisFrame(bool force)
60+ {
61+ nuxAssertMsg (GetWindowThread()->IsEmbeddedWindow(),
62+ "[BaseWindow::PresentInEmbeddedModeOnThisFrame] only "
63+ "supported in embdded mode");
64+
65+ /* Invisible windows are never presented */
66+ if (!IsVisible())
67+ return;
68+
69+ if (nux::GetWindowThread()->AddToPresentationList(this, force))
70+ _present_in_embedded_mode = true;
71+ }
72+
73+ void BaseWindow::MarkPresentedInEmbeddedMode()
74+ {
75+ _present_in_embedded_mode = false;
76+ _last_presented_geometry_in_embedded_mode = GetAbsoluteGeometry();
77+ }
78+
79+ nux::Geometry const& BaseWindow::LastPresentedGeometryInEmbeddedMode() const
80+ {
81+ return _last_presented_geometry_in_embedded_mode;
82+ }
83+
84+ bool BaseWindow::AllowPresentationInEmbeddedMode() const
85+ {
86+ return _present_in_embedded_mode;
87+ }
88+
89+ void BaseWindow::PrepareParentRedirectedView()
90+ {
91+ Area::PrepareParentRedirectedView();
92+ if (GetWindowThread()->IsEmbeddedWindow())
93+ PresentInEmbeddedModeOnThisFrame();
94+ }
95+
96 void BaseWindow::SetEnterFocusInputArea(InputArea *input_area)
97 {
98 if (_enter_focus_input_area)
99
100=== modified file 'Nux/BaseWindow.h'
101--- Nux/BaseWindow.h 2012-11-12 20:59:56 +0000
102+++ Nux/BaseWindow.h 2013-10-31 01:12:55 +0000
103@@ -188,6 +188,13 @@
104 return _name;
105 }
106
107+ void PresentInEmbeddedModeOnThisFrame(bool force = false);
108+ void MarkPresentedInEmbeddedMode();
109+ bool AllowPresentationInEmbeddedMode() const;
110+ nux::Geometry const& LastPresentedGeometryInEmbeddedMode() const;
111+
112+ void PrepareParentRedirectedView();
113+
114 #ifdef NUX_GESTURES_SUPPORT
115 virtual Area* GetInputAreaHitByGesture(const nux::GestureEvent &event);
116 #endif
117@@ -261,6 +268,14 @@
118 bool _child_need_redraw; //!<True is there is a child of the BaseWindow that needs to be redrawn;
119 float _opacity;
120
121+ bool _present_in_embedded_mode; //!<True if we should draw this window's
122+ // backing texture to the screen on the
123+ // next frame
124+ nux::Geometry _last_presented_geometry_in_embedded_mode;
125+
126+ bool _contents_ready_for_presentation; //!<True if this window's contents has just been
127+ // redrawn and it is awaiting presentation
128+
129 friend class PopUpWindow;
130
131 friend class WindowThread;
132
133=== modified file 'Nux/GridHLayout.cpp'
134--- Nux/GridHLayout.cpp 2012-11-05 21:31:06 +0000
135+++ Nux/GridHLayout.cpp 2013-10-31 01:12:55 +0000
136@@ -516,11 +516,8 @@
137 continue;
138 }
139
140- Geometry it_geo = (*it)->GetAbsoluteGeometry();
141- Geometry intersection = visibility_geometry.Intersect(it_geo);
142-
143 // Test if the element is inside the Grid before rendering.
144- if (!intersection.IsNull())
145+ if (visibility_geometry.IsIntersecting((*it)->GetAbsoluteGeometry()))
146 {
147 if (first == false)
148 {
149
150=== modified file 'Nux/GridVLayout.cpp'
151--- Nux/GridVLayout.cpp 2012-07-24 05:39:41 +0000
152+++ Nux/GridVLayout.cpp 2013-10-31 01:12:55 +0000
153@@ -300,14 +300,9 @@
154 it = elements.begin();
155
156 Geometry base = GetGeometry();
157- Geometry parent_geometry = GetAbsoluteGeometry();
158- Geometry visibility_geometry = parent_geometry;
159- if (GetToplevel())
160- {
161- parent_geometry = GetToplevel()->GetAbsoluteGeometry();
162- }
163+ Geometry const& parent_geometry = GetToplevel() ? GetToplevel()->GetAbsoluteGeometry() : GetAbsoluteGeometry();
164
165- visibility_geometry = parent_geometry.Intersect(GetAbsoluteGeometry());
166+ bool geometry_is_visible = parent_geometry.IsIntersecting(GetAbsoluteGeometry());
167
168 graphics_engine.PushClippingRectangle(base);
169
170@@ -318,10 +313,8 @@
171 if (it == elements.end())
172 break;
173
174- Geometry intersection = base.Intersect((*it)->GetGeometry());
175-
176 // Test if the element is inside the Grid before rendering.
177- if (!visibility_geometry.IsNull())
178+ if (geometry_is_visible)
179 {
180 int X = base.x + m_h_out_margin + i * (_children_size.width + m_h_in_margin);
181 int Y = base.y + m_v_out_margin + j * (_children_size.height + m_v_in_margin);
182
183=== modified file 'Nux/View.cpp'
184--- Nux/View.cpp 2013-04-08 14:02:32 +0000
185+++ Nux/View.cpp 2013-10-31 01:12:55 +0000
186@@ -425,6 +425,13 @@
187
188 void View::QueueDraw()
189 {
190+ // Report to a parent view with redirect_rendering_to_texture_ set to true that one of its children
191+ // needs to be redrawn.
192+ //
193+ // We should always do this, as the conditions for parent rendering may have
194+ // changed between child QueueDraw calls (eg window visibility)
195+ PrepareParentRedirectedView();
196+
197 if (draw_cmd_queued_)
198 return;
199
200@@ -435,10 +442,6 @@
201 application->RequestRedraw();
202 }
203
204- // Report to a parent view with redirect_rendering_to_texture_ set to true that one of its children
205- // needs to be redrawn.
206- PrepareParentRedirectedView();
207-
208 if (view_layout_)
209 {
210 // If this view has requested a draw, then all of it children in the view_layout_
211
212=== modified file 'Nux/WindowCompositor.cpp'
213--- Nux/WindowCompositor.cpp 2013-05-28 10:26:28 +0000
214+++ Nux/WindowCompositor.cpp 2013-10-31 01:12:55 +0000
215@@ -41,8 +41,11 @@
216 DECLARE_LOGGER(logger, "nux.window");
217
218 WindowCompositor::WindowCompositor(WindowThread* window_thread)
219- : reference_fbo_(0)
220+ : draw_reference_fbo_(0)
221+ , read_reference_fbo_(0)
222 , window_thread_(window_thread)
223+ , currently_rendering_windows_(nullptr)
224+ , current_global_clip_rect_(nullptr)
225 {
226 m_OverlayWindow = NULL;
227 _tooltip_window = NULL;
228@@ -135,7 +138,7 @@
229 _view_window_list.end(), window);
230 if (it == _view_window_list.end())
231 {
232- _view_window_list.push_front(ObjectWeakPtr<BaseWindow>(window));
233+ _view_window_list.push_front(WeakBaseWindowPtr(window));
234
235 RenderTargetTextures rt;
236
237@@ -192,30 +195,36 @@
238 NuxEventType event_type,
239 ObjectWeakPtr<InputArea>& area_under_mouse_pointer)
240 {
241- ObjectWeakPtr<BaseWindow> window;
242+ WeakBaseWindowPtr window;
243 GetAreaUnderMouse(mouse_position, event_type, area_under_mouse_pointer, window);
244 }
245
246 void WindowCompositor::GetAreaUnderMouse(const Point& mouse_position,
247 NuxEventType event_type,
248 ObjectWeakPtr<InputArea>& area_under_mouse_pointer,
249- ObjectWeakPtr<BaseWindow>& window)
250+ WeakBaseWindowPtr& window)
251 {
252 window = NULL;
253 area_under_mouse_pointer = NULL;
254
255 // Go through the list of BaseWindo and find the first area over which the
256 // mouse pointer is.
257- WindowList::iterator window_it;
258- for (window_it = _view_window_list.begin(); window_it != _view_window_list.end(); ++window_it)
259+ for (auto const& window_it : _view_window_list)
260 {
261- if ((*window_it).IsValid() && (*window_it)->IsVisible())
262+ // Since the mouse is really an input-level thing, we want to know
263+ // if the underlying input window is enabled or if the window is
264+ // visible
265+
266+ if (!window_it.IsValid())
267+ continue;
268+
269+ if (window_it->InputWindowEnabled() || window_it->IsVisible())
270 {
271- Area* area = (*window_it)->FindAreaUnderMouse(mouse_position, event_type);
272+ Area* area = window_it->FindAreaUnderMouse(mouse_position, event_type);
273 if (area)
274 {
275 area_under_mouse_pointer = static_cast<InputArea*>(area);
276- window = *window_it;
277+ window = window_it;
278 return;
279 }
280 }
281@@ -890,26 +899,24 @@
282 unsigned int key_symbol,
283 unsigned int special_keys_state,
284 ObjectWeakPtr<InputArea>& key_focus_area,
285- ObjectWeakPtr<BaseWindow>& window)
286+ WeakBaseWindowPtr& window)
287 {
288 key_focus_area = NULL;
289 window = NULL;
290
291 // Go through the list of BaseWindos and find the first area over which the mouse pointer is.
292- WindowList::iterator window_it;
293- window_it = _view_window_list.begin();
294- while (!key_focus_area.IsValid() && window_it != _view_window_list.end())
295+ for (auto const& window_it : _view_window_list)
296 {
297- if ((*window_it).IsValid() && (*window_it)->IsVisible())
298+ if (window_it.IsValid() && window_it->IsVisible())
299 {
300- key_focus_area = NUX_STATIC_CAST(InputArea*, (*window_it)->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
301+ key_focus_area = NUX_STATIC_CAST(InputArea*, window_it->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
302 if (key_focus_area.IsValid())
303 {
304 // We have found an area. We are going to exit the while loop.
305- window = *window_it;
306+ window = window_it;
307+ break;
308 }
309 }
310- ++window_it;
311 }
312
313 // If key_focus_area is NULL, then try the main window layout.
314@@ -928,7 +935,7 @@
315 unsigned int special_keys_state,
316 InputArea* root_search_area,
317 ObjectWeakPtr<InputArea>& key_focus_area,
318- ObjectWeakPtr<BaseWindow>& window)
319+ WeakBaseWindowPtr& window)
320 {
321 key_focus_area = NULL;
322 window = NULL;
323@@ -975,7 +982,7 @@
324 InputArea* keyboard_event_grab_view = GetKeyboardGrabArea();
325
326 ObjectWeakPtr<InputArea> focus_area; // The view under the mouse
327- ObjectWeakPtr<BaseWindow> base_window; // The BaseWindow below the mouse pointer.
328+ WeakBaseWindowPtr base_window; // The BaseWindow below the mouse pointer.
329
330 if (keyboard_event_grab_view)
331 {
332@@ -1173,7 +1180,7 @@
333 inside_event_cycle_ = false;
334 }
335
336- void WindowCompositor::StartModalWindow(ObjectWeakPtr<BaseWindow> window)
337+ void WindowCompositor::StartModalWindow(WeakBaseWindowPtr window)
338 {
339 if (window == 0)
340 return;
341@@ -1186,7 +1193,7 @@
342 }
343 }
344
345- void WindowCompositor::StopModalWindow(ObjectWeakPtr<BaseWindow> window)
346+ void WindowCompositor::StopModalWindow(WeakBaseWindowPtr window)
347 {
348 if (!_modal_view_window_list.empty())
349 {
350@@ -1206,7 +1213,7 @@
351 if (it != _view_window_list.end())
352 {
353 _view_window_list.erase(it);
354- _view_window_list.push_front(ObjectWeakPtr<BaseWindow> (window));
355+ _view_window_list.push_front(WeakBaseWindowPtr(window));
356 }
357
358 EnsureAlwaysOnFrontWindow();
359@@ -1226,7 +1233,7 @@
360 if (it != _view_window_list.end())
361 {
362 _view_window_list.erase(it);
363- _view_window_list.push_back(ObjectWeakPtr<BaseWindow> (window));
364+ _view_window_list.push_back(WeakBaseWindowPtr(window));
365 }
366
367 EnsureAlwaysOnFrontWindow();
368@@ -1273,7 +1280,7 @@
369 if ((top_pos < bot_pos) && (strict == false))
370 {
371 _view_window_list.erase(it_top);
372- _view_window_list.insert(it_bot, ObjectWeakPtr<BaseWindow> (top_floating_view));
373+ _view_window_list.insert(it_bot, WeakBaseWindowPtr(top_floating_view));
374 }
375
376 EnsureAlwaysOnFrontWindow();
377@@ -1281,7 +1288,7 @@
378
379 void WindowCompositor::SetAlwaysOnFrontWindow(BaseWindow* window)
380 {
381- _always_on_front_window = ObjectWeakPtr<BaseWindow> (window);
382+ _always_on_front_window = WeakBaseWindowPtr(window);
383
384 EnsureAlwaysOnFrontWindow();
385 }
386@@ -1341,6 +1348,39 @@
387 }
388 }
389
390+ namespace
391+ {
392+ void AssignWeakBaseWindowMatchingRaw(WindowCompositor::WeakBaseWindowPtr const& w, BaseWindow* bw, WindowCompositor::WeakBaseWindowPtr *ptr)
393+ {
394+ if (w.IsValid() && w.GetPointer() == bw)
395+ *ptr = w;
396+ }
397+ }
398+
399+ void WindowCompositor::ForEachBaseWindow(ForEachBaseWindowFunc const& func)
400+ {
401+ for (auto const& window : _view_window_list)
402+ {
403+ if (window.IsValid())
404+ func(window);
405+ }
406+
407+ for (auto const& window : _modal_view_window_list)
408+ {
409+ if (window.IsValid())
410+ func(window);
411+ }
412+
413+ if (m_MenuWindow.IsValid())
414+ func(m_MenuWindow);
415+
416+ if (_tooltip_window.IsValid())
417+ func(_tooltip_window);
418+
419+ if (m_OverlayWindow.IsValid())
420+ func(m_OverlayWindow);
421+ }
422+
423 void WindowCompositor::Draw(bool SizeConfigurationEvent, bool force_draw)
424 {
425 inside_rendering_cycle_ = true;
426@@ -1414,7 +1454,7 @@
427 void WindowCompositor::DrawMenu(bool force_draw)
428 {
429 #if !defined(NUX_MINIMAL)
430- ObjectWeakPtr<BaseWindow> window = m_MenuWindow;
431+ WeakBaseWindowPtr window(m_MenuWindow);
432
433 if (window.IsValid())
434 {
435@@ -1443,11 +1483,10 @@
436
437 void WindowCompositor::DrawOverlay(bool /* force_draw */)
438 {
439- ObjectWeakPtr<BaseWindow> window = m_OverlayWindow;
440 int buffer_width = window_thread_->GetGraphicsEngine().GetWindowWidth();
441 int buffer_height = window_thread_->GetGraphicsEngine().GetWindowHeight();
442
443- if (window.IsValid())
444+ if (m_OverlayWindow.IsValid())
445 {
446 //window_thread_->GetGraphicsEngine().SetContext(x, y, buffer_width, buffer_height);
447 window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
448@@ -1468,11 +1507,10 @@
449
450 void WindowCompositor::DrawTooltip(bool /* force_draw */)
451 {
452- ObjectWeakPtr<BaseWindow> window = _tooltip_window;
453 int buffer_width = window_thread_->GetGraphicsEngine().GetWindowWidth();
454 int buffer_height = window_thread_->GetGraphicsEngine().GetWindowHeight();
455
456- if (window.IsValid())
457+ if (_tooltip_window.IsValid())
458 {
459 //window_thread_->GetGraphicsEngine().SetContext(x, y, buffer_width, buffer_height);
460 window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
461@@ -1501,6 +1539,63 @@
462 GetPainter().EmptyBackgroundStack();
463 }
464
465+ void WindowCompositor::PresentAnyReadyWindows()
466+ {
467+ if (!currently_rendering_windows_ || !current_global_clip_rect_)
468+ return;
469+
470+ GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
471+
472+ // Present all buffers to the screen
473+ graphics_engine.ApplyClippingRectangle();
474+ CHECKGL(glDepthMask(GL_FALSE));
475+
476+ WindowList &windows = *currently_rendering_windows_;
477+ Geometry &global_clip_rect = *current_global_clip_rect_;
478+
479+ for (auto const& window_ptr : windows)
480+ {
481+ if (window_ptr.IsNull())
482+ continue;
483+
484+ BaseWindow* window = window_ptr.GetPointer();
485+
486+ if (window->IsVisible())
487+ {
488+ auto const& win_geo = window->GetGeometry();
489+
490+ if (!global_clip_rect.IsIntersecting(win_geo))
491+ {
492+ // The global clipping area can be seen as a per monitor clipping
493+ // region. It is mostly used in embedded mode with compiz. If we
494+ // get here, it means that the BaseWindow we want to render is not
495+ // in area of the monitor that compiz is currently rendering. So
496+ // skip it.
497+ continue;
498+ }
499+
500+ RenderTargetTextures& rt = GetWindowBuffer(window);
501+
502+ if (rt.color_rt.IsValid())
503+ {
504+ /* Already been presented */
505+ if (!window->_contents_ready_for_presentation)
506+ continue;
507+
508+ /* Caller doesn't want us to render this yet */
509+ if (window_thread_->IsEmbeddedWindow() && !window->AllowPresentationInEmbeddedMode())
510+ continue;
511+
512+ // Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
513+ // has cancelled any opengl framebuffer object that was set.
514+ PresentBufferToScreen(rt.color_rt, win_geo.x, win_geo.y, false, false, window->GetOpacity(), window->premultiply());
515+
516+ window->_contents_ready_for_presentation = false;
517+ }
518+ }
519+ }
520+ }
521+
522 void WindowCompositor::RenderTopViews(bool force_draw,
523 WindowList& windows_to_render,
524 bool drawModal)
525@@ -1512,13 +1607,17 @@
526 GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
527 unsigned int window_width = graphics_engine.GetWindowWidth();
528 unsigned int window_height = graphics_engine.GetWindowHeight();
529- GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
530 graphics_engine.SetViewport(0, 0, window_width, window_height);
531 graphics_engine.EmptyClippingRegion();
532
533 Geometry global_clip_rect = graphics_engine.GetScissorRect();
534 global_clip_rect.y = window_height - global_clip_rect.y - global_clip_rect.height;
535
536+ current_global_clip_rect_ = &global_clip_rect;
537+
538+ // We don't need to restore framebuffers if we didn't update any windows
539+ bool updated_any_windows = false;
540+
541 // Always make a copy of the windows to render. We have no control over
542 // the windows we are actually drawing. It has been observed that some
543 // windows modify the windows stack during the draw process.
544@@ -1530,19 +1629,23 @@
545 // list, lets reverse it as we are constructing, as we want to draw the
546 // windows from back to front.
547 WindowList windows(windows_to_render.rbegin(), windows_to_render.rend());
548- for (WindowList::iterator it = windows.begin(), end = windows.end(); it != end; ++it)
549+
550+ currently_rendering_windows_ = &windows;
551+
552+ for (auto const& window_ptr : windows)
553 {
554- WeakBaseWindowPtr& window_ptr = *it;
555 if (window_ptr.IsNull())
556 continue;
557
558 BaseWindow* window = window_ptr.GetPointer();
559+
560 if (!drawModal && window->IsModal())
561 continue;
562
563 if (window->IsVisible())
564 {
565- if (global_clip_rect.Intersect(window->GetGeometry()).IsNull())
566+ auto const& win_geo = window->GetGeometry();
567+ if (!global_clip_rect.IsIntersecting(win_geo))
568 {
569 // The global clipping area can be seen as a per monitor clipping
570 // region. It is mostly used in embedded mode with compiz. If we
571@@ -1586,33 +1689,21 @@
572 }
573 else
574 {
575- int x = window->GetBaseX();
576- int y = window->GetBaseY();
577 Matrix4 mat;
578- mat.Translate(x, y, 0);
579+ mat.Translate(win_geo.x, win_geo.y, 0);
580 graphics_engine.SetOrthographicProjectionMatrix(window_width, window_height);
581 }
582
583 RenderTopViewContent(window, force_draw);
584- }
585
586- if (rt.color_rt.IsValid())
587- {
588 m_FrameBufferObject->Deactivate();
589-
590- // Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
591- // has cancelled any opengl framebuffer object that was set.
592-
593- CHECKGL(glDepthMask(GL_FALSE));
594- {
595- graphics_engine.ApplyClippingRectangle();
596- PresentBufferToScreen(rt.color_rt, window->GetBaseX(), window->GetBaseY(), false, false, window->GetOpacity(), window->premultiply());
597- }
598 CHECKGL(glDepthMask(GL_TRUE));
599 graphics_engine.GetRenderStates().SetBlend(false);
600+ updated_any_windows = true;
601 }
602
603 window->_child_need_redraw = false;
604+ window->_contents_ready_for_presentation = true;
605 }
606 else
607 {
608@@ -1622,7 +1713,29 @@
609 }
610 }
611
612- m_FrameBufferObject->Deactivate();
613+ /* If any windows were updated, then we need to rebind our
614+ * reference framebuffer */
615+ if (updated_any_windows)
616+ {
617+ if (GetWindowThread()->IsEmbeddedWindow())
618+ {
619+ // Restore the reference framebuffer
620+ if (!RestoreReferenceFramebuffer())
621+ {
622+ LOG_DEBUG(logger) << "RenderTopViews: Setting the Reference fbo has failed.";
623+ }
624+ }
625+ else
626+ {
627+ GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
628+ }
629+ }
630+
631+ /* Present any windows which haven't yet been presented */
632+ PresentAnyReadyWindows();
633+
634+ currently_rendering_windows_ = nullptr;
635+ current_global_clip_rect_ = nullptr;
636 }
637
638 void WindowCompositor::RenderMainWindowComposition(bool force_draw)
639@@ -1720,23 +1833,8 @@
640 m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
641 m_FrameBufferObject->Activate();
642 }
643- else
644- {
645- if (GetWindowThread()->IsEmbeddedWindow() && reference_fbo_)
646- {
647- // In the context of Unity, we may want Nux to restore a specific fbo and render the
648- // BaseWindow texture into it. That fbo is called a reference framebuffer object. if a
649- // Reference framebuffer object is present, Nux sets it.
650- if (!RestoreReferenceFramebuffer())
651- {
652- nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
653- }
654- }
655- else
656- {
657- GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
658- }
659- }
660+
661+ // Reference framebuffer is already restored
662
663 window_thread_->GetGraphicsEngine().EmptyClippingRegion();
664 window_thread_->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, window_width, window_height);
665@@ -1949,7 +2047,7 @@
666 {
667 // There is a keyboard grab pending. Only an area that is a child of the area that has
668 // the keyboard grab can be set to receive keyboard events.
669- nuxDebugMsg("[WindowCompositor::SetKeyFocusArea] There is a keyboard grab pending. Cannot change the keyboard event receiver.");
670+ LOG_DEBUG(logger) << "SetKeyFocusArea: There is a keyboard grab pending. Cannot change the keyboard event receiver.";
671 return false;
672 }
673
674@@ -2047,14 +2145,13 @@
675 {
676 WindowList::iterator it;
677
678- for (it = _view_window_list.begin(); it != _view_window_list.end(); ++it)
679+ for (auto const& win : _view_window_list)
680 {
681- if (!(*it).IsValid())
682+ if (!win.IsValid())
683 continue;
684- if ((*it)->IsVisible())
685- {
686- (*it)->NotifyConfigurationChange(Width, Height);
687- }
688+
689+ if (win->IsVisible())
690+ win->NotifyConfigurationChange(Width, Height);
691 }
692 }
693
694@@ -2140,11 +2237,22 @@
695
696 nuxAssert(buffer_width >= 1);
697 nuxAssert(buffer_height >= 1);
698- // Restore Main Frame Buffer
699- m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
700- m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
701- m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
702- m_FrameBufferObject->Activate();
703+ // Restore Main Frame Buffer if not in embedded mode
704+ if (!GetWindowThread()->IsEmbeddedWindow())
705+ {
706+ m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
707+ m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
708+ m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
709+ m_FrameBufferObject->Activate();
710+ }
711+ else
712+ {
713+ // Restore reference framebuffer
714+ RestoreReferenceFramebuffer();
715+
716+ // Present any ready windows
717+ PresentAnyReadyWindows();
718+ }
719
720 window_thread_->GetGraphicsEngine().SetViewport(0, 0, buffer_width, buffer_height);
721 window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
722@@ -2215,7 +2323,7 @@
723
724 if (GetPointerGrabArea() == area)
725 {
726- nuxDebugMsg("[WindowCompositor::GrabPointerAdd] The area already has the grab");
727+ LOG_DEBUG(logger) << "GrabPointerAdd: The area already has the grab";
728 return result;
729 }
730
731@@ -2282,7 +2390,7 @@
732
733 if (GetKeyboardGrabArea() == area)
734 {
735- nuxDebugMsg("[WindowCompositor::GrabKeyboardAdd] The area already has the grab");
736+ LOG_DEBUG(logger) << "GrabKeyboardAdd: The area already has the grab";
737 return result;
738 }
739
740@@ -2429,9 +2537,10 @@
741 return (*keyboard_grab_stack_.begin());
742 }
743
744- void WindowCompositor::SetReferenceFramebuffer(unsigned int fbo_object, Geometry fbo_geometry)
745+ void WindowCompositor::SetReferenceFramebuffer(unsigned int draw_fbo_object, unsigned int read_fbo_object, Geometry const& fbo_geometry)
746 {
747- reference_fbo_ = fbo_object;
748+ draw_reference_fbo_ = draw_fbo_object;
749+ read_reference_fbo_ = read_fbo_object;
750 reference_fbo_geometry_ = fbo_geometry;
751 }
752
753@@ -2497,7 +2606,7 @@
754 return ok;
755 }
756
757- void SetReferenceFramebufferViewport (const nux::Geometry &reference_fbo_geometry_)
758+ void SetReferenceFramebufferViewport(const nux::Geometry &reference_fbo_geometry_)
759 {
760 CHECKGL(glViewport(reference_fbo_geometry_.x,
761 reference_fbo_geometry_.y,
762@@ -2508,24 +2617,53 @@
763
764 bool WindowCompositor::RestoreReferenceFramebuffer()
765 {
766- if (!reference_fbo_)
767- return false;
768-
769 // It is assumed that the reference fbo contains valid textures.
770 // Nux does the following:
771 // - Bind the reference fbo (reference_fbo_)
772 // - Call glDrawBuffer with GL_COLOR_ATTACHMENT0
773 // - Set the opengl viewport size (reference_fbo_geometry_)
774
775- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, reference_fbo_));
776-#ifndef NUX_OPENGLES_20
777- CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
778- CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
779-#endif
780-
781- SetReferenceFramebufferViewport (reference_fbo_geometry_);
782-
783- return CheckExternalFramebufferStatus (GL_FRAMEBUFFER_EXT);
784+#ifndef NUX_OPENGLES_20
785+ CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, draw_reference_fbo_));
786+ CHECKGL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, read_reference_fbo_));
787+ if (draw_reference_fbo_)
788+ {
789+ CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
790+ }
791+ else
792+ {
793+ CHECKGL(glDrawBuffer(GL_BACK));
794+ }
795+
796+ if (read_reference_fbo_)
797+ {
798+ CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
799+ }
800+ else
801+ {
802+ CHECKGL(glReadBuffer(GL_BACK));
803+ }
804+#else
805+ nuxAssertMsg(draw_reference_fbo_ == read_reference_fbo_,
806+ "[WindowCompositor::RestoreReferenceFramebuffer]: OpenGL|ES does not"\
807+ " support separate draw and read framebuffer bindings, using the supplied"\
808+ " draw binding");
809+ CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER, draw_reference_fbo_));
810+#endif
811+
812+ SetReferenceFramebufferViewport(reference_fbo_geometry_);
813+
814+#ifndef NUX_OPENGLES_20
815+ int restore_status =
816+ (!draw_reference_fbo_ ||
817+ CheckExternalFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT)) &&
818+ (!read_reference_fbo_ ||
819+ CheckExternalFramebufferStatus(GL_READ_FRAMEBUFFER_EXT));
820+#else
821+ int restore_status = CheckExternalFramebufferStatus(GL_FRAMEBUFFER);
822+#endif
823+
824+ return restore_status;
825 }
826
827 void WindowCompositor::RestoreMainFramebuffer()
828@@ -2533,6 +2671,14 @@
829 // This is a bit inefficient as we unbind and then rebind
830 nux::GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer ();
831 RestoreReferenceFramebuffer ();
832+
833+ /* Present any ready windows after restoring
834+ * the reference framebuffer. This ensures that if
835+ * we need to restore the reference framebuffer to
836+ * get access to its contents through glCopyTexSubImage2D
837+ * that it will also have any rendered views in it too
838+ */
839+ PresentAnyReadyWindows();
840 }
841
842 #ifdef NUX_GESTURES_SUPPORT
843@@ -2545,7 +2691,7 @@
844 {
845 InputArea *input_area = nullptr;
846
847- for (auto window : _view_window_list)
848+ for (auto const& window : _view_window_list)
849 {
850 if (!window.IsValid())
851 continue;
852
853=== modified file 'Nux/WindowCompositor.h'
854--- Nux/WindowCompositor.h 2013-04-29 23:33:12 +0000
855+++ Nux/WindowCompositor.h 2013-10-31 01:12:55 +0000
856@@ -23,6 +23,8 @@
857 #ifndef WINDOWCOMPOSITOR_H
858 #define WINDOWCOMPOSITOR_H
859
860+#include <functional>
861+
862 #include "BaseWindow.h"
863
864 #include <sigc++/trackable.h>
865@@ -53,6 +55,7 @@
866 {
867 public:
868 typedef ObjectWeakPtr<BaseWindow> WeakBaseWindowPtr;
869+ typedef std::function <void(WeakBaseWindowPtr const&)> ForEachBaseWindowFunc;
870
871 WindowCompositor(WindowThread* window_thread);
872 ~WindowCompositor();
873@@ -112,9 +115,11 @@
874 Return the area that has the keyboard focus.
875
876 @return The area that has the keyboard focus.
877- */
878+ */
879 InputArea* GetKeyFocusArea();
880
881+ void ForEachBaseWindow(ForEachBaseWindowFunc const&);
882+
883 //! Signal emitted when a BaseWindow becomes visible.
884 /*!
885 This signal is emitted after the BaseWindow has emitted it own sigVisible signal.
886@@ -155,14 +160,14 @@
887 void GetAreaUnderMouse(const Point& mouse_position,
888 NuxEventType event_type,
889 ObjectWeakPtr<InputArea>& area_under_mouse_pointer,
890- ObjectWeakPtr<BaseWindow>& window);
891+ WeakBaseWindowPtr& window);
892
893 //! Traverse the widget tree and found the area has the key focus.
894 void FindKeyFocusArea(NuxEventType event_type,
895 unsigned int key_symbol,
896 unsigned int special_keys_state,
897 ObjectWeakPtr<InputArea>& key_focus_area,
898- ObjectWeakPtr<BaseWindow>& window);
899+ WeakBaseWindowPtr& window);
900
901 //! Traverse the widget tree and found the area has the key focus, but start from a specified widget.
902 void FindKeyFocusAreaFrom(NuxEventType event_type,
903@@ -170,7 +175,7 @@
904 unsigned int special_keys_state,
905 InputArea* root_search_area,
906 ObjectWeakPtr<InputArea>& key_focus_area,
907- ObjectWeakPtr<BaseWindow>& window);
908+ WeakBaseWindowPtr& window);
909
910 void ResetMousePointerAreas();
911
912@@ -239,10 +244,11 @@
913 restored after Nux completes it rendering. The external fbo is used only in embedded mode. \n
914 If the fbo_object parameter 0, then the reference fbo is invalid and will not be used.
915
916- @param fbo_object The opengl index of the fbo.
917+ @param draw_fbo_object The opengl index of the GL_DRAW_FRAMEBUFFER_EXT.
918+ @param read_fbo_object The opengl index of the GL_READ_FRAMEBUFFER_EXT.
919 @param fbo_geometry The geometry of the fbo.
920 */
921- void SetReferenceFramebuffer(unsigned int fbo_object, Geometry fbo_geometry);
922+ void SetReferenceFramebuffer(unsigned int draw_fbo_object, unsigned int read_fbo_object, const Geometry &fbo_geometry);
923
924 /*!
925 Bind the reference opengl framebuffer object.
926@@ -259,8 +265,8 @@
927
928 ObjectPtr<IOpenGLFrameBufferObject> m_FrameBufferObject;
929
930- void StartModalWindow(ObjectWeakPtr<BaseWindow>);
931- void StopModalWindow(ObjectWeakPtr<BaseWindow>);
932+ void StartModalWindow(WeakBaseWindowPtr);
933+ void StopModalWindow(WeakBaseWindowPtr);
934
935 #if !defined(NUX_MINIMAL)
936 void AddMenu(MenuPage* menu, BaseWindow* window, bool OverrideCurrentMenuChain = true);
937@@ -268,7 +274,7 @@
938 void CleanMenu();
939 #endif
940
941- void PushModalWindow(ObjectWeakPtr<BaseWindow> window);
942+ void PushModalWindow(WeakBaseWindowPtr window);
943
944 void SetWidgetDrawingOverlay(InputArea* ic, BaseWindow* OverlayWindow);
945 InputArea* GetWidgetDrawingOverlay();
946@@ -408,6 +414,8 @@
947 #endif
948
949 private:
950+ typedef std::list<WeakBaseWindowPtr> WindowList;
951+
952 //! Render the interface.
953 void Draw(bool SizeConfigurationEvent, bool force_draw);
954
955@@ -422,7 +430,9 @@
956 @WindowList The list of top views.
957 @draw_modal True if the top view that is modal is to be rendered.
958 */
959- void RenderTopViews(bool force_draw, std::list< ObjectWeakPtr<BaseWindow> >& WindowList, bool draw_modal);
960+ void RenderTopViews(bool force_draw, WindowList&, bool draw_modal);
961+
962+ void PresentAnyReadyWindows();
963
964 //! Render the content of a top view.
965 void RenderTopViewContent(BaseWindow* window, bool force_draw);
966@@ -511,7 +521,6 @@
967 bool on_menu_closure_continue_with_event_;
968 AbstractPaintLayer* m_Background;
969
970- typedef std::list<WeakBaseWindowPtr> WindowList;
971 WindowList _view_window_list;
972 WindowList _modal_view_window_list;
973 WeakBaseWindowPtr _always_on_front_window; //!< Floating view that always remains on top.
974@@ -534,7 +543,8 @@
975 int m_TooltipY;
976
977 //! The fbo to restore after Nux rendering in embedded mode.
978- unsigned int reference_fbo_;
979+ unsigned int draw_reference_fbo_;
980+ unsigned int read_reference_fbo_;
981 Geometry reference_fbo_geometry_;
982
983 //! True if the platform has support for depth textures.
984@@ -571,6 +581,9 @@
985 std::unique_ptr<GestureBroker> gesture_broker_;
986 #endif
987
988+ WindowList* currently_rendering_windows_;
989+ Geometry* current_global_clip_rect_;
990+
991 //! Perform some action before destruction.
992 /*!
993 Perform some action before destruction. This function should only be
994
995=== modified file 'Nux/WindowThread.cpp'
996--- Nux/WindowThread.cpp 2013-04-13 21:21:01 +0000
997+++ Nux/WindowThread.cpp 2013-10-31 01:12:55 +0000
998@@ -19,6 +19,8 @@
999 *
1000 */
1001
1002+#include <functional>
1003+
1004 #include "Nux.h"
1005 #include "Layout.h"
1006 #include "NuxCore/Logger.h"
1007@@ -50,6 +52,7 @@
1008
1009 WindowThread::WindowThread(const char *WindowTitle, int width, int height, AbstractThread *Parent, bool Modal)
1010 : AbstractThread(Parent)
1011+ , foreign_frame_frozen_(false)
1012 , window_initial_width_(width)
1013 , window_initial_height_(height)
1014 , window_title_(WindowTitle)
1015@@ -168,7 +171,7 @@
1016 this->GetTimerHandler().RemoveTimerHandler(async_wake_up_timer_handle_);
1017 _pending_wake_up_timer = false;
1018 }
1019-
1020+
1021 void WindowThread::ProcessDraw(GraphicsEngine &graphics_engine, bool force_draw)
1022 {
1023 if (main_layout_)
1024@@ -192,7 +195,7 @@
1025 {
1026 _draw_requested_to_host_wm = true;
1027 RedrawRequested.emit();
1028-
1029+
1030 if (!IsEmbeddedWindow())
1031 {
1032 // If the system is not in embedded mode and an asynchronous request for a Draw is made,
1033@@ -728,7 +731,7 @@
1034 {
1035 ReconfigureLayout();
1036 }
1037- else
1038+ else
1039 {
1040 // Compute the layouts that have been queued.
1041 ComputeQueuedLayout();
1042@@ -1348,7 +1351,7 @@
1043 }
1044 }
1045 }
1046-
1047+
1048 void WindowThread::AddToDrawList(View *view)
1049 {
1050 Area *parent;
1051@@ -1376,20 +1379,59 @@
1052 window->_child_need_redraw = true;
1053 }
1054
1055- m_dirty_areas.push_back(geo);
1056+ dirty_areas_.push_back(geo);
1057 }
1058-
1059+
1060 void WindowThread::ClearDrawList()
1061 {
1062- m_dirty_areas.clear();
1063+ dirty_areas_.clear();
1064 }
1065-
1066+
1067 std::vector<Geometry> const& WindowThread::GetDrawList() const
1068 {
1069- return m_dirty_areas;
1070- }
1071-
1072- bool WindowThread::IsEmbeddedWindow()
1073+ return dirty_areas_;
1074+ }
1075+
1076+ bool WindowThread::AddToPresentationList(BaseWindow* bw, bool force)
1077+ {
1078+ if (!bw)
1079+ return false;
1080+
1081+ RequestRedraw();
1082+
1083+ bool force_or_not_frozen = (force || !foreign_frame_frozen_);
1084+ std::vector<WeakBaseWindowPtr>& target_list = force_or_not_frozen ? presentation_list_embedded_ :
1085+ presentation_list_embedded_next_frame_;
1086+
1087+ if (std::find(target_list.begin(), target_list.end(), bw) != target_list.end())
1088+ return force_or_not_frozen;
1089+
1090+ target_list.push_back(WeakBaseWindowPtr(bw));
1091+ return force_or_not_frozen;
1092+ }
1093+
1094+ std::vector<nux::Geometry> WindowThread::GetPresentationListGeometries() const
1095+ {
1096+ std::vector<nux::Geometry> presentation_geometries;
1097+ for (auto const& base_window : presentation_list_embedded_)
1098+ {
1099+ if (base_window.IsValid())
1100+ {
1101+ nux::Geometry const& abs_geom = base_window->GetAbsoluteGeometry();
1102+ nux::Geometry const& last_geom = base_window->LastPresentedGeometryInEmbeddedMode();
1103+ presentation_geometries.push_back(abs_geom);
1104+
1105+ if (abs_geom != last_geom)
1106+ {
1107+ if (!last_geom.IsNull())
1108+ presentation_geometries.push_back(last_geom);
1109+ }
1110+ }
1111+ }
1112+ return presentation_geometries;
1113+ }
1114+
1115+ bool WindowThread::IsEmbeddedWindow() const
1116 {
1117 return embedded_window_;
1118 }
1119@@ -1468,7 +1510,7 @@
1120 {
1121 ReconfigureLayout();
1122 }
1123- else
1124+ else
1125 {
1126 // Compute the layouts that have been queued.
1127 ComputeQueuedLayout();
1128@@ -1529,13 +1571,25 @@
1129 return request_draw_cycle_to_host_wm;
1130 }
1131
1132- void WindowThread::RenderInterfaceFromForeignCmd(Geometry *clip)
1133+ void WindowThread::PresentWindowsIntersectingGeometryOnThisFrame(Geometry const& rect)
1134+ {
1135+ nuxAssertMsg(IsEmbeddedWindow(),
1136+ "[WindowThread::PresentWindowIntersectingGeometryOnThisFrame] "
1137+ "can only be called inside an embedded window");
1138+
1139+ window_compositor_->ForEachBaseWindow([&rect] (WeakBaseWindowPtr const& w) {
1140+ if (rect.IsIntersecting(w->GetAbsoluteGeometry()))
1141+ w->PresentInEmbeddedModeOnThisFrame(true);
1142+ });
1143+ }
1144+
1145+ void WindowThread::RenderInterfaceFromForeignCmd(Geometry const& clip)
1146 {
1147 nuxAssertMsg(IsEmbeddedWindow() == true, "[WindowThread::RenderInterfaceFromForeignCmd] You can only call RenderInterfaceFromForeignCmd if the window was created with CreateFromForeignWindow.");
1148
1149 if (!IsEmbeddedWindow())
1150 return;
1151-
1152+
1153 IOpenGLShaderProgram::SetShaderTracking(true);
1154
1155 // Set Nux opengl states. The other plugin in compiz have changed the GPU opengl states.
1156@@ -1545,17 +1599,12 @@
1157 GetWindowThread()->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, GetWindowThread()->GetGraphicsEngine().GetWindowWidth(),
1158 GetWindowThread()->GetGraphicsEngine().GetWindowHeight());
1159
1160- if (graphics_display_->IsPauseThreadGraphicsRendering() == false)
1161+ if (!graphics_display_->IsPauseThreadGraphicsRendering())
1162 {
1163 ComputeQueuedLayout();
1164-
1165- if (clip)
1166- GetWindowThread()->GetGraphicsEngine().SetGlobalClippingRectangle(*clip);
1167-
1168+ GetWindowThread()->GetGraphicsEngine().SetGlobalClippingRectangle(clip);
1169 window_compositor_->Draw(window_size_configuration_event_, force_rendering_);
1170-
1171- if (clip)
1172- GetWindowThread()->GetGraphicsEngine().DisableGlobalClippingRectangle();
1173+ GetWindowThread()->GetGraphicsEngine().DisableGlobalClippingRectangle();
1174 // When rendering in embedded mode, nux does not attempt to measure the frame rate...
1175
1176 // Cleanup
1177@@ -1568,17 +1617,38 @@
1178
1179 CHECKGL( glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
1180
1181- graphics_display_->GetGpuDevice()->DeactivateFrameBuffer();
1182 IOpenGLShaderProgram::SetShaderTracking(false);
1183-
1184- if (IsEmbeddedWindow() && window_compositor_->reference_fbo_)
1185+ }
1186+
1187+ void WindowThread::ForeignFrameEnded()
1188+ {
1189+ nuxAssertMsg(IsEmbeddedWindow(),
1190+ "[WindowThread::ForeignFrameEnded] "
1191+ "can only be called inside an embedded window");
1192+
1193+ window_compositor_->ForEachBaseWindow([] (WeakBaseWindowPtr const& w) {
1194+ w->MarkPresentedInEmbeddedMode();
1195+ });
1196+
1197+ presentation_list_embedded_.clear();
1198+
1199+ foreign_frame_frozen_ = false;
1200+
1201+ /* Move all the BaseWindows in presentation_list_embedded_next_frame_
1202+ * to presentation_list_embedded_ and mark them for presentation
1203+ */
1204+ for (auto const& win : presentation_list_embedded_next_frame_)
1205 {
1206- // Restore the reference framebuffer
1207- if (!window_compositor_->RestoreReferenceFramebuffer())
1208- {
1209- nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
1210- }
1211+ if (win.IsValid())
1212+ win->PresentInEmbeddedModeOnThisFrame();
1213 }
1214+
1215+ presentation_list_embedded_next_frame_.clear();
1216+ }
1217+
1218+ void WindowThread::ForeignFrameCutoff()
1219+ {
1220+ foreign_frame_frozen_ = true;
1221 }
1222
1223 int WindowThread::InstallEventInspector(EventInspector function, void* data)
1224
1225=== modified file 'Nux/WindowThread.h'
1226--- Nux/WindowThread.h 2013-04-10 18:56:19 +0000
1227+++ Nux/WindowThread.h 2013-10-31 01:12:55 +0000
1228@@ -32,6 +32,7 @@
1229 namespace nux
1230 {
1231
1232+ class BaseWindow;
1233 class WindowThread;
1234 class Layout;
1235 class HLayout;
1236@@ -216,7 +217,7 @@
1237
1238 @return True if embedded inside Compiz.
1239 */
1240- bool IsEmbeddedWindow();
1241+ bool IsEmbeddedWindow() const;
1242
1243 #if defined(NUX_OS_WINDOWS)
1244 bool ProcessForeignEvent(HWND hWnd, MSG msg, WPARAM wParam, LPARAM lParam, void *data);
1245@@ -227,13 +228,37 @@
1246 #endif
1247
1248 /*!
1249+ In embedded mode, allow presentation on any windows intersecting this
1250+ rect. The effect of this is culmulative for the frame, so it can be
1251+ called multiple times with many different rects until
1252+ RenderInterfaceFromForeignCmd is called.
1253+ \sa IsEmbeddedWindow
1254+
1255+ @param rect Region of the display to consider for presenting windows
1256+ */
1257+ void PresentWindowsIntersectingGeometryOnThisFrame(Geometry const& rect);
1258+
1259+ /*!
1260 Render the interface. This command is send from the pluging when the window thread is embedded.
1261 The clip region matches the surface of one single monitor screen, or a region inside that screen.
1262 \sa IsEmbeddedWindow.
1263
1264 @param clip Region of the display to render.
1265 */
1266- void RenderInterfaceFromForeignCmd(Geometry *clip);
1267+ void RenderInterfaceFromForeignCmd(Geometry const& clip);
1268+
1269+ /*!
1270+ Used to mark the end of the foreign frame. All calls to PresentInEmbeddedModeOnThisFrame
1271+ are now redirected to this upcoming frame where we will be called next.
1272+ */
1273+ void ForeignFrameEnded();
1274+
1275+ /*!
1276+ Used to mark the cutoff point where all calls to PresentInEmbeddedModeOnThisFrame
1277+ should be effective on the next frame, and not this one, because the parent context
1278+ has stopped tracking damage events for this frame
1279+ */
1280+ void ForeignFrameCutoff();
1281
1282 #if !defined(NUX_MINIMAL)
1283 /*!
1284@@ -319,12 +344,20 @@
1285
1286 bool IsRedrawNeeded() const;
1287
1288+ // DrawList - this is a maintained list of areas that will
1289+ // be completely redraw on the next frame
1290 void AddToDrawList(View *view);
1291-
1292 void ClearDrawList();
1293
1294 std::vector<Geometry> const& GetDrawList() const;
1295
1296+ // PresentationList - this is a maintained list of areas that
1297+ // will be presented to the reference framebuffer or backbuffer
1298+ // in embedded mode on the next frame
1299+ bool AddToPresentationList(nux::BaseWindow*, bool force);
1300+
1301+ std::vector<Geometry> GetPresentationListGeometries() const;
1302+
1303 #ifdef NUX_GESTURES_SUPPORT
1304 /*!
1305 Simple wrapper for ProcessEvent for connection with GeisAdapter::event_ready
1306@@ -542,7 +575,24 @@
1307 This list contains the layout that need to be recomputed following the resizing of one of the sub element.
1308 */
1309 std::list<Area *> _queued_layout_list;
1310- std::vector<Geometry> m_dirty_areas;
1311+ std::vector<Geometry> dirty_areas_;
1312+
1313+ typedef nux::ObjectWeakPtr<nux::BaseWindow> WeakBaseWindowPtr;
1314+
1315+ std::vector<WeakBaseWindowPtr> presentation_list_embedded_;
1316+
1317+ /*!
1318+ This list contains al lthe windows which will be presented on the next frame
1319+ (eg, after ForeignFrameEnded they are moved into m_presentation_list_embedded
1320+ and marked for presentation)
1321+ */
1322+ std::vector<WeakBaseWindowPtr> presentation_list_embedded_next_frame_;
1323+
1324+ /*! Whether or not the current frame is "frozen" because the host WM has stopped tracking
1325+ damage events. If so we should put all presentation requests on the next frame instead
1326+ of this one
1327+ */
1328+ bool foreign_frame_frozen_;
1329
1330 //! This variable is true while we are computing the layout the starting from the outmost layout(the Main Layout);
1331 bool _inside_layout_cycle;
1332
1333=== modified file 'NuxCore/Rect.cpp'
1334--- NuxCore/Rect.cpp 2013-04-08 14:02:32 +0000
1335+++ NuxCore/Rect.cpp 2013-10-31 01:12:55 +0000
1336@@ -37,8 +37,8 @@
1337 Rect::Rect(int x_, int y_, int width_, int height_)
1338 : x(x_)
1339 , y(y_)
1340- , width(Max<int> (0, width_))
1341- , height(Max<int> (0, height_))
1342+ , width(std::max<int>(0, width_))
1343+ , height(std::max<int>(0, height_))
1344 {}
1345
1346 Rect::Rect(const Rect &r)
1347@@ -124,23 +124,26 @@
1348 (y <= y_) && (y + height > y_) );
1349 }
1350
1351+ bool Rect::IsIntersecting(const Rect &r) const
1352+ {
1353+ return ! ((r.x > x + width) ||
1354+ (r.x + r.width < x) ||
1355+ (r.y > y + height) ||
1356+ (r.y + r.height < y));
1357+ }
1358+
1359 Rect Rect::Intersect (const Rect &r) const
1360 {
1361 // Get the corner points.
1362
1363- bool intersect = ! ((r.x > x + width) ||
1364- (r.x + r.width < x) ||
1365- (r.y > y + height) ||
1366- (r.y + r.height < y));
1367-
1368- if (intersect)
1369+ if (IsIntersecting(r))
1370 {
1371 const Point &ul1 = Point (x, y);
1372 const Point &ul2 = Point (r.x, r.y);
1373- int xx = Max<int> (ul1.x, ul2.x);
1374- int yy = Max<int> (ul1.y, ul2.y);
1375- int ww = Min<int> (ul1.x + width, ul2.x + r.width) - xx;
1376- int hh = Min<int> (ul1.y + height, ul2.y + r.height) - yy;
1377+ int xx = std::max<int>(ul1.x, ul2.x);
1378+ int yy = std::max<int>(ul1.y, ul2.y);
1379+ int ww = std::min<int>(ul1.x + width, ul2.x + r.width) - xx;
1380+ int hh = std::min<int>(ul1.y + height, ul2.y + r.height) - yy;
1381
1382 return Rect (xx, yy, ww, hh);
1383 }
1384@@ -201,5 +204,10 @@
1385 lhs.height * scalar);
1386 }
1387
1388+ std::ostream& operator<<(std::ostream &os, Rect const& rect)
1389+ {
1390+ return os << "Rect, x: " << rect.x << " y: " << rect.y << " width: " <<
1391+ rect.width << " height: " << rect.height << std::endl;
1392+ }
1393 }
1394
1395
1396=== modified file 'NuxCore/Rect.h'
1397--- NuxCore/Rect.h 2013-04-08 14:02:32 +0000
1398+++ NuxCore/Rect.h 2013-10-31 01:12:55 +0000
1399@@ -49,6 +49,7 @@
1400
1401 bool IsInside(const Point &p) const;
1402 bool IsInside(const Point2D<float> &p) const;
1403+ bool IsIntersecting(const Rect&) const;
1404 Rect Intersect(const Rect &) const;
1405
1406 // expand the width by factor_x and the height by factor_y
1407@@ -105,6 +106,7 @@
1408 if (height < 0)
1409 height = 0;
1410 }
1411+
1412 void OffsetPosition (int dx, int dy)
1413 {
1414 x += dx;
1415@@ -131,6 +133,8 @@
1416 Rect operator-(Rect const& lhs, Rect const& rhs);
1417 Rect operator*(Rect const& lhs, float scalar);
1418
1419+ std::ostream& operator<<(std::ostream &os, Rect const&);
1420+
1421 typedef Rect Geometry;
1422 }
1423
1424
1425=== modified file 'NuxGraphics/GLDeviceFrameBufferObject.cpp'
1426--- NuxGraphics/GLDeviceFrameBufferObject.cpp 2011-10-19 20:32:38 +0000
1427+++ NuxGraphics/GLDeviceFrameBufferObject.cpp 2013-10-31 01:12:55 +0000
1428@@ -65,12 +65,22 @@
1429
1430 void GLFramebufferObject::Bind()
1431 {
1432- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
1433+#ifdef NUX_OPENGLES_20
1434+ GLenum binding = GL_FRAMEBUFFER;
1435+#else
1436+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
1437+#endif
1438+ CHECKGL(glBindFramebufferEXT(binding, m_fboId));
1439 }
1440
1441 void GLFramebufferObject::Disable()
1442 {
1443- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1444+#ifdef NUX_OPENGLES_20
1445+ GLenum binding = GL_FRAMEBUFFER;
1446+#else
1447+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
1448+#endif
1449+ CHECKGL(glBindFramebufferEXT(binding, 0));
1450 }
1451
1452 void
1453@@ -170,11 +180,11 @@
1454 {
1455 #ifndef NUX_OPENGLES_20
1456 // Only binds if m_fboId is different than the currently bound FBO
1457- CHECKGL(glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ));
1458+ CHECKGL(glGetIntegerv( GL_DRAW_FRAMEBUFFER_BINDING_EXT, &m_savedFboId ));
1459
1460 if (m_fboId != m_savedFboId)
1461 {
1462- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId));
1463+ CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fboId));
1464 }
1465 #else
1466 // Only binds if m_fboId is different than the currently bound FBO
1467@@ -189,10 +199,15 @@
1468
1469 void GLFramebufferObject::_GuardedUnbind()
1470 {
1471+#ifdef NUX_OPENGLES_20
1472+ GLenum binding = GL_FRAMEBUFFER;
1473+#else
1474+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
1475+#endif
1476 // Returns FBO binding to the previously enabled FBO
1477 if (m_savedFboId != m_fboId)
1478 {
1479- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint) m_savedFboId));
1480+ CHECKGL(glBindFramebufferEXT(binding, (GLuint) m_savedFboId));
1481 }
1482 }
1483
1484
1485=== modified file 'NuxGraphics/GpuDevice.cpp'
1486--- NuxGraphics/GpuDevice.cpp 2013-05-01 18:12:51 +0000
1487+++ NuxGraphics/GpuDevice.cpp 2013-10-31 01:12:55 +0000
1488@@ -1069,8 +1069,14 @@
1489 return;
1490 }
1491
1492+#ifdef NUX_OPENGLES_20
1493+ GLenum binding = GL_FRAMEBUFFER;
1494+#else
1495+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
1496+#endif
1497+
1498 active_framebuffer_object_.Release();
1499- CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1500+ CHECKGL(glBindFramebufferEXT(binding, 0));
1501 CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
1502 }
1503
1504
1505=== modified file 'NuxGraphics/GpuDeviceTexture.cpp'
1506--- NuxGraphics/GpuDeviceTexture.cpp 2012-11-16 19:11:05 +0000
1507+++ NuxGraphics/GpuDeviceTexture.cpp 2013-10-31 01:12:55 +0000
1508@@ -73,7 +73,7 @@
1509 return result;
1510 }
1511
1512- ObjectPtr<IOpenGLTexture2D> GpuDevice::CreateTexture2DFromID(int /* id */
1513+ ObjectPtr<IOpenGLTexture2D> GpuDevice::CreateTexture2DFromID(int id
1514 , int width
1515 , int height
1516 , int levels
1517@@ -95,6 +95,12 @@
1518
1519 ObjectPtr<IOpenGLTexture2D> result;
1520 result.Adopt(new IOpenGLTexture2D(width, height, levels, pixel_format, true, NUX_FILE_LINE_PARAM));
1521+
1522+ /* Assign the external id to the internal id. This allows us
1523+ * to use the foreign texture as if it were a native one.
1524+ *
1525+ * This is really important. Don't remove it */
1526+ result->_OpenGLID = id;
1527 return result;
1528 }
1529
1530
1531=== modified file 'NuxGraphics/GraphicsEngine.cpp'
1532--- NuxGraphics/GraphicsEngine.cpp 2013-04-08 14:02:32 +0000
1533+++ NuxGraphics/GraphicsEngine.cpp 2013-10-31 01:12:55 +0000
1534@@ -509,7 +509,7 @@
1535 //////////////////////
1536 // DRAW CLIPPING //
1537 //////////////////////
1538- void GraphicsEngine::PushClippingRectangle(Rect rect)
1539+ void GraphicsEngine::PushClippingRectangle(Rect const& rect)
1540 {
1541 if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid())
1542 {
1543@@ -530,7 +530,7 @@
1544
1545 if (stacksize == 0)
1546 {
1547- r1 = Rect(0, 0, window_width, window_height);
1548+ r1.Set(0, 0, window_width, window_height);
1549 }
1550 else
1551 {
1552@@ -552,7 +552,7 @@
1553
1554 if ((x1 > x0) && (y1 > y0))
1555 {
1556- _clipping_rect = Rect(x0, y0, x1 - x0, y1 - y0);
1557+ _clipping_rect.Set(x0, y0, x1 - x0, y1 - y0);
1558 ClippingRect.push_back(Rect(x0, y0, x1 - x0, y1 - y0));
1559
1560 EnableScissoring(true);
1561@@ -560,7 +560,7 @@
1562 }
1563 else
1564 {
1565- _clipping_rect = Rect(0, 0, 0, 0);
1566+ _clipping_rect.Set(0, 0, 0, 0);
1567 ClippingRect.push_back(_clipping_rect);
1568 EnableScissoring(true);
1569 SetOpenGLClippingRectangle(0, 0, 0, 0);
1570@@ -580,7 +580,7 @@
1571
1572 if (stacksize == 0)
1573 {
1574- _clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
1575+ _clipping_rect.Set(0, 0, _viewport.width, _viewport.height);
1576 EnableScissoring(true);
1577 SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height);
1578 }
1579@@ -605,7 +605,7 @@
1580
1581 if (stacksize == 0)
1582 {
1583- _clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
1584+ _clipping_rect.Set(0, 0, _viewport.width, _viewport.height);
1585 EnableScissoring(true);
1586 SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height);
1587 }
1588@@ -628,23 +628,23 @@
1589
1590 ClippingRect.clear();
1591 {
1592- _clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
1593+ _clipping_rect.Set(0, 0, _viewport.width, _viewport.height);
1594 EnableScissoring(true);
1595 SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height);
1596 }
1597 }
1598-
1599- void GraphicsEngine::SetGlobalClippingRectangle(Rect rect)
1600+
1601+ void GraphicsEngine::SetGlobalClippingRectangle(Rect const& rect)
1602 {
1603 _global_clipping_enabled = true;
1604- _global_clipping_rect = Rect(rect.x, _viewport.height - rect.y - rect.height, rect.width, rect.height);
1605+ _global_clipping_rect.Set(rect.x, _viewport.height - rect.y - rect.height, rect.width, rect.height);
1606 ApplyClippingRectangle();
1607 }
1608-
1609+
1610 void GraphicsEngine::DisableGlobalClippingRectangle()
1611 {
1612 _global_clipping_enabled = false;
1613- _global_clipping_rect = Rect(0, 0, _viewport.width, _viewport.height);
1614+ _global_clipping_rect.Set(0, 0, _viewport.width, _viewport.height);
1615 ApplyClippingRectangle();
1616 }
1617
1618@@ -1188,9 +1188,9 @@
1619 CHECKGL(glScissor(_scissor.x, _scissor.y, _scissor.width, _scissor.height));
1620 }
1621
1622- Rect GraphicsEngine::GetScissorRect()
1623+ Rect const& GraphicsEngine::GetScissorRect() const
1624 {
1625- return Rect(_scissor.x, _scissor.y, _scissor.width, _scissor.height);
1626+ return _scissor;
1627 }
1628
1629 void GraphicsEngine::EnableScissoring(bool b)
1630
1631=== modified file 'NuxGraphics/GraphicsEngine.h'
1632--- NuxGraphics/GraphicsEngine.h 2012-11-28 16:44:59 +0000
1633+++ NuxGraphics/GraphicsEngine.h 2013-10-31 01:12:55 +0000
1634@@ -533,13 +533,13 @@
1635 //////////////////////
1636
1637 mutable std::vector<Rect> ClippingRect;
1638- void PushClippingRectangle(Rect rect);
1639+ void PushClippingRectangle(Rect const& rect);
1640 void PopClippingRectangle();
1641 void EmptyClippingRegion();
1642 //! Set the clipping according to the clipping rectangle stack.
1643 void ApplyClippingRectangle();
1644-
1645- void SetGlobalClippingRectangle(Rect rect);
1646+
1647+ void SetGlobalClippingRectangle(Rect const& rect);
1648 void DisableGlobalClippingRectangle();
1649
1650 //! Bypass the clipping rectangle stack and set a different clipping rectangle region.
1651@@ -553,7 +553,7 @@
1652
1653 Rect GetClippingRegion() const;
1654 int GetNumberOfClippingRegions() const;
1655-
1656+
1657 void AddClipOffset(int x, int y); //!< Deprecated. Use PushClipOffset.
1658 void PushClipOffset(int x, int y);
1659 void PopClipOffset();
1660@@ -592,7 +592,7 @@
1661 */
1662 void SetScissorOffset(int x, int y);
1663
1664- Rect GetScissorRect();
1665+ Rect const& GetScissorRect() const;
1666 void EnableScissoring(bool b);
1667
1668
1669
1670=== modified file 'NuxGraphics/IOpenGLFrameBufferObject.cpp'
1671--- NuxGraphics/IOpenGLFrameBufferObject.cpp 2013-05-01 18:13:16 +0000
1672+++ NuxGraphics/IOpenGLFrameBufferObject.cpp 2013-10-31 01:12:55 +0000
1673@@ -336,7 +336,13 @@
1674 // Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil).
1675 int IOpenGLFrameBufferObject::Deactivate()
1676 {
1677- CHECKGL(glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ));
1678+#ifdef NUX_OPENGLES_20
1679+ GLenum binding = GL_FRAMEBUFFER;
1680+#else
1681+ GLenum binding = GL_DRAW_FRAMEBUFFER_EXT;
1682+#endif
1683+
1684+ CHECKGL(glBindFramebufferEXT( binding, 0 ));
1685
1686 #ifndef NUX_OPENGLES_20
1687 CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
1688@@ -352,7 +358,7 @@
1689 return 1;
1690 }
1691
1692- void IOpenGLFrameBufferObject::PushClippingRegion(Rect rect)
1693+ void IOpenGLFrameBufferObject::PushClippingRegion(Rect const& rect)
1694 {
1695 Rect r0;
1696 if (GetGraphicsDisplay()->GetGraphicsEngine())
1697@@ -365,7 +371,7 @@
1698
1699 if (stacksize == 0)
1700 {
1701- current_clip_rect = Rect(0, 0, attachment_width_, attachment_height_);
1702+ current_clip_rect.Set(0, 0, attachment_width_, attachment_height_);
1703 }
1704 else
1705 {
1706@@ -392,7 +398,7 @@
1707 }
1708 else
1709 {
1710- _clipping_rect = Rect(0, 0, 0, 0);
1711+ _clipping_rect.Set(0, 0, 0, 0);
1712 _ClippingRegionStack.push_back(Rect(0, 0, 0, 0));
1713 SetOpenGLClippingRectangle(0, 0, 0, 0);
1714 }
1715@@ -405,7 +411,7 @@
1716
1717 if (stacksize == 0)
1718 {
1719- _clipping_rect = Rect(0, 0, attachment_width_, attachment_height_);
1720+ _clipping_rect.Set(0, 0, attachment_width_, attachment_height_);
1721 SetOpenGLClippingRectangle(0, 0, attachment_width_, attachment_height_);
1722 }
1723 else
1724@@ -420,7 +426,7 @@
1725 {
1726 _ClippingRegionStack.clear();
1727 {
1728- _clipping_rect = Rect(0, 0, attachment_width_, attachment_height_);
1729+ _clipping_rect.Set(0, 0, attachment_width_, attachment_height_);
1730 SetOpenGLClippingRectangle(0, 0, attachment_width_, attachment_height_);
1731 }
1732 }
1733@@ -431,7 +437,7 @@
1734
1735 if (stacksize == 0)
1736 {
1737- _clipping_rect = Rect(0, 0, attachment_width_, attachment_height_);
1738+ _clipping_rect.Set(0, 0, attachment_width_, attachment_height_);
1739 SetOpenGLClippingRectangle(0, 0, attachment_width_, attachment_height_);
1740 }
1741 else
1742@@ -455,7 +461,7 @@
1743 {
1744 if (GetGraphicsDisplay()->GetGraphicsEngine())
1745 {
1746- _clipping_rect = Rect(x, y, width, height);
1747+ _clipping_rect.Set(x, y, width, height);
1748 GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor(x, y, width, height);
1749 }
1750 }
1751
1752=== modified file 'NuxGraphics/IOpenGLFrameBufferObject.h'
1753--- NuxGraphics/IOpenGLFrameBufferObject.h 2013-05-01 01:24:48 +0000
1754+++ NuxGraphics/IOpenGLFrameBufferObject.h 2013-10-31 01:12:55 +0000
1755@@ -58,7 +58,7 @@
1756
1757 // For 2D screen operations
1758 std::vector<Rect> _ClippingRegionStack;
1759- void PushClippingRegion(Rect rect);
1760+ void PushClippingRegion(Rect const& rect);
1761 void PopClippingRegion();
1762 void EmptyClippingRegion();
1763 void ApplyClippingRegion();
1764
1765=== modified file 'configure.ac'
1766--- configure.ac 2013-09-27 18:11:13 +0000
1767+++ configure.ac 2013-10-31 01:12:55 +0000
1768@@ -15,7 +15,7 @@
1769 #
1770 m4_define([nux_major_version], [4])
1771 m4_define([nux_minor_version], [0])
1772-m4_define([nux_micro_version], [3])
1773+m4_define([nux_micro_version], [4])
1774
1775 m4_define([nux_api_version], [4.0])
1776 # Increase the number (to the current date) everytime you propose a branch that breaks the API or ABI
1777@@ -23,8 +23,7 @@
1778 # e.g.: december 5th, 2011 is: 20111205
1779 # To make more than one API change in a day, add a number to the date. Like 20111205.xx
1780
1781-m4_define([nux_abi_version], [20130718.0])
1782-
1783+m4_define([nux_abi_version], [20131029.0])
1784 m4_define([nux_version],
1785 [nux_major_version.nux_minor_version.nux_micro_version])
1786
1787
1788=== modified file 'debian/changelog'
1789--- debian/changelog 2013-10-11 06:15:47 +0000
1790+++ debian/changelog 2013-10-31 01:12:55 +0000
1791@@ -1,3 +1,10 @@
1792+nux (4.0.4-0ubuntu1) UNRELEASED; urgency=low
1793+
1794+ [ Sam Spilsbury ]
1795+ * Bump version to 4.0.4.
1796+
1797+ -- Chris Townsend <christopher.townsend@canonical.com> Tue, 29 Oct 2013 18:12:16 -0400
1798+
1799 nux (4.0.3+13.10.20131011-0ubuntu1) saucy; urgency=low
1800
1801 [ Stephen M. Webb ]
1802
1803=== modified file 'tests/gtest-nux-windowcompositor.cpp'
1804--- tests/gtest-nux-windowcompositor.cpp 2012-11-19 22:24:05 +0000
1805+++ tests/gtest-nux-windowcompositor.cpp 2013-10-31 01:12:55 +0000
1806@@ -145,82 +145,147 @@
1807
1808 namespace
1809 {
1810+ typedef void (*NGLGenFramebuffers)(GLsizei, GLuint *);
1811+ typedef void (*NGLGenRenderbuffers)(GLsizei, GLuint *);
1812+ typedef void (*NGLBindFramebuffer)(GLenum, GLuint);
1813+ typedef void (*NGLBindRenderbuffer)(GLenum, GLuint);
1814+ typedef void (*NGLRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei);
1815+ typedef void (*NGLFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint);
1816+ typedef void (*NGLDeleteFramebuffers)(GLsizei, const GLuint *);
1817+ typedef void (*NGLDeleteRenderbuffers)(GLsizei, const GLuint *);
1818+
1819+ #ifdef NUX_OPENGLES_20
1820+ GLuint NGL_RENDERBUFFER = GL_RENDERBUFFER;
1821+ /* No separate draw or read targets on OpenGL|ES */
1822+ GLuint NGL_DRAW_FRAMEBUFFER = GL_FRAMEBUFFER;
1823+ GLuint NGL_READ_FRAMEBUFFER = GL_FRAMEBUFFER;
1824+ GLuint NGL_DRAW_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING;
1825+ GLuint NGL_READ_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING;
1826+ GLuint NGL_COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0;
1827+ GLuint NGL_RGBA_STORAGE = GL_RGBA4;
1828+ #else
1829+ GLuint NGL_RENDERBUFFER = GL_RENDERBUFFER_EXT;
1830+ GLuint NGL_DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER_EXT;
1831+ GLuint NGL_READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER_EXT;
1832+ GLuint NGL_DRAW_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING_EXT;
1833+ GLuint NGL_READ_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING_EXT;
1834+ GLuint NGL_COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0_EXT;
1835+ GLuint NGL_RGBA_STORAGE = GL_RGBA8_EXT;
1836+ #endif
1837+
1838 class ReferenceFramebuffer
1839 {
1840 public:
1841
1842 ReferenceFramebuffer ()
1843 {
1844- glGenFramebuffersEXT (1, &fboName);
1845- glGenRenderbuffersEXT (1, &rbName);
1846-
1847- glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, rbName);
1848- glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_RGBA8_EXT, 300, 200);
1849- glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fboName);
1850- glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rbName);
1851+ #ifdef NUX_OPENGLES_20
1852+ nglGenFramebuffers = &glGenFramebuffers;
1853+ nglGenRenderbuffers = &glGenRenderbuffers;
1854+ nglBindRenderbuffer = &glBindRenderbuffer;
1855+ nglBindFramebuffer = &glBindFramebuffer;
1856+ nglRenderbufferStorage = &glRenderbufferStorage;
1857+ nglFramebufferRenderbuffer = &glFramebufferRenderbuffer;
1858+ nglDeleteRenderbuffers = &glDeleteRenderbuffers;
1859+ nglDeleteFramebuffers = &glDeleteFramebuffers;
1860+ #else
1861+ nglGenFramebuffers = glGenFramebuffersEXT;
1862+ nglGenRenderbuffers = glGenRenderbuffersEXT;
1863+ nglBindRenderbuffer = glBindRenderbufferEXT;
1864+ nglBindFramebuffer = glBindFramebufferEXT;
1865+ nglRenderbufferStorage = glRenderbufferStorageEXT;
1866+ nglFramebufferRenderbuffer = glFramebufferRenderbufferEXT;
1867+ nglDeleteRenderbuffers = glDeleteRenderbuffersEXT;
1868+ nglDeleteFramebuffers = glDeleteFramebuffersEXT;
1869+ #endif
1870+
1871+ nglGenFramebuffers(1, &fboName);
1872+ nglGenRenderbuffers(1, &rbName);
1873+
1874+ nglBindRenderbuffer(NGL_RENDERBUFFER, rbName);
1875+ nglRenderbufferStorage(NGL_RENDERBUFFER, NGL_RGBA_STORAGE, 300, 200);
1876+ nglBindFramebuffer(NGL_DRAW_FRAMEBUFFER, fboName);
1877+ nglBindFramebuffer(NGL_READ_FRAMEBUFFER, fboName);
1878+ nglFramebufferRenderbuffer(NGL_DRAW_FRAMEBUFFER, NGL_COLOR_ATTACHMENT0, NGL_RENDERBUFFER, rbName);
1879 }
1880
1881 ~ReferenceFramebuffer ()
1882 {
1883- glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
1884- glDeleteRenderbuffers (1, &rbName);
1885- glDeleteRenderbuffers (1, &fboName);
1886+ nglBindFramebuffer(NGL_DRAW_FRAMEBUFFER, 0);
1887+ nglBindFramebuffer(NGL_READ_FRAMEBUFFER, 0);
1888+ nglDeleteRenderbuffers(1, &rbName);
1889+ nglDeleteFramebuffers(1, &fboName);
1890 }
1891
1892- GLuint fboName, rbName;
1893+ GLuint fboName, rbName;
1894+
1895+ /* Each instance of the class needs to keep its own
1896+ * copy of the extension functions as glewInit () needs
1897+ * to be called in the desktop case before they are available */
1898+
1899+ NGLGenFramebuffers nglGenFramebuffers;
1900+ NGLGenRenderbuffers nglGenRenderbuffers;
1901+ NGLBindRenderbuffer nglBindRenderbuffer;
1902+ NGLBindFramebuffer nglBindFramebuffer;
1903+ NGLRenderbufferStorage nglRenderbufferStorage;
1904+ NGLFramebufferRenderbuffer nglFramebufferRenderbuffer;
1905+ NGLDeleteRenderbuffers nglDeleteRenderbuffers;
1906+ NGLDeleteFramebuffers nglDeleteFramebuffers;
1907 };
1908 }
1909+
1910 TEST_F(TestWindowCompositor, TestRestoreReferenceFramebufferDirect)
1911 {
1912 ReferenceFramebuffer reference;
1913- GLint fbBinding;
1914-
1915- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1916-
1917- ASSERT_EQ (fbBinding, reference.fboName);
1918-
1919- wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(fbBinding, nux::Geometry (0, 0, 300, 200));
1920+ GLint dfbBinding, rfbBinding;
1921+
1922+ glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1923+ glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1924+
1925+ ASSERT_EQ (dfbBinding, reference.fboName);
1926+
1927+ wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(dfbBinding, rfbBinding, nux::Geometry (0, 0, 300, 200));
1928
1929 ASSERT_TRUE (wnd_thread->GetWindowCompositor().RestoreReferenceFramebuffer());
1930- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1931- ASSERT_EQ (fbBinding, reference.fboName);
1932+ glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1933+ glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1934+ ASSERT_EQ (dfbBinding, reference.fboName);
1935+ ASSERT_EQ (rfbBinding, reference.fboName);
1936 }
1937
1938 TEST_F(TestWindowCompositor, TestRestoreReferenceFramebufferThroughRestoreMain)
1939 {
1940 ReferenceFramebuffer reference;
1941- GLint fbBinding;
1942-
1943- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1944-
1945- ASSERT_EQ (fbBinding, reference.fboName);
1946-
1947- wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(fbBinding, nux::Geometry (0, 0, 300, 200));
1948+ GLint dfbBinding, rfbBinding;
1949+
1950+ glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1951+ glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1952+
1953+ ASSERT_EQ(dfbBinding, reference.fboName);
1954+
1955+ wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(dfbBinding, rfbBinding, nux::Geometry (0, 0, 300, 200));
1956 wnd_thread->GetWindowCompositor().RestoreMainFramebuffer();
1957- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1958- ASSERT_EQ (fbBinding, reference.fboName);
1959-}
1960-
1961-TEST_F(TestWindowCompositor, TestNoRestoreReferenceFramebufferDirectIfNoReferenceFramebuffer)
1962-{
1963- GLint fbBinding;
1964- ASSERT_FALSE (wnd_thread->GetWindowCompositor().RestoreReferenceFramebuffer());
1965- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1966- ASSERT_EQ (fbBinding, 0);
1967+ glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1968+ glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1969+ ASSERT_EQ(dfbBinding, reference.fboName);
1970+ ASSERT_EQ(rfbBinding, reference.fboName);
1971 }
1972
1973 TEST_F(TestWindowCompositor, TestRestoreBackbufferThroughRestoreMain)
1974 {
1975 ReferenceFramebuffer reference;
1976- GLint fbBinding;
1977-
1978- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1979-
1980- ASSERT_EQ (fbBinding, reference.fboName);
1981+ GLint dfbBinding, rfbBinding;
1982+
1983+ glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1984+ glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1985+
1986+ ASSERT_EQ (dfbBinding, reference.fboName);
1987
1988 wnd_thread->GetWindowCompositor().RestoreMainFramebuffer();
1989- glGetIntegerv (GL_FRAMEBUFFER_BINDING_EXT, &fbBinding);
1990- ASSERT_EQ (fbBinding, 0);
1991+ glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding);
1992+ glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding);
1993+ ASSERT_EQ(dfbBinding, 0);
1994+ ASSERT_EQ(rfbBinding, 0);
1995 }
1996
1997 TEST_F(TestWindowCompositor, TestSetKeyFocusArea)
1998
1999=== modified file 'tests/gtest-nux-windowthread.cpp'
2000--- tests/gtest-nux-windowthread.cpp 2013-02-01 09:14:07 +0000
2001+++ tests/gtest-nux-windowthread.cpp 2013-10-31 01:12:55 +0000
2002@@ -8,18 +8,25 @@
2003 #include <string>
2004 #include <fstream>
2005
2006+#include <memory>
2007 #include <iostream>
2008 #include <gmock/gmock.h>
2009 #include <boost/filesystem.hpp>
2010 #include <glib.h>
2011
2012+#include <X11/X.h>
2013+
2014 #include "Nux/Nux.h"
2015+#include "Nux/View.h"
2016+#include "Nux/HLayout.h"
2017+#include "Nux/ProgramFramework/TestView.h"
2018
2019
2020 using namespace testing;
2021 using ::testing::Invoke;
2022
2023-namespace {
2024+namespace
2025+{
2026
2027 class MockFdDispatch
2028 {
2029@@ -278,5 +285,495 @@
2030 close (pipefd2[1]);
2031 }
2032
2033+class EmbeddedContext : public ::testing::Test
2034+{
2035+ public:
2036+
2037+ EmbeddedContext()
2038+ : _display(XOpenDisplay(NULL))
2039+ , _root(DefaultRootWindow(_display))
2040+ , _window(XCreateSimpleWindow(_display,
2041+ _root,
2042+ 0,
2043+ 0,
2044+ 300,
2045+ 200,
2046+ 0,
2047+ 0,
2048+ 0))
2049+ , _visinfo(NULL)
2050+ , _context(NULL)
2051+ {
2052+ XVisualInfo temp;
2053+ XWindowAttributes attrib;
2054+ if(!XGetWindowAttributes(_display, _window, &attrib))
2055+ throw std::runtime_error("failed to get window attributes");
2056+
2057+ temp.visualid = XVisualIDFromVisual(attrib.visual);
2058+
2059+ int nvinfo = 0;
2060+ _visinfo = XGetVisualInfo(_display, VisualIDMask, &temp, &nvinfo);
2061+
2062+ if (!_visinfo || !nvinfo)
2063+ throw std::runtime_error("failed to find visual");
2064+
2065+#ifndef NUX_OPENGLES_20
2066+ GLint value = 0;
2067+ glXGetConfig(_display, _visinfo, GLX_USE_GL, &value);
2068+
2069+ if (!value)
2070+ std::runtime_error("available visual is not a gl visual");
2071+
2072+ _context = glXCreateContext(_display, _visinfo, NULL, true);
2073+ glXMakeCurrent(_display, _window, _context);
2074+#else
2075+ EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display);
2076+ EGLint major, minor;
2077+ if (!eglInitialize(eglDisplay, &major, &minor))
2078+ throw std::runtime_error("eglInitialize failed");
2079+
2080+ const EGLint config_attribs[] = {
2081+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
2082+ EGL_RED_SIZE, 1,
2083+ EGL_GREEN_SIZE, 1,
2084+ EGL_BLUE_SIZE, 1,
2085+ EGL_ALPHA_SIZE, 0,
2086+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2087+ EGL_CONFIG_CAVEAT, EGL_NONE,
2088+ EGL_STENCIL_SIZE, 1,
2089+ EGL_NONE
2090+ };
2091+
2092+ const EGLint context_attribs[] = {
2093+ EGL_CONTEXT_CLIENT_VERSION, 2,
2094+ EGL_NONE
2095+ };
2096+
2097+ EGLint count, visualid;
2098+ EGLConfig configs[1024];
2099+
2100+ if (!eglChooseConfig(eglDisplay, config_attribs, configs, 1024, &count))
2101+ throw std::runtime_error("eglChooseConfig failed");
2102+
2103+ visualid = temp.visualid;
2104+ EGLConfig config = configs[0];
2105+
2106+ for (int i = 0; i < count; ++i)
2107+ {
2108+ EGLint val;
2109+ eglGetConfigAttrib(eglDisplay, configs[i], EGL_NATIVE_VISUAL_ID, &val);
2110+ if (visualid == val)
2111+ {
2112+ config = configs[i];
2113+ break;
2114+ }
2115+ }
2116+
2117+ eglBindAPI(EGL_OPENGL_ES_API);
2118+ _surface = eglCreateWindowSurface(eglDisplay, config, _window, 0);
2119+ if (_surface == EGL_NO_SURFACE)
2120+ throw std::runtime_error("eglCreateWindowSurface failed");
2121+
2122+ _context = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, context_attribs);
2123+ if (_context == EGL_NO_CONTEXT)
2124+ throw std::runtime_error("eglCreateContext failed");
2125+
2126+ if (!eglMakeCurrent(eglDisplay, _surface, _surface, _context))
2127+ throw std::runtime_error("eglMakeCurrent failed");
2128+#endif
2129+ }
2130+
2131+ MOCK_METHOD0(verifyInit, void());
2132+
2133+ static void nuxInitThreadEntry(nux::NThread *, void *user_data)
2134+ {
2135+ EmbeddedContext *context = reinterpret_cast <EmbeddedContext *> (user_data);
2136+ context->verifyInit();
2137+ }
2138+
2139+ void SetUp ()
2140+ {
2141+ EXPECT_CALL(*this, verifyInit());
2142+ nux::NuxInitialize(0);
2143+ _window_thread.reset(nux::CreateFromForeignWindow(_window,
2144+ _context,
2145+ EmbeddedContext::nuxInitThreadEntry,
2146+ this));
2147+ _window_thread->Run(NULL);
2148+ while (g_main_context_iteration(g_main_context_default(), false));
2149+ }
2150+
2151+ ~EmbeddedContext ()
2152+ {
2153+#ifndef NUX_OPENGLES_20
2154+ glXDestroyContext(_display, _context);
2155+#else
2156+ EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display);
2157+ eglDestroyContext(eglDisplay, _context);
2158+ eglDestroySurface(eglDisplay, _surface);
2159+ eglTerminate(eglDisplay);
2160+#endif
2161+ XDestroyWindow (_display, _window);
2162+ XCloseDisplay (_display);
2163+ }
2164+
2165+ const std::shared_ptr <nux::WindowThread> &
2166+ WindowThread () const
2167+ {
2168+ return _window_thread;
2169+ }
2170+
2171+ private:
2172+
2173+ Display *_display;
2174+ Window _root;
2175+ Window _window;
2176+ XVisualInfo *_visinfo;
2177+#ifndef NUX_OPENGLES_20
2178+ GLXContext _context;
2179+#else
2180+ EGLSurface _surface;
2181+ EGLContext _context;
2182+#endif
2183+
2184+ std::shared_ptr <nux::WindowThread> _window_thread;
2185+};
2186+
2187+TEST_F(EmbeddedContext, WindowThreadIsEmbedded)
2188+{
2189+ EXPECT_TRUE(WindowThread()->IsEmbeddedWindow());
2190+}
2191+
2192+/* There's not a whole lot we can do to test this at the moment
2193+ * since we can't really mock out the behaviour of GraphicsEngine
2194+ */
2195+TEST_F(EmbeddedContext, PresentViewInEmbeddedReadiesForPresentation)
2196+{
2197+ nux::ObjectPtr <nux::BaseWindow> bw(new nux::BaseWindow(TEXT("")));
2198+ bw->ShowWindow(true, false);
2199+ WindowThread()->ForeignFrameEnded();
2200+ bw->PresentInEmbeddedModeOnThisFrame();
2201+ EXPECT_TRUE(bw->AllowPresentationInEmbeddedMode());
2202+}
2203+
2204+TEST_F(EmbeddedContext, QueueDrawOnChildInEmbeddedReadiesForPresentation)
2205+{
2206+ nux::ObjectPtr <nux::BaseWindow> bw(new nux::BaseWindow(TEXT("")));
2207+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2208+ nux::View* view = new nux::TestView("");
2209+ layout->AddView(view, 1);
2210+ bw->SetLayout(layout);
2211+ bw->ShowWindow(true, false);
2212+
2213+ /* Draw command is implicitly queued by ShowWindow, remove it */
2214+ view->DoneRedraw();
2215+ WindowThread()->ForeignFrameEnded();
2216+
2217+ view->QueueDraw();
2218+ EXPECT_TRUE(bw->AllowPresentationInEmbeddedMode());
2219+}
2220+
2221+TEST_F(EmbeddedContext, DonePresentViewInEmbeddedMode)
2222+{
2223+ nux::ObjectPtr <nux::BaseWindow> bw(new nux::BaseWindow(TEXT("")));
2224+ bw->PresentInEmbeddedModeOnThisFrame();
2225+ bw->MarkPresentedInEmbeddedMode();
2226+ EXPECT_FALSE(bw->AllowPresentationInEmbeddedMode());
2227+}
2228+
2229+TEST_F(EmbeddedContext, NoPresentInvisibleOnQueueDraw)
2230+{
2231+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
2232+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2233+ nux::View* view = new nux::TestView("");
2234+ layout->AddView(view, 1);
2235+ window->SetLayout(layout);
2236+ window->ShowWindow(false);
2237+ view->QueueDraw();
2238+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
2239+}
2240+
2241+TEST_F(EmbeddedContext, NoPresentInvisible)
2242+{
2243+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
2244+ window->ShowWindow(false);
2245+ window->PresentInEmbeddedModeOnThisFrame();
2246+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
2247+}
2248+
2249+TEST_F(EmbeddedContext, AllowPresentationSubsequentQueueDraw)
2250+{
2251+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
2252+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2253+ nux::View* view = new nux::TestView("");
2254+ layout->AddView(view, 1);
2255+ window->SetLayout(layout);
2256+
2257+ /* This will call QueueDraw initially and attempt to add
2258+ * the window to the presentation list */
2259+ window->SetGeometry(nux::Geometry(0, 0, 100, 100));
2260+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
2261+
2262+ /* This will call it again */
2263+ window->ShowWindow(true);
2264+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
2265+}
2266+
2267+TEST_F(EmbeddedContext, StillProcessDrawIfInvisible)
2268+{
2269+ nux::ObjectPtr <nux::BaseWindow> window(new nux::BaseWindow(TEXT("")));
2270+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2271+ nux::View* view = new nux::TestView("");
2272+ layout->AddView(view, 1);
2273+ window->SetLayout(layout);
2274+ window->ShowWindow(false);
2275+ view->QueueDraw();
2276+ nux::Geometry clip(0, 0, 100, 100);
2277+ WindowThread()->RenderInterfaceFromForeignCmd(clip);
2278+ EXPECT_FALSE(view->IsRedrawNeeded());
2279+}
2280+
2281+class EmbeddedContextWindow : public EmbeddedContext
2282+{
2283+ public:
2284+
2285+ virtual void SetUp()
2286+ {
2287+ EmbeddedContext::SetUp();
2288+ _base_window = nux::ObjectPtr<nux::BaseWindow>(new nux::BaseWindow(TEXT("")));
2289+ _base_window->ShowWindow(true, false);
2290+
2291+ /* QueueDraw will call PresentInEmbeddedModeOnThisFrame - we
2292+ * need to unset this state in order to test it properly */
2293+ _base_window->MarkPresentedInEmbeddedMode();
2294+ _base_window->DoneRedraw();
2295+ }
2296+
2297+ virtual nux::ObjectPtr <nux::BaseWindow> const &
2298+ Window()
2299+ {
2300+ return _base_window;
2301+ }
2302+
2303+ private:
2304+
2305+ nux::ObjectPtr <nux::BaseWindow> _base_window;
2306+};
2307+
2308+class RedrawRequestVerification
2309+{
2310+ public:
2311+
2312+ MOCK_METHOD0(RedrawRequested, void());
2313+};
2314+
2315+TEST_F(EmbeddedContextWindow, AllowPresentationRequestsRedraw)
2316+{
2317+ RedrawRequestVerification verification;
2318+
2319+ EXPECT_CALL(verification, RedrawRequested());
2320+ WindowThread()->RedrawRequested.connect(sigc::mem_fun (&verification,
2321+ &RedrawRequestVerification::RedrawRequested));
2322+ Window()->PresentInEmbeddedModeOnThisFrame();
2323+}
2324+
2325+TEST_F(EmbeddedContextWindow, AllowPresentationAddsToPresentationList)
2326+{
2327+ Window()->PresentInEmbeddedModeOnThisFrame();
2328+ std::vector <nux::Geometry> present_list(WindowThread()->GetPresentationListGeometries());
2329+
2330+ ASSERT_EQ(1, present_list.size());
2331+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
2332+}
2333+
2334+TEST_F(EmbeddedContextWindow, AfterCutoffAddsToPresentationListNext)
2335+{
2336+ WindowThread()->ForeignFrameEnded();
2337+ WindowThread()->ForeignFrameCutoff();
2338+ ASSERT_TRUE(WindowThread()->GetPresentationListGeometries().empty());
2339+
2340+ Window()->PresentInEmbeddedModeOnThisFrame();
2341+
2342+ EXPECT_TRUE(WindowThread()->GetPresentationListGeometries().empty());
2343+}
2344+
2345+TEST_F(EmbeddedContextWindow, MultipleAllowPresentationAddsToPresentationListUnique)
2346+{
2347+ Window()->PresentInEmbeddedModeOnThisFrame();
2348+ Window()->PresentInEmbeddedModeOnThisFrame();
2349+ std::vector <nux::Geometry> present_list(WindowThread()->GetPresentationListGeometries());
2350+
2351+ ASSERT_EQ(1, present_list.size());
2352+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
2353+}
2354+
2355+TEST_F(EmbeddedContextWindow, OneSetOfGeometryForRePresentOnUnchangedPosition)
2356+{
2357+ Window()->PresentInEmbeddedModeOnThisFrame();
2358+ Window()->MarkPresentedInEmbeddedMode();
2359+ Window()->PresentInEmbeddedModeOnThisFrame();
2360+ std::vector <nux::Geometry> present_list(WindowThread()->GetPresentationListGeometries());
2361+
2362+ ASSERT_EQ(1, present_list.size());
2363+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
2364+}
2365+
2366+TEST_F(EmbeddedContextWindow, TwoSetsOfGeometryForRePresentOnChangedPosition)
2367+{
2368+ Window()->PresentInEmbeddedModeOnThisFrame();
2369+ Window()->MarkPresentedInEmbeddedMode();
2370+ Window()->PresentInEmbeddedModeOnThisFrame();
2371+ Window()->SetBaseX(Window()->GetBaseX() + 1);
2372+ std::vector <nux::Geometry> present_list(WindowThread()->GetPresentationListGeometries());
2373+
2374+ ASSERT_EQ(2, present_list.size());
2375+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
2376+ EXPECT_EQ(present_list[1], Window()->LastPresentedGeometryInEmbeddedMode());
2377+}
2378+
2379+TEST_F(EmbeddedContextWindow, QueueDrawAddsParentToPresentationList)
2380+{
2381+ nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2382+ nux::View* view = new nux::TestView("");
2383+ layout->AddView(view, 1);
2384+ Window()->SetLayout(layout);
2385+ view->QueueDraw();
2386+ std::vector <nux::Geometry> present_list(WindowThread()->GetPresentationListGeometries());
2387+
2388+ ASSERT_EQ(1, present_list.size());
2389+ EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry());
2390+}
2391+
2392+class EmbeddedContextMultiWindow : public EmbeddedContext
2393+{
2394+ public:
2395+
2396+ virtual void SetUp()
2397+ {
2398+ EmbeddedContext::SetUp();
2399+ }
2400+
2401+ const nux::ObjectPtr<nux::BaseWindow> & SpawnWindow()
2402+ {
2403+ _base_windows.push_back(nux::ObjectPtr<nux::BaseWindow>(new nux::BaseWindow(TEXT(""))));
2404+ _base_windows.back()->ShowWindow(true, false);
2405+
2406+ /* QueueDraw will call PresentInEmbeddedModeOnThisFrame - we
2407+ * need to unset this state in order to test it properly */
2408+ _base_windows.back()->MarkPresentedInEmbeddedMode();
2409+ return _base_windows.back();
2410+ }
2411+
2412+ virtual std::vector <nux::ObjectPtr <nux::BaseWindow> > const &
2413+ Windows()
2414+ {
2415+ return _base_windows;
2416+ }
2417+
2418+ private:
2419+
2420+ std::vector <nux::ObjectPtr <nux::BaseWindow> > _base_windows;
2421+};
2422+
2423+TEST_F(EmbeddedContextMultiWindow, PresentIfIntersectsRectOneWindow)
2424+{
2425+ nux::Geometry geo(0, 0, 100, 100);
2426+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
2427+ window->SetGeometry(geo);
2428+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
2429+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
2430+}
2431+
2432+TEST_F(EmbeddedContextMultiWindow, PresentOnlyOneWindow)
2433+{
2434+ nux::Geometry geo(0, 0, 100, 100);
2435+ nux::Geometry outside_geo(0, 101, 100, 100);
2436+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
2437+ nux::ObjectPtr<nux::BaseWindow> outside(SpawnWindow());
2438+ window->SetGeometry(geo);
2439+ outside->SetGeometry(outside_geo);
2440+
2441+ /* Call ForeignFrameEnded to clear the presentation list set up
2442+ * by making windows visible */
2443+ WindowThread()->ForeignFrameEnded();
2444+
2445+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
2446+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
2447+ EXPECT_FALSE(outside->AllowPresentationInEmbeddedMode());
2448+}
2449+
2450+TEST_F(EmbeddedContextMultiWindow, PresentBoth)
2451+{
2452+ nux::Geometry geo(0, 0, 100, 101);
2453+ nux::Geometry other_geo(0, 100, 100, 100);
2454+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
2455+ nux::ObjectPtr<nux::BaseWindow> other(SpawnWindow());
2456+ window->SetGeometry(geo);
2457+ other->SetGeometry(other_geo);
2458+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
2459+ EXPECT_TRUE(window->AllowPresentationInEmbeddedMode());
2460+ EXPECT_TRUE(other->AllowPresentationInEmbeddedMode());
2461+}
2462+
2463+TEST_F(EmbeddedContextMultiWindow, ForeignFrameEndedPresentNone)
2464+{
2465+ nux::Geometry geo(0, 0, 100, 100);
2466+ nux::ObjectPtr<nux::BaseWindow> window(SpawnWindow());
2467+ window->SetGeometry(geo);
2468+ WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo);
2469+ WindowThread()->ForeignFrameEnded();
2470+ EXPECT_FALSE(window->AllowPresentationInEmbeddedMode());
2471+ EXPECT_TRUE(WindowThread()->GetPresentationListGeometries().empty());
2472+}
2473+
2474+TEST_F(EmbeddedContextMultiWindow, AddToPresentationListFailsAfterCutoff)
2475+{
2476+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
2477+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
2478+ WindowThread()->ForeignFrameEnded();
2479+ ASSERT_TRUE(WindowThread()->GetPresentationListGeometries().empty());
2480+ EXPECT_TRUE(WindowThread()->AddToPresentationList(windowOne.GetPointer(), false));
2481+ EXPECT_FALSE(WindowThread()->GetPresentationListGeometries().empty());
2482+ WindowThread()->ForeignFrameCutoff();
2483+ EXPECT_FALSE(WindowThread()->AddToPresentationList(windowTwo.GetPointer(), false));
2484+}
2485+
2486+TEST_F(EmbeddedContextMultiWindow, NoPresentInEmbeddedOnThisFrameAfterFrameCutoff)
2487+{
2488+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
2489+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
2490+ WindowThread()->ForeignFrameEnded();
2491+ windowOne->PresentInEmbeddedModeOnThisFrame();
2492+ WindowThread()->ForeignFrameCutoff();
2493+ windowTwo->PresentInEmbeddedModeOnThisFrame();
2494+ EXPECT_TRUE(windowOne->AllowPresentationInEmbeddedMode());
2495+ EXPECT_FALSE(windowTwo->AllowPresentationInEmbeddedMode());
2496+}
2497+
2498+TEST_F(EmbeddedContextMultiWindow, PresentInEmbeddedOnThisFrameAfterFrameCutoffIfForced)
2499+{
2500+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
2501+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
2502+ WindowThread()->ForeignFrameEnded();
2503+ windowOne->PresentInEmbeddedModeOnThisFrame();
2504+ WindowThread()->ForeignFrameCutoff();
2505+ windowTwo->PresentInEmbeddedModeOnThisFrame(true);
2506+ EXPECT_TRUE(windowOne->AllowPresentationInEmbeddedMode());
2507+ EXPECT_TRUE(windowTwo->AllowPresentationInEmbeddedMode());
2508+}
2509+
2510+TEST_F(EmbeddedContextMultiWindow, MoveToPresentationListAfterFrameEndedIfCaughtInCutoff)
2511+{
2512+ nux::ObjectPtr<nux::BaseWindow> windowOne(SpawnWindow());
2513+ nux::ObjectPtr<nux::BaseWindow> windowTwo(SpawnWindow());
2514+ WindowThread()->ForeignFrameEnded();
2515+ windowOne->PresentInEmbeddedModeOnThisFrame();
2516+ WindowThread()->ForeignFrameCutoff();
2517+ windowTwo->PresentInEmbeddedModeOnThisFrame();
2518+ WindowThread()->ForeignFrameEnded();
2519+ EXPECT_FALSE(windowOne->AllowPresentationInEmbeddedMode());
2520+ EXPECT_TRUE(windowTwo->AllowPresentationInEmbeddedMode());
2521+}
2522+
2523
2524 }
2525
2526=== modified file 'tests/gtest-nuxgraphics-texture.cpp'
2527--- tests/gtest-nuxgraphics-texture.cpp 2013-07-03 22:28:18 +0000
2528+++ tests/gtest-nuxgraphics-texture.cpp 2013-10-31 01:12:55 +0000
2529@@ -60,6 +60,22 @@
2530 }
2531 }
2532
2533+TEST_F(TestTextures, TestCreateTexture2DFromIDAssignemnt)
2534+{
2535+ GLuint texid;
2536+ glGenTextures(1, &texid);
2537+ glBindTexture(GL_TEXTURE_2D, texid);
2538+ nux::ObjectPtr<nux::IOpenGLTexture2D> foreign_texture_as_nux_texture
2539+ (nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(
2540+ texid,
2541+ 1, 1,
2542+ 0,
2543+ nux::BITFMT_B8G8R8A8));
2544+ EXPECT_EQ(texid, foreign_texture_as_nux_texture->GetOpenGLID());
2545+ glBindTexture(GL_TEXTURE_2D, 0);
2546+ glDeleteTextures(1, &texid);
2547+}
2548+
2549 TEST_F(TestTextures, FallbackTexture2DFromFile)
2550 {
2551 ASSERT_THAT(CreateTexture2DFromFile(nullptr, -1, false), IsNull());
2552@@ -102,4 +118,4 @@
2553 ASSERT_THAT(LoadTextureFromFile(std::string()), NotNull());
2554 }
2555
2556-}
2557\ No newline at end of file
2558+}

Subscribers

People subscribed via source and target branches