Merge lp:~unity-team/nux/nux.fix_1091589.1 into lp:nux
- nux.fix_1091589.1
- Merge into trunk
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 |
Related bugs: |
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://
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://
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.
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal | # |
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:
> 40 + {
> 41 + _present_
> 42 + _last_presented
> GetAbsoluteGeom
> 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:
> 46 + {
> 47 + return _last_presented
> 48 + }
> 49 +
> 50 + bool BaseWindow:
> 51 + {
> 52 + return _present_
> 53 + }
>
> Can these methods be const?
>
> + for (WindowList:
> 145 + it != _view_window_
> 146 + ++it)
> 147 + {
> 148 + if (it->IsValid())
> 149 + func (*it);
> 150 + }
>
> Why not a range-based for loop? :)
>
> 206 + void WindowComposito
> draw_fbo_object,
> 207 + unsigned int
> read_fbo_object,
> 208 + Geometry
> fbo_geometry)
>
> Geometry const& fbo... ?
>
> 374 + WindowComposito
> 375 +
> window_
> _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<
> 407 + m_presentation_
> 408 + it != m_presentation_
> 409 + ++it)
> 410 + {
>
> For range-based loop... :)
>
> Btw logic looks good to me.
> --
> https:/
> You are the owner of lp:~smspillaz/nux/nux.fix_1091589.
>
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:
> 40 + {
> 41 + _present_
> 42 + _last_presented
> 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 OnPresentedInEm
>
> 374 + WindowComposito
> 375 + window_
>
> 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::WindowComp
nux::WindowComp
*);
Then the helper function could look something like:
window_
_1, bw, &ptr));
Its basically a glorified:
nux::WindowComp
for (nux::WeakBaseW
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
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:
> > 40 + {
> > 41 + _present_
> > 42 + _last_presented
> GetAbsoluteGeom
> > 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 OnPresentedInEm
Yeah sounds good to me.
>
> >
> > 374 + WindowComposito
> > 375 + window_
> 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::WindowComp
> nux::WindowComp
> *);
>
> Then the helper function could look something like:
>
> window_
> sRawPtr,
> _1, bw, &ptr));
>
> Its basically a glorified:
>
> nux::WindowComp
>
> for (nux::WeakBaseW
> 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
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:757
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:758
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:760
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:761
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:762
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:764
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:792
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
MC Return (mc-return) wrote : Posted in a previous version of this proposal | # |
News:
http://
AMD's fglrx 13.6 Beta driver now also supports GLX_EXT_buffer_age extension !!! \o/
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.
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:/
> You are the owner of lp:~smspillaz/nux/nux.fix_1091589.1.
>
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Thanks for the feedback, done.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:793
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal | # |
I like this function :)
183 + void WindowComposito
Very functional style! One suggestion would be a different name, possibly. MapFunctionOnAl
547 + if (std::find (m_presentation
548 + m_presentation_
549 + ptr) != m_presentation_
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 :)
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 WindowComposito
&func)
>
> Very functional style! One suggestion would be a different name,
possibly. MapFunctionOnAl
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
> 548 + m_presentation_
> 549 + ptr) != m_presentation_
> 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:/
> You are the owner of lp:~smspillaz/nux/nux.fix_1091589.1.
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 :)
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:794
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:796
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:797
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:801
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:802
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 803. By Marco Trevisan (Treviño)
-
Area: some code cleanup into PrepareParentRe
directedView - 804. By Marco Trevisan (Treviño)
-
BaseWindow, WindowThread: some code cleanup
Remove unnededed methods, rename to match their role and use const& in RenderInterface
FromForeignCmd - 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:803
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 806. By Marco Trevisan (Treviño)
-
Nux: use IsIntersecting when possible
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:805
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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 FindWeakBaseWin
dowPtrForRawPtr 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:806
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:810
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:814
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:818
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:819
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Christopher Townsend (townsend) wrote : | # |
Works fine for me. +1
Brandon Schaefer (brandontschaefer) wrote : | # |
LGTM
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
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 | +} |
39 + void BaseWindow: :WasPresentedIn EmbeddedMode( ) in_embedded_ mode = false; _geometry_ in_embedded_ mode = GetAbsoluteGeom etry();
40 + {
41 + _present_
42 + _last_presented
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: :LastPresentedG eometryInEmbedd edMode( ) _geometry_ in_embedded_ mode; :AllowPresentat ionInEmbeddedMo de() in_embedded_ mode;
46 + {
47 + return _last_presented
48 + }
49 +
50 + bool BaseWindow:
51 + {
52 + return _present_
53 + }
Can these methods be const?
+ for (WindowList: :iterator it = _view_window_ list.begin( ); list.end( );
145 + it != _view_window_
146 + ++it)
147 + {
148 + if (it->IsValid())
149 + func (*it);
150 + }
Why not a range-based for loop? :)
206 + void WindowComposito r::SetReference Framebuffer( unsigned int draw_fbo_object,
207 + unsigned int read_fbo_object,
208 + Geometry fbo_geometry)
Geometry const& fbo... ?
374 + WindowComposito r::WeakBaseWind owPtr ptr; compositor_ ->OnAllBaseWind ows(std: :bind(AssignWea kBaseWindowMatc hingRaw, _1, bw, &ptr));
375 + window_
It took me a while to understand what this code was for, maybe we can make it more readable.
406 + for (std::vector< WindowComposito r::WeakBaseWind owPtr>: :iterator it = list_embedded. begin() ; list_embedded. end();
407 + m_presentation_
408 + it != m_presentation_
409 + ++it)
410 + {
For range-based loop... :)
Btw logic looks good to me.