Merge lp:~compiz-team/compiz/compiz.fix_1024304.1 into lp:compiz/0.9.10
- compiz.fix_1024304.1
- Merge into 0.9.10
Status: | Superseded |
---|---|
Proposed branch: | lp:~compiz-team/compiz/compiz.fix_1024304.1 |
Merge into: | lp:compiz/0.9.10 |
Diff against target: |
2383 lines (+1494/-88) 27 files modified
plugins/animation/src/animation.cpp (+1/-1) plugins/composite/CMakeLists.txt (+6/-1) plugins/composite/include/composite/agedamagequery.h (+53/-0) plugins/composite/include/composite/composite.h (+49/-14) plugins/composite/src/backbuffertracking/CMakeLists.txt (+31/-0) plugins/composite/src/backbuffertracking/include/backbuffertracking.h (+125/-0) plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp (+214/-0) plugins/composite/src/backbuffertracking/tests/CMakeLists.txt (+24/-0) plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp (+450/-0) plugins/composite/src/privates.h (+18/-2) plugins/composite/src/screen.cpp (+138/-11) plugins/kdecompat/src/kdecompat.cpp (+2/-2) plugins/opengl/include/opengl/opengl.h (+18/-3) plugins/opengl/src/paint.cpp (+13/-8) plugins/opengl/src/privates.h (+31/-4) plugins/opengl/src/screen.cpp (+301/-30) plugins/opengl/src/window.cpp (+1/-2) plugins/place/src/place.cpp (+1/-2) plugins/resize/src/resize.cpp (+1/-1) plugins/ring/src/ring.cpp (+1/-1) plugins/scale/src/scale.cpp (+3/-1) plugins/staticswitcher/src/staticswitcher.cpp (+1/-1) plugins/switcher/src/switcher.cpp (+1/-1) plugins/td/src/3d.cpp (+1/-1) plugins/water/src/water.cpp (+7/-0) plugins/water/src/water.h (+1/-0) src/window.cpp (+2/-2) |
To merge this branch: | bzr merge lp:~compiz-team/compiz/compiz.fix_1024304.1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Andrea Azzarone | Pending | ||
Esokrates | testing, benchmarking | Pending | |
Daniel van Vugt | Pending | ||
Timo Jyrinki | build&run | Pending | |
Review via email: mp+156466@code.launchpad.net |
This proposal supersedes a proposal from 2013-02-28.
This proposal has been superseded by a proposal from 2013-04-24.
Commit message
Add support for the GLX_EXT_buffer_age extension on hardware that supports it, which should result in a nice speed-boost due to the fact that we no longer have to abuse fillrate by retaining old frame contents, and instead asking the driver how defined the current frame is.
Added external API for plugins to register their own damage tracking objects - with a callback as to whether or not to track the specified damage. This allows plugins that rely on both the retrospective and new damage to the framebuffer to ignore feedback caused by their old damage events.
(LP: #1024304)
Description of the change
Add support for the GLX_EXT_buffer_age extension on hardware that supports it, which should result in a nice speed-boost due to the fact that we no longer have to abuse fillrate by retaining old frame contents, and instead asking the driver how defined the current frame is.
Note: I've marked this needs review for now, but it shouldn't be merged because it confuses unity a fair bit. I've got some branches on unity which will make it work with this code (albeit, the launcher and panel will be re-presented on every frame, but that is what was happening anyways and is harmless for performance).
1. https:/
2. https:/
Note 2: I don't have any solid numbers on this yet. Daniel reported a 10% difference with redirect-
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.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3557
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:3560
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Esokrates (esokrarkose) wrote : Posted in a previous version of this proposal | # |
I have used the ppa containing these changes since the beginning and could confirm the performance improvements using Phoronix Test Suite (and of course my subjective feeling). Comparing benchmarks of compiz 0.9.9.0 and the branch containing the improvements (both disabled "unredirect fullscreen windows") clearly shows that there is an substantial performance improvement.
Part of my benchmark results can be downloaded here:
http://
MC Return (mc-return) wrote : Posted in a previous version of this proposal | # |
The change to debian/changelog seems to be unintended and should probably be removed.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3561
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3563
http://
Executed test runs:
FAILURE: 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 | # |
FAILED: Continuous integration, rev:3563
http://
Executed test runs:
FAILURE: http://
FAILURE: 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:3564
http://
Executed test runs:
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:3565
http://
Executed test runs:
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 | # |
FAILED: Continuous integration, rev:3566
http://
Executed test runs:
FAILURE: 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:3567
http://
Executed test runs:
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 | # |
FAILED: Continuous integration, rev:3568
http://
Executed test runs:
FAILURE: http://
FAILURE: 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:3628
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal | # |
I'm getting a crash on Intel SandyBridge with this branch. At least machine information at bug #1153482 - that was after canceling the first apport dialog. Apport refuses to file the actual compiz .crash file since it notices the version numbers are out of date, but I can send the CoreDump.gz and/or .crash via e-mail.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Don't worry it doesn't matter. I've been told that all
non-insignificant changes to compiz are automatically vetoed at this
point.
On Mon, Mar 11, 2013 at 3:52 PM, Timo Jyrinki
<email address hidden> wrote:
> Review: Needs Fixing
>
> I'm getting a crash on Intel SandyBridge with this branch. At least machine information at bug #1153482 - that was after canceling the first apport dialog. Apport refuses to file the actual compiz .crash file since it notices the version numbers are out of date, but I can send the CoreDump.gz and/or .crash via e-mail.
> --
> https:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Stacktrace would be nice though. Can you get one manually?
On Mon, Mar 11, 2013 at 4:01 PM, Sam Spilsbury <email address hidden> wrote:
> Don't worry it doesn't matter. I've been told that all
> non-insignificant changes to compiz are automatically vetoed at this
> point.
>
> On Mon, Mar 11, 2013 at 3:52 PM, Timo Jyrinki
> <email address hidden> wrote:
>> Review: Needs Fixing
>>
>> I'm getting a crash on Intel SandyBridge with this branch. At least machine information at bug #1153482 - that was after canceling the first apport dialog. Apport refuses to file the actual compiz .crash file since it notices the version numbers are out of date, but I can send the CoreDump.gz and/or .crash via e-mail.
>> --
>> https:/
>> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>
>
>
> --
> Sam Spilsbury
--
Sam Spilsbury
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal | # |
Sorry, PEBKAC, recompiled Unity against it and now it works. I don't have a raring machine where I could test the actual functionality, but seems to work on Intel identically to before.
So approved with regards to build / run on Intel without GLX_EXT_buffer_age.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Ah, cool that you got it working on intel hw.
Unfortunately my understanding is that this won't go in for raring. It requires both a Unity and Nux change in order to ensure that there isn't a performance /regression/ (because of Unity's brain-dead damageScreen-
Sadly, the ps-team had three months to review these changes and I kept them up-to-date during that entire time, but the feet-dragging has effectively meant its come to a point where they won't be merged :(
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal | # |
Does this branch depends on? https:/
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal | # |
Andrea: I don't think so (I might be wrong), but these are surely required to go in together with this:
https:/
https:/
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
@Timo: at the moment, it kinda pulls in https:/
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal | # |
> @Timo: at the moment, it kinda pulls in https:/
> team/compiz/
> https:/
> with the former in mind. If we're still interested in getting this is (I'd be
> happy if we were) I can do a quick refactor to try and remove the dependency.
Yes, please. If we can get this into a mergeable state in the next week there's a good chance we can get it in by final beta freeze (March 28). Otherwise, it's still worth getting in post-13.04
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
On Thu, Mar 21, 2013 at 9:14 PM, Andrea Azzarone <email address hidden> wrote:
>> @Timo: at the moment, it kinda pulls in https:/
>> team/compiz/
>> https:/
>> with the former in mind. If we're still interested in getting this is (I'd be
>> happy if we were) I can do a quick refactor to try and remove the dependency.
>
> Yes, please. If we can get this into a mergeable state in the next week there's a good chance we can get it in by final beta freeze (March 28). Otherwise, it's still worth getting in post-13.04
:) Alrighty, glad to see this resolved. Is it cleared with distro?
> --
> https:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
--
Sam Spilsbury
Didier Roche-Tolomelli (didrocks) wrote : Posted in a previous version of this proposal | # |
Hey Sam, do you mind talking to duflu and see if he gets time to review this branch? If he's happy with it, we can get it in.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
I think Daniel is busy on other projects. Subscribe him if you want, but I
think this should be left to the main legacy stack maintainers.
On 21/03/2013 11:39 PM, "Didier Roche" <email address hidden> wrote:
> Hey Sam, do you mind talking to duflu and see if he gets time to review
> this branch? If he's happy with it, we can get it in.
> --
>
> https:/
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Okay, so the unity branch should only depend on this one now.
Though the other one is certainly a nice to have - it means we don't have to read out the bindings from opengl in unity.
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Please re-target this for lp:compiz/0.9.10
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3628
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sam Spilsbury (smspillaz) wrote : | # |
Okay, so I've talked to Didier about this and we've come up with a small plan of action. We'll need to give this a week solid of QA at the beginning of the S cycle and then make sure that we don't have any AP regressions. That'll happen in about two weeks.
- 3632. By Sam Spilsbury
-
Merge lp:compiz
- 3633. By Sam Spilsbury
-
Merge lp:compiz
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3633
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 3634. By Sam Spilsbury
-
Merge lp:compiz
- 3635. By Sam Spilsbury
-
Fix typo
- 3636. By Sam Spilsbury
-
We reset the frame provider at the end of glXInitContext, no need to do
it before that in the GLES case - 3637. By Sam Spilsbury
-
Revert unrelated changes, unrevert some unintentional changes to
window.cpp - 3638. By Sam Spilsbury
-
Merge lp:compiz
- 3639. By Sam Spilsbury
-
Merge lp:compiz
- 3640. By Sam Spilsbury
-
Merge lp:compiz
- 3641. By Sam Spilsbury
-
Revert introduction of PAINT_WINDOW_
NO_DRAW_ MASKS. It isn't entirely
relevant here. - 3642. By Sam Spilsbury
-
Merge lp:compiz
- 3643. By Sam Spilsbury
-
Rename addOverdrawDama
geRegion to recordDamageOnC urrentFrame and tidy
up some formatting - 3644. By Sam Spilsbury
-
Allow an empty callback argument to getDamageQuery. Makes the plugin API
simpler - 3645. By Sam Spilsbury
-
Merge lp:compiz
- 3646. By Sam Spilsbury
-
Merge lp:compiz
- 3647. By Sam Spilsbury
-
Merge lp:compiz
Unmerged revisions
- 3647. By Sam Spilsbury
-
Merge lp:compiz
- 3646. By Sam Spilsbury
-
Merge lp:compiz
- 3645. By Sam Spilsbury
-
Merge lp:compiz
- 3644. By Sam Spilsbury
-
Allow an empty callback argument to getDamageQuery. Makes the plugin API
simpler - 3643. By Sam Spilsbury
-
Rename addOverdrawDama
geRegion to recordDamageOnC urrentFrame and tidy
up some formatting - 3642. By Sam Spilsbury
-
Merge lp:compiz
- 3641. By Sam Spilsbury
-
Revert introduction of PAINT_WINDOW_
NO_DRAW_ MASKS. It isn't entirely
relevant here. - 3640. By Sam Spilsbury
-
Merge lp:compiz
- 3639. By Sam Spilsbury
-
Merge lp:compiz
- 3638. By Sam Spilsbury
-
Merge lp:compiz
Preview Diff
1 | === modified file 'plugins/animation/src/animation.cpp' |
2 | --- plugins/animation/src/animation.cpp 2013-02-27 11:33:10 +0000 |
3 | +++ plugins/animation/src/animation.cpp 2013-04-24 14:57:28 +0000 |
4 | @@ -1617,7 +1617,7 @@ |
5 | // Is this the first glPaint call this round |
6 | // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK? |
7 | if (mPAScreen->mStartingNewPaintRound && |
8 | - !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)) |
9 | + !(mask & PAINT_WINDOW_NO_DRAW_MASKS)) |
10 | { |
11 | mPAScreen->mStartingNewPaintRound = false; |
12 | |
13 | |
14 | === modified file 'plugins/composite/CMakeLists.txt' |
15 | --- plugins/composite/CMakeLists.txt 2012-09-25 01:15:36 +0000 |
16 | +++ plugins/composite/CMakeLists.txt 2013-04-24 14:57:28 +0000 |
17 | @@ -2,9 +2,14 @@ |
18 | |
19 | include (CompizPlugin) |
20 | |
21 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) |
22 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/pixmapbinding/include) |
23 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking/include) |
24 | + |
25 | link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/pixmapbinding) |
26 | +link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/backbuffertracking) |
27 | |
28 | -compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding) |
29 | +compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding compiz_composite_backbuffertracking) |
30 | |
31 | add_subdirectory (src/pixmapbinding) |
32 | +add_subdirectory (src/backbuffertracking) |
33 | |
34 | === added file 'plugins/composite/include/composite/agedamagequery.h' |
35 | --- plugins/composite/include/composite/agedamagequery.h 1970-01-01 00:00:00 +0000 |
36 | +++ plugins/composite/include/composite/agedamagequery.h 2013-04-24 14:57:28 +0000 |
37 | @@ -0,0 +1,53 @@ |
38 | +/* |
39 | + * Compiz, composite plugin, GLX_EXT_buffer_age logic |
40 | + * |
41 | + * Copyright (c) 2012 Sam Spilsbury |
42 | + * Authors: Sam Spilsbury <smspillaz@gmail.com> |
43 | + * |
44 | + * Permission is hereby granted, free of charge, to any person obtaining a |
45 | + * copy of this software and associated documentation files (the "Software"), |
46 | + * to deal in the Software without restriction, including without limitation |
47 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
48 | + * and/or sell copies of the Software, and to permit persons to whom the |
49 | + * Software is furnished to do so, subject to the following conditions: |
50 | + * |
51 | + * The above copyright notice and this permission notice shall be included in |
52 | + * all copies or substantial portions of the Software. |
53 | + * |
54 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
55 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
56 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
57 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
58 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
59 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
60 | + * DEALINGS IN THE SOFTWARE. |
61 | + */ |
62 | +#ifndef _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H |
63 | +#define _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H |
64 | + |
65 | +#include <boost/shared_ptr.hpp> |
66 | +#include <core/region.h> |
67 | + |
68 | +namespace compiz |
69 | +{ |
70 | +namespace composite |
71 | +{ |
72 | +namespace buffertracking |
73 | +{ |
74 | +class AgeDamageQuery |
75 | +{ |
76 | + public: |
77 | + |
78 | + typedef boost::shared_ptr <AgeDamageQuery> Ptr; |
79 | + typedef boost::function <bool (const CompRegion &)> AreaShouldBeMarkedDirty; |
80 | + |
81 | + virtual ~AgeDamageQuery () {} |
82 | + virtual CompRegion damageForFrameAge (unsigned int) = 0; |
83 | + virtual const CompRegion & currentFrameDamage () = 0; |
84 | +}; |
85 | +} |
86 | +} |
87 | +} |
88 | + |
89 | +#endif |
90 | + |
91 | |
92 | === modified file 'plugins/composite/include/composite/composite.h' |
93 | --- plugins/composite/include/composite/composite.h 2012-10-16 05:11:10 +0000 |
94 | +++ plugins/composite/include/composite/composite.h 2013-04-24 14:57:28 +0000 |
95 | @@ -30,7 +30,7 @@ |
96 | |
97 | #include <X11/extensions/Xcomposite.h> |
98 | |
99 | -#define COMPIZ_COMPOSITE_ABI 5 |
100 | +#define COMPIZ_COMPOSITE_ABI 6 |
101 | |
102 | #include "core/pluginclasshandler.h" |
103 | #include "core/timer.h" |
104 | @@ -38,6 +38,8 @@ |
105 | #include "core/screen.h" |
106 | #include "core/wrapsystem.h" |
107 | |
108 | +#include "composite/agedamagequery.h" |
109 | + |
110 | #define COMPOSITE_SCREEN_DAMAGE_PENDING_MASK (1 << 0) |
111 | #define COMPOSITE_SCREEN_DAMAGE_REGION_MASK (1 << 1) |
112 | #define COMPOSITE_SCREEN_DAMAGE_ALL_MASK (1 << 2) |
113 | @@ -98,18 +100,19 @@ |
114 | namespace composite |
115 | { |
116 | class PaintHandler { |
117 | -public: |
118 | - virtual ~PaintHandler () {}; |
119 | - |
120 | - virtual void paintOutputs (CompOutput::ptrList &outputs, |
121 | - unsigned int mask, |
122 | - const CompRegion ®ion) = 0; |
123 | - |
124 | - virtual bool hasVSync () { return false; }; |
125 | - virtual bool requiredForcedRefreshRate () { return false; }; |
126 | - |
127 | - virtual void prepareDrawing () {}; |
128 | - virtual bool compositingActive () { return false; }; |
129 | + public: |
130 | + virtual ~PaintHandler () {}; |
131 | + |
132 | + virtual void paintOutputs (CompOutput::ptrList &outputs, |
133 | + unsigned int mask, |
134 | + const CompRegion ®ion) = 0; |
135 | + |
136 | + virtual bool hasVSync () { return false; }; |
137 | + virtual bool requiredForcedRefreshRate () { return false; }; |
138 | + |
139 | + virtual void prepareDrawing () {}; |
140 | + virtual bool compositingActive () { return false; }; |
141 | + virtual unsigned int getFrameAge () { return 1; } |
142 | }; |
143 | } |
144 | } |
145 | @@ -173,12 +176,19 @@ |
146 | * Hookable function to damage regions directly |
147 | */ |
148 | virtual void damageRegion (const CompRegion &r); |
149 | + |
150 | + /** |
151 | + * Hookable function to notify plugins that the last damage |
152 | + * event for this frame has been received, and all further damage |
153 | + * events will be for the next frame |
154 | + */ |
155 | + virtual void damageCutoff (); |
156 | }; |
157 | |
158 | extern template class PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>; |
159 | |
160 | class CompositeScreen : |
161 | - public WrapableHandler<CompositeScreenInterface, 7>, |
162 | + public WrapableHandler<CompositeScreenInterface, 8>, |
163 | public PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>, |
164 | public CompOption::Class |
165 | { |
166 | @@ -203,6 +213,24 @@ |
167 | void damageScreen (); |
168 | |
169 | void damagePending (); |
170 | + |
171 | + /** |
172 | + * Causes the damage that was recorded on N - 1 number of |
173 | + * frames ago to be added to the current frame, applied |
174 | + * culmulatively. An age of "zero" means that the entire frame |
175 | + * is considered undefined and must be completely repaired, |
176 | + * wheras an age of 1 means that this frame is the same as the |
177 | + * last frame, so no damage is required. |
178 | + */ |
179 | + void applyDamageForFrameAge (unsigned int); |
180 | + unsigned int getFrameAge (); |
181 | + void addOverdrawDamageRegion (const CompRegion &); |
182 | + |
183 | + typedef compiz::composite::buffertracking::AgeDamageQuery DamageQuery; |
184 | + typedef DamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty; |
185 | + |
186 | + DamageQuery::Ptr |
187 | + getDamageQuery (const AreaShouldBeMarkedDirty &callback); |
188 | |
189 | |
190 | unsigned int damageMask (); |
191 | @@ -248,6 +276,7 @@ |
192 | * event loop |
193 | */ |
194 | WRAPABLE_HND (6, CompositeScreenInterface, void, damageRegion, const CompRegion &); |
195 | + WRAPABLE_HND (7, CompositeScreenInterface, void, damageCutoff); |
196 | |
197 | friend class PrivateCompositeDisplay; |
198 | |
199 | @@ -310,6 +339,12 @@ |
200 | */ |
201 | #define PAINT_WINDOW_BLEND_MASK (1 << 19) |
202 | |
203 | +/** |
204 | + * flags that would indicate the window is never actually drawn |
205 | + */ |
206 | +#define PAINT_WINDOW_NO_DRAW_MASKS (PAINT_WINDOW_OCCLUSION_DETECTION_MASK | \ |
207 | + PAINT_WINDOW_NO_CORE_INSTANCE_MASK) |
208 | + |
209 | class CompositeWindowInterface; |
210 | extern template class WrapableInterface<CompositeWindow, CompositeWindowInterface>; |
211 | |
212 | |
213 | === added directory 'plugins/composite/src/backbuffertracking' |
214 | === added file 'plugins/composite/src/backbuffertracking/CMakeLists.txt' |
215 | --- plugins/composite/src/backbuffertracking/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
216 | +++ plugins/composite/src/backbuffertracking/CMakeLists.txt 2013-04-24 14:57:28 +0000 |
217 | @@ -0,0 +1,31 @@ |
218 | +INCLUDE_DIRECTORIES ( |
219 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../include |
220 | + ${CMAKE_CURRENT_SOURCE_DIR}/include |
221 | + ${CMAKE_CURRENT_SOURCE_DIR}/src |
222 | + |
223 | + ${Boost_INCLUDE_DIRS} |
224 | +) |
225 | + |
226 | +LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS}) |
227 | + |
228 | +SET( |
229 | + SRCS |
230 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking.cpp |
231 | +) |
232 | + |
233 | +ADD_LIBRARY( |
234 | + compiz_composite_backbuffertracking STATIC |
235 | + |
236 | + ${SRCS} |
237 | +) |
238 | + |
239 | +if (COMPIZ_BUILD_TESTING) |
240 | +ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests ) |
241 | +endif (COMPIZ_BUILD_TESTING) |
242 | + |
243 | +TARGET_LINK_LIBRARIES( |
244 | + compiz_composite_backbuffertracking |
245 | + |
246 | + compiz_size |
247 | + compiz_core |
248 | +) |
249 | |
250 | === added directory 'plugins/composite/src/backbuffertracking/include' |
251 | === added file 'plugins/composite/src/backbuffertracking/include/backbuffertracking.h' |
252 | --- plugins/composite/src/backbuffertracking/include/backbuffertracking.h 1970-01-01 00:00:00 +0000 |
253 | +++ plugins/composite/src/backbuffertracking/include/backbuffertracking.h 2013-04-24 14:57:28 +0000 |
254 | @@ -0,0 +1,125 @@ |
255 | +/* |
256 | + * Compiz, composite plugin, GLX_EXT_buffer_age logic |
257 | + * |
258 | + * Copyright (c) 2012 Sam Spilsbury |
259 | + * Authors: Sam Spilsbury <smspillaz@gmail.com> |
260 | + * |
261 | + * Permission is hereby granted, free of charge, to any person obtaining a |
262 | + * copy of this software and associated documentation files (the "Software"), |
263 | + * to deal in the Software without restriction, including without limitation |
264 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
265 | + * and/or sell copies of the Software, and to permit persons to whom the |
266 | + * Software is furnished to do so, subject to the following conditions: |
267 | + * |
268 | + * The above copyright notice and this permission notice shall be included in |
269 | + * all copies or substantial portions of the Software. |
270 | + * |
271 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
272 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
273 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
274 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
275 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
276 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
277 | + * DEALINGS IN THE SOFTWARE. |
278 | + */ |
279 | +#ifndef _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H |
280 | +#define _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H |
281 | + |
282 | +#include <memory> |
283 | +#include <boost/noncopyable.hpp> |
284 | +#include <boost/shared_ptr.hpp> |
285 | +#include <boost/weak_ptr.hpp> |
286 | +#include <boost/function.hpp> |
287 | + |
288 | +#include <composite/agedamagequery.h> |
289 | + |
290 | +class CompSize; |
291 | +class CompRegion; |
292 | + |
293 | +namespace compiz |
294 | +{ |
295 | +namespace composite |
296 | +{ |
297 | +namespace buffertracking |
298 | +{ |
299 | +class DamageAgeTracking |
300 | +{ |
301 | + public: |
302 | + |
303 | + virtual ~DamageAgeTracking () {}; |
304 | + virtual void dirtyAreaOnCurrentFrame (const CompRegion &) = 0; |
305 | + virtual void overdrawRegionOnPaintingFrame (const CompRegion &) = 0; |
306 | + virtual void subtractObscuredArea (const CompRegion &) = 0; |
307 | + virtual void incrementFrameAges () = 0; |
308 | +}; |
309 | + |
310 | +class AgeingDamageBufferObserver |
311 | +{ |
312 | + public: |
313 | + |
314 | + virtual ~AgeingDamageBufferObserver () {}; |
315 | + virtual void observe (DamageAgeTracking &damageAgeTracker) = 0; |
316 | + virtual void unobserve (DamageAgeTracking &damageAgeTracker) = 0; |
317 | +}; |
318 | + |
319 | +class AgeingDamageBuffers : |
320 | + public AgeingDamageBufferObserver, |
321 | + boost::noncopyable |
322 | +{ |
323 | + public: |
324 | + |
325 | + AgeingDamageBuffers (); |
326 | + |
327 | + void observe (DamageAgeTracking &damageAgeTracker); |
328 | + void unobserve (DamageAgeTracking &damageAgeTracker); |
329 | + void incrementAges (); |
330 | + void markAreaDirty (const CompRegion ®); |
331 | + void markAreaDirtyOnLastFrame (const CompRegion ®); |
332 | + void subtractObscuredArea (const CompRegion ®); |
333 | + |
334 | + private: |
335 | + |
336 | + class Private; |
337 | + std::auto_ptr <Private> priv; |
338 | +}; |
339 | + |
340 | +class FrameRoster : |
341 | + public DamageAgeTracking, |
342 | + public AgeDamageQuery, |
343 | + boost::noncopyable |
344 | +{ |
345 | + public: |
346 | + |
347 | + typedef AgeDamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty; |
348 | + typedef boost::shared_ptr <FrameRoster> Ptr; |
349 | + |
350 | + FrameRoster (const CompSize &size, |
351 | + AgeingDamageBufferObserver &tracker, |
352 | + const AreaShouldBeMarkedDirty &shouldMarkDirty); |
353 | + |
354 | + ~FrameRoster (); |
355 | + |
356 | + void dirtyAreaOnCurrentFrame (const CompRegion &); |
357 | + void overdrawRegionOnPaintingFrame (const CompRegion &); |
358 | + void subtractObscuredArea (const CompRegion &); |
359 | + void incrementFrameAges (); |
360 | + CompRegion damageForFrameAge (unsigned int); |
361 | + const CompRegion & currentFrameDamage (); |
362 | + |
363 | + class Private; |
364 | + std::auto_ptr <Private> priv; |
365 | + |
366 | + static const unsigned int NUM_TRACKED_FRAMES = 10; |
367 | + |
368 | + static |
369 | + FrameRoster::Ptr create (const CompSize &size, |
370 | + |
371 | + const AreaShouldBeMarkedDirty &shouldMarkDirty); |
372 | + |
373 | + private: |
374 | + |
375 | +}; |
376 | +} // namespace buffertracking |
377 | +} // namespace composite |
378 | +} // namespace compiz |
379 | +#endif |
380 | |
381 | === added directory 'plugins/composite/src/backbuffertracking/src' |
382 | === added file 'plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp' |
383 | --- plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 1970-01-01 00:00:00 +0000 |
384 | +++ plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 2013-04-24 14:57:28 +0000 |
385 | @@ -0,0 +1,214 @@ |
386 | +/* |
387 | + * Compiz, composite plugin, GLX_EXT_buffer_age logic |
388 | + * |
389 | + * Copyright (c) 2012 Sam Spilsbury |
390 | + * Authors: Sam Spilsbury <smspillaz@gmail.com> |
391 | + * |
392 | + * Permission is hereby granted, free of charge, to any person obtaining a |
393 | + * copy of this software and associated documentation files (the "Software"), |
394 | + * to deal in the Software without restriction, including without limitation |
395 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
396 | + * and/or sell copies of the Software, and to permit persons to whom the |
397 | + * Software is furnished to do so, subject to the following conditions: |
398 | + * |
399 | + * The above copyright notice and this permission notice shall be included in |
400 | + * all copies or substantial portions of the Software. |
401 | + * |
402 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
403 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
404 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
405 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
406 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
407 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
408 | + * DEALINGS IN THE SOFTWARE. |
409 | + */ |
410 | +#include <deque> |
411 | +#include <core/size.h> |
412 | +#include <core/region.h> |
413 | +#include "backbuffertracking.h" |
414 | +#include <cstdio> |
415 | + |
416 | +namespace bt = compiz::composite::buffertracking; |
417 | + |
418 | +class bt::FrameRoster::Private |
419 | +{ |
420 | + public: |
421 | + |
422 | + Private (const CompSize &size, |
423 | + bt::AgeingDamageBufferObserver &observer, |
424 | + const bt::FrameRoster::AreaShouldBeMarkedDirty &shouldBeMarkedDirty) : |
425 | + screenSize (size), |
426 | + observer (observer), |
427 | + shouldBeMarkedDirty (shouldBeMarkedDirty), |
428 | + oldFrames (1) |
429 | + { |
430 | + } |
431 | + |
432 | + CompSize screenSize; |
433 | + bt::AgeingDamageBufferObserver &observer; |
434 | + bt::FrameRoster::AreaShouldBeMarkedDirty shouldBeMarkedDirty; |
435 | + std::deque <CompRegion> oldFrames; |
436 | +}; |
437 | + |
438 | +bt::FrameRoster::FrameRoster (const CompSize &size, |
439 | + bt::AgeingDamageBufferObserver &tracker, |
440 | + const AreaShouldBeMarkedDirty &shouldBeMarkedDirty) : |
441 | + priv (new bt::FrameRoster::Private (size, |
442 | + tracker, |
443 | + shouldBeMarkedDirty)) |
444 | +{ |
445 | + priv->observer.observe (*this); |
446 | +} |
447 | + |
448 | +bt::FrameRoster::~FrameRoster () |
449 | +{ |
450 | + priv->observer.unobserve (*this); |
451 | +} |
452 | + |
453 | +CompRegion |
454 | +bt::FrameRoster::damageForFrameAge (unsigned int age) |
455 | +{ |
456 | + if (!age) |
457 | + return CompRegion (0, 0, |
458 | + priv->screenSize.width (), |
459 | + priv->screenSize.height ()); |
460 | + |
461 | + if (age >= priv->oldFrames.size ()) |
462 | + return CompRegion (0, 0, |
463 | + priv->screenSize.width (), |
464 | + priv->screenSize.height ()); |
465 | + |
466 | + CompRegion accumulatedDamage; |
467 | + |
468 | + while (age--) |
469 | + { |
470 | + unsigned int frameNum = (priv->oldFrames.size () - age) - 1; |
471 | + accumulatedDamage += priv->oldFrames[frameNum]; |
472 | + } |
473 | + |
474 | + return accumulatedDamage; |
475 | +} |
476 | + |
477 | +void |
478 | +bt::FrameRoster::dirtyAreaOnCurrentFrame (const CompRegion &r) |
479 | +{ |
480 | + if (priv->shouldBeMarkedDirty (r)) |
481 | + (*priv->oldFrames.rbegin ()) += r; |
482 | +} |
483 | + |
484 | +void |
485 | +bt::FrameRoster::subtractObscuredArea (const CompRegion &r) |
486 | +{ |
487 | + (*priv->oldFrames.rbegin ()) -= r; |
488 | +} |
489 | + |
490 | +void |
491 | +bt::FrameRoster::overdrawRegionOnPaintingFrame (const CompRegion &r) |
492 | +{ |
493 | + assert (priv->oldFrames.size () > 1); |
494 | + std::deque <CompRegion>::reverse_iterator it = priv->oldFrames.rbegin (); |
495 | + ++it; |
496 | + (*it) += r; |
497 | +} |
498 | + |
499 | +void |
500 | +bt::FrameRoster::incrementFrameAges () |
501 | +{ |
502 | + priv->oldFrames.push_back (CompRegion ()); |
503 | + |
504 | + /* Get rid of old frames */ |
505 | + if (priv->oldFrames.size () > NUM_TRACKED_FRAMES) |
506 | + priv->oldFrames.pop_front (); |
507 | +} |
508 | + |
509 | +const CompRegion & |
510 | +bt::FrameRoster::currentFrameDamage () |
511 | +{ |
512 | + return *priv->oldFrames.rbegin (); |
513 | +} |
514 | + |
515 | +class bt::AgeingDamageBuffers::Private |
516 | +{ |
517 | + public: |
518 | + |
519 | + std::vector <bt::DamageAgeTracking *> damageAgeTrackers; |
520 | +}; |
521 | + |
522 | +bt::AgeingDamageBuffers::AgeingDamageBuffers () : |
523 | + priv (new bt::AgeingDamageBuffers::Private ()) |
524 | +{ |
525 | +} |
526 | + |
527 | +void |
528 | +bt::AgeingDamageBuffers::observe (bt::DamageAgeTracking &damageAgeTracker) |
529 | +{ |
530 | + priv->damageAgeTrackers.push_back (&damageAgeTracker); |
531 | +} |
532 | + |
533 | +void |
534 | +bt::AgeingDamageBuffers::unobserve (bt::DamageAgeTracking &damageAgeTracker) |
535 | +{ |
536 | + std::vector <bt::DamageAgeTracking *>::iterator it = |
537 | + std::find (priv->damageAgeTrackers.begin (), |
538 | + priv->damageAgeTrackers.end (), |
539 | + &damageAgeTracker); |
540 | + |
541 | + if (it != priv->damageAgeTrackers.end ()) |
542 | + priv->damageAgeTrackers.erase (it); |
543 | +} |
544 | + |
545 | +void |
546 | +bt::AgeingDamageBuffers::incrementAges () |
547 | +{ |
548 | + for (std::vector <bt::DamageAgeTracking *>::iterator it = |
549 | + priv->damageAgeTrackers.begin (); |
550 | + it != priv->damageAgeTrackers.end (); |
551 | + ++it) |
552 | + { |
553 | + bt::DamageAgeTracking *tracker = *it; |
554 | + |
555 | + tracker->incrementFrameAges (); |
556 | + } |
557 | +} |
558 | + |
559 | +void |
560 | +bt::AgeingDamageBuffers::markAreaDirty (const CompRegion ®) |
561 | +{ |
562 | + for (std::vector <bt::DamageAgeTracking *>::iterator it = |
563 | + priv->damageAgeTrackers.begin (); |
564 | + it != priv->damageAgeTrackers.end (); |
565 | + ++it) |
566 | + { |
567 | + bt::DamageAgeTracking *tracker = *it; |
568 | + |
569 | + tracker->dirtyAreaOnCurrentFrame (reg); |
570 | + } |
571 | +} |
572 | + |
573 | +void |
574 | +bt::AgeingDamageBuffers::subtractObscuredArea (const CompRegion ®) |
575 | +{ |
576 | + for (std::vector <bt::DamageAgeTracking *>::iterator it = |
577 | + priv->damageAgeTrackers.begin (); |
578 | + it != priv->damageAgeTrackers.end (); |
579 | + ++it) |
580 | + { |
581 | + bt::DamageAgeTracking *tracker = *it; |
582 | + |
583 | + tracker->subtractObscuredArea (reg); |
584 | + } |
585 | +} |
586 | + |
587 | +void |
588 | +bt::AgeingDamageBuffers::markAreaDirtyOnLastFrame (const CompRegion ®) |
589 | +{ |
590 | + for (std::vector <bt::DamageAgeTracking *>::iterator it = |
591 | + priv->damageAgeTrackers.begin (); |
592 | + it != priv->damageAgeTrackers.end (); |
593 | + ++it) |
594 | + { |
595 | + bt::DamageAgeTracking *tracker = *it; |
596 | + |
597 | + tracker->overdrawRegionOnPaintingFrame (reg); |
598 | + } |
599 | +} |
600 | |
601 | === added directory 'plugins/composite/src/backbuffertracking/tests' |
602 | === added file 'plugins/composite/src/backbuffertracking/tests/CMakeLists.txt' |
603 | --- plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
604 | +++ plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 2013-04-24 14:57:28 +0000 |
605 | @@ -0,0 +1,24 @@ |
606 | +find_library (GMOCK_LIBRARY gmock) |
607 | +find_library (GMOCK_MAIN_LIBRARY gmock_main) |
608 | + |
609 | +if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND) |
610 | + message ("Google Mock and Google Test not found - cannot build tests!") |
611 | + set (COMPIZ_BUILD_TESTING OFF) |
612 | +endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND) |
613 | + |
614 | +include_directories (${GTEST_INCLUDE_DIRS}) |
615 | + |
616 | +link_directories (${COMPIZ_LIBRARY_DIRS}) |
617 | + |
618 | +add_executable (compiz_test_composite_backbuffertracking |
619 | + ${CMAKE_CURRENT_SOURCE_DIR}/test-composite-backbuffertracking.cpp) |
620 | + |
621 | +target_link_libraries (compiz_test_composite_backbuffertracking |
622 | + compiz_composite_backbuffertracking |
623 | + ${GTEST_BOTH_LIBRARIES} |
624 | + ${GMOCK_LIBRARY} |
625 | + ${GMOCK_MAIN_LIBRARY} |
626 | + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. |
627 | + ) |
628 | + |
629 | +compiz_discover_tests (compiz_test_composite_backbuffertracking COVERAGE compiz_composite_backbuffertracking) |
630 | |
631 | === added file 'plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp' |
632 | --- plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 1970-01-01 00:00:00 +0000 |
633 | +++ plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 2013-04-24 14:57:28 +0000 |
634 | @@ -0,0 +1,450 @@ |
635 | +/* |
636 | + * Compiz, composite plugin, GLX_EXT_buffer_age logic |
637 | + * |
638 | + * Copyright (c) 2012 Sam Spilsbury |
639 | + * Authors: Sam Spilsbury <smspillaz@gmail.com> |
640 | + * |
641 | + * Permission is hereby granted, free of charge, to any person obtaining a |
642 | + * copy of this software and associated documentation files (the "Software"), |
643 | + * to deal in the Software without restriction, including without limitation |
644 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
645 | + * and/or sell copies of the Software, and to permit persons to whom the |
646 | + * Software is furnished to do so, subject to the following conditions: |
647 | + * |
648 | + * The above copyright notice and this permission notice shall be included in |
649 | + * all copies or substantial portions of the Software. |
650 | + * |
651 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
652 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
653 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
654 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
655 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
656 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
657 | + * DEALINGS IN THE SOFTWARE. |
658 | + */ |
659 | +#include <boost/bind.hpp> |
660 | + |
661 | +#include <gtest/gtest.h> |
662 | +#include <gmock/gmock.h> |
663 | + |
664 | +#include <core/region.h> |
665 | +#include <core/size.h> |
666 | + |
667 | +#include "backbuffertracking.h" |
668 | + |
669 | +using ::testing::NiceMock; |
670 | +using ::testing::_; |
671 | +using ::testing::AtLeast; |
672 | + |
673 | +namespace bt = compiz::composite::buffertracking; |
674 | + |
675 | +namespace |
676 | +{ |
677 | +class MockAgeingDamageBufferObserver : |
678 | + public bt::AgeingDamageBufferObserver |
679 | +{ |
680 | + public: |
681 | + |
682 | + MOCK_METHOD1 (observe, void (bt::DamageAgeTracking &)); |
683 | + MOCK_METHOD1 (unobserve, void (bt::DamageAgeTracking &)); |
684 | +}; |
685 | + |
686 | +bool alwaysTrackDamage (const CompRegion &) |
687 | +{ |
688 | + return true; |
689 | +} |
690 | + |
691 | + |
692 | +class BackbufferTracking : |
693 | + public ::testing::Test |
694 | +{ |
695 | + public: |
696 | + |
697 | + BackbufferTracking () : |
698 | + screen (1000, 1000), |
699 | + roster () |
700 | + { |
701 | + } |
702 | + |
703 | + virtual void SetUp () |
704 | + { |
705 | + SetupRoster (); |
706 | + } |
707 | + |
708 | + virtual void SetupRoster () |
709 | + { |
710 | + roster.reset (new bt::FrameRoster (screen, |
711 | + niceTracker, |
712 | + boost::bind (alwaysTrackDamage, |
713 | + _1))); |
714 | + } |
715 | + |
716 | + protected: |
717 | + |
718 | + CompSize screen; |
719 | + NiceMock <MockAgeingDamageBufferObserver> niceTracker; |
720 | + bt::FrameRoster::Ptr roster; |
721 | +}; |
722 | + |
723 | +class BackbufferTrackingCallbacks : |
724 | + public BackbufferTracking |
725 | +{ |
726 | + public: |
727 | + |
728 | + BackbufferTrackingCallbacks () : |
729 | + shouldDamage (false) |
730 | + { |
731 | + } |
732 | + |
733 | + protected: |
734 | + |
735 | + void allowDamage (bool allow) |
736 | + { |
737 | + shouldDamage = allow; |
738 | + } |
739 | + |
740 | + private: |
741 | + |
742 | + virtual void SetupRoster () |
743 | + { |
744 | + roster.reset (new bt::FrameRoster (screen, |
745 | + niceTracker, |
746 | + boost::bind (&BackbufferTrackingCallbacks::shouldDamageCallback, |
747 | + this, _1))); |
748 | + } |
749 | + |
750 | + bool shouldDamageCallback (const CompRegion &) |
751 | + { |
752 | + return shouldDamage; |
753 | + } |
754 | + |
755 | + bool shouldDamage; |
756 | +}; |
757 | +} |
758 | + |
759 | +std::ostream & |
760 | +operator<< (std::ostream &os, const CompRegion ®) |
761 | +{ |
762 | + os << "Region with Bounding Rectangle : " << |
763 | + reg.boundingRect ().x () << " " << |
764 | + reg.boundingRect ().y () << " " << |
765 | + reg.boundingRect ().width () << " " << |
766 | + reg.boundingRect ().height () << std::endl; |
767 | + CompRect::vector rects (reg.rects ()); |
768 | + for (CompRect::vector::iterator it = rects.begin (); |
769 | + it != rects.end (); |
770 | + it++) |
771 | + os << " - subrectangle: " << |
772 | + (*it).x () << " " << |
773 | + (*it).y () << " " << |
774 | + (*it).width () << " " << |
775 | + (*it).height () << " " << std::endl; |
776 | + |
777 | + return os; |
778 | +} |
779 | + |
780 | +TEST (BackbufferTrackingConstruction, CreateAddsToObserverList) |
781 | +{ |
782 | + MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver; |
783 | + |
784 | + /* We can't verify the argument here, |
785 | + * but we can verify the function call */ |
786 | + EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_)); |
787 | + EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_)).Times (AtLeast (0)); |
788 | + bt::FrameRoster roster (CompSize (), |
789 | + mockAgeingDamageBufferObserver, |
790 | + boost::bind (alwaysTrackDamage, _1)); |
791 | +} |
792 | + |
793 | +TEST (BackbufferTrackingConstruction, DestroyRemovesFromObserverList) |
794 | +{ |
795 | + MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver; |
796 | + |
797 | + /* We can't verify the argument here, |
798 | + * but we can verify the function call */ |
799 | + EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_)).Times (AtLeast (0)); |
800 | + EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_)); |
801 | + bt::FrameRoster roster (CompSize (), |
802 | + mockAgeingDamageBufferObserver, |
803 | + boost::bind (alwaysTrackDamage, _1)); |
804 | +} |
805 | + |
806 | +TEST_F (BackbufferTrackingCallbacks, TrackIntoCurrentIfCallbackTrue) |
807 | +{ |
808 | + allowDamage (true); |
809 | + CompRegion damage (100, 100, 100, 100); |
810 | + roster->dirtyAreaOnCurrentFrame (damage); |
811 | + EXPECT_EQ (damage, roster->currentFrameDamage ()); |
812 | +} |
813 | + |
814 | +TEST_F (BackbufferTrackingCallbacks, NoTrackIntoCurrentIfCallbackFalse) |
815 | +{ |
816 | + allowDamage (false); |
817 | + CompRegion damage (100, 100, 100, 100); |
818 | + roster->dirtyAreaOnCurrentFrame (damage); |
819 | + EXPECT_EQ (emptyRegion, roster->currentFrameDamage ()); |
820 | +} |
821 | + |
822 | +TEST_F (BackbufferTracking, DirtyAreaSubtraction) |
823 | +{ |
824 | + CompRegion dirty (100, 100, 100, 100); |
825 | + CompRegion obscured (150, 150, 50, 50); |
826 | + roster->dirtyAreaOnCurrentFrame (dirty); |
827 | + roster->subtractObscuredArea (obscured); |
828 | + EXPECT_EQ (dirty - obscured, roster->currentFrameDamage ()); |
829 | +} |
830 | + |
831 | +TEST_F (BackbufferTracking, DirtyAreaForAgeZeroAll) |
832 | +{ |
833 | + EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()), |
834 | + roster->damageForFrameAge (0)); |
835 | +} |
836 | + |
837 | +TEST_F (BackbufferTracking, DirtyAreaAllForOlderThanTrackedAge) |
838 | +{ |
839 | + EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()), |
840 | + roster->damageForFrameAge (1)); |
841 | +} |
842 | + |
843 | +TEST_F (BackbufferTracking, NoDirtyAreaForLastFrame) |
844 | +{ |
845 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
846 | + roster->dirtyAreaOnCurrentFrame (all); |
847 | + roster->incrementFrameAges (); |
848 | + EXPECT_EQ (emptyRegion, roster->damageForFrameAge (1)); |
849 | +} |
850 | + |
851 | +TEST_F (BackbufferTracking, DirtyAreaIfMoreSinceLastFrame) |
852 | +{ |
853 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
854 | + roster->dirtyAreaOnCurrentFrame (all); |
855 | + roster->incrementFrameAges (); |
856 | + roster->dirtyAreaOnCurrentFrame(all); |
857 | + EXPECT_EQ (all, roster->damageForFrameAge (1)); |
858 | +} |
859 | + |
860 | +TEST_F (BackbufferTracking, AddOverdrawRegionForLastFrame) |
861 | +{ |
862 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
863 | + roster->dirtyAreaOnCurrentFrame (all); |
864 | + roster->incrementFrameAges (); |
865 | + roster->incrementFrameAges (); |
866 | + roster->overdrawRegionOnPaintingFrame (all); |
867 | + EXPECT_EQ (all, roster->damageForFrameAge (2)); |
868 | +} |
869 | + |
870 | +TEST_F (BackbufferTracking, TwoFramesAgo) |
871 | +{ |
872 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
873 | + CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2); |
874 | + |
875 | + roster->dirtyAreaOnCurrentFrame (all); |
876 | + roster->incrementFrameAges (); |
877 | + roster->dirtyAreaOnCurrentFrame (topleft); |
878 | + roster->incrementFrameAges (); |
879 | + EXPECT_EQ (topleft, roster->damageForFrameAge (2)); |
880 | +} |
881 | + |
882 | +TEST_F (BackbufferTracking, TwoFramesAgoCulmulative) |
883 | +{ |
884 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
885 | + CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2); |
886 | + CompRegion topright (0, screen.width () / 2, |
887 | + screen.width () / 2, |
888 | + screen.height () / 2); |
889 | + |
890 | + roster->dirtyAreaOnCurrentFrame (all); |
891 | + roster->incrementFrameAges (); |
892 | + roster->dirtyAreaOnCurrentFrame (topleft); |
893 | + roster->dirtyAreaOnCurrentFrame (topright); |
894 | + roster->incrementFrameAges (); |
895 | + EXPECT_EQ (topleft + topright, roster->damageForFrameAge (2)); |
896 | +} |
897 | + |
898 | +TEST_F (BackbufferTracking, ThreeFramesAgo) |
899 | +{ |
900 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
901 | + CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2); |
902 | + CompRegion bottomright (screen.width () / 2, |
903 | + screen.height () / 2, |
904 | + screen.width () / 2, |
905 | + screen.height () / 2); |
906 | + |
907 | + roster->dirtyAreaOnCurrentFrame (all); |
908 | + roster->incrementFrameAges (); |
909 | + roster->dirtyAreaOnCurrentFrame (topleft); |
910 | + roster->incrementFrameAges (); |
911 | + roster->dirtyAreaOnCurrentFrame (bottomright); |
912 | + roster->incrementFrameAges (); |
913 | + |
914 | + EXPECT_EQ (topleft + bottomright, roster->damageForFrameAge (3)); |
915 | +} |
916 | + |
917 | +/* These are more or less functional tests from this point forward |
918 | + * just checking a number of different situations */ |
919 | + |
920 | +TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFrames) |
921 | +{ |
922 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
923 | + CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2); |
924 | + CompRegion bottomright (screen.width () / 2, |
925 | + screen.height () / 2, |
926 | + screen.width () / 2, |
927 | + screen.height () / 2); |
928 | + CompRegion topright (screen.width () / 2, |
929 | + 0, |
930 | + screen.width () / 2, |
931 | + screen.height () / 2); |
932 | + |
933 | + roster->dirtyAreaOnCurrentFrame (all); |
934 | + roster->incrementFrameAges (); |
935 | + roster->dirtyAreaOnCurrentFrame (topleft); |
936 | + roster->incrementFrameAges (); |
937 | + roster->dirtyAreaOnCurrentFrame (bottomright); |
938 | + roster->incrementFrameAges (); |
939 | + roster->dirtyAreaOnCurrentFrame (topright); |
940 | + roster->incrementFrameAges (); |
941 | + |
942 | + EXPECT_EQ (topright + bottomright, roster->damageForFrameAge (3)); |
943 | +} |
944 | + |
945 | +TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFramesAndOverlap) |
946 | +{ |
947 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
948 | + CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2); |
949 | + CompRegion bottomright (screen.width () / 2, |
950 | + screen.height () / 2, |
951 | + screen.width () / 2, |
952 | + screen.height () / 2); |
953 | + CompRegion topright (screen.width () / 2, |
954 | + 0, |
955 | + screen.width () / 2, |
956 | + screen.height () / 2); |
957 | + |
958 | + roster->dirtyAreaOnCurrentFrame (all); |
959 | + roster->incrementFrameAges (); |
960 | + roster->dirtyAreaOnCurrentFrame (topleft); |
961 | + roster->incrementFrameAges (); |
962 | + roster->dirtyAreaOnCurrentFrame (bottomright); |
963 | + roster->incrementFrameAges (); |
964 | + roster->dirtyAreaOnCurrentFrame (bottomright); |
965 | + roster->incrementFrameAges (); |
966 | + |
967 | + EXPECT_EQ (bottomright, roster->damageForFrameAge (3)); |
968 | +} |
969 | + |
970 | +TEST_F (BackbufferTracking, AllDamageForExceedingMaxTrackedFrames) |
971 | +{ |
972 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
973 | + CompRegion damage (0, 0, 1, 1); |
974 | + |
975 | + roster->dirtyAreaOnCurrentFrame (all); |
976 | + |
977 | + for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES - 1; ++i) |
978 | + { |
979 | + roster->incrementFrameAges (); |
980 | + roster->dirtyAreaOnCurrentFrame (damage); |
981 | + } |
982 | + |
983 | + EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES + 1)); |
984 | +} |
985 | + |
986 | +TEST_F (BackbufferTracking, DamageForMaxTrackedFrame) |
987 | +{ |
988 | + CompRegion all (0, 0, screen.width (), screen.height ()); |
989 | + CompRegion damage (0, 0, 1, 1); |
990 | + |
991 | + roster->dirtyAreaOnCurrentFrame (all); |
992 | + |
993 | + for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES + 1; ++i) |
994 | + { |
995 | + roster->incrementFrameAges (); |
996 | + roster->dirtyAreaOnCurrentFrame (damage); |
997 | + } |
998 | + |
999 | + EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES)); |
1000 | +} |
1001 | + |
1002 | +class MockDamageAgeTracking : |
1003 | + public bt::DamageAgeTracking |
1004 | +{ |
1005 | + public: |
1006 | + |
1007 | + typedef boost::shared_ptr <MockDamageAgeTracking> Ptr; |
1008 | + |
1009 | + MOCK_METHOD0 (incrementFrameAges, void ()); |
1010 | + MOCK_METHOD1 (dirtyAreaOnCurrentFrame, void (const CompRegion &)); |
1011 | + MOCK_METHOD1 (subtractObscuredArea, void (const CompRegion &)); |
1012 | + MOCK_METHOD1 (overdrawRegionOnPaintingFrame, void (const CompRegion &)); |
1013 | +}; |
1014 | + |
1015 | +class AgeingDamageBuffers : |
1016 | + public ::testing::Test |
1017 | +{ |
1018 | + public: |
1019 | + |
1020 | + AgeingDamageBuffers () |
1021 | + { |
1022 | + ageing.observe (mockDamageAgeTracker); |
1023 | + } |
1024 | + |
1025 | + MockDamageAgeTracking mockDamageAgeTracker; |
1026 | + bt::AgeingDamageBuffers ageing; |
1027 | +}; |
1028 | + |
1029 | +TEST_F (AgeingDamageBuffers, IncrementAgesOnValidRosters) |
1030 | +{ |
1031 | + EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ()); |
1032 | + ageing.incrementAges (); |
1033 | +} |
1034 | + |
1035 | +TEST_F (AgeingDamageBuffers, DirtyAreaOnValidRosters) |
1036 | +{ |
1037 | + CompRegion dirtyArea (100, 100, 100, 100); |
1038 | + EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (dirtyArea)); |
1039 | + ageing.markAreaDirty (dirtyArea); |
1040 | +} |
1041 | + |
1042 | +TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnValidRosters) |
1043 | +{ |
1044 | + CompRegion obscuredArea (100, 100, 100, 100); |
1045 | + EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (obscuredArea)); |
1046 | + ageing.subtractObscuredArea (obscuredArea); |
1047 | +} |
1048 | + |
1049 | +TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnValidRosters) |
1050 | +{ |
1051 | + CompRegion overdrawArea (100, 100, 100, 100); |
1052 | + EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (overdrawArea)); |
1053 | + ageing.markAreaDirtyOnLastFrame (overdrawArea); |
1054 | +} |
1055 | + |
1056 | +TEST_F (AgeingDamageBuffers, IncrementAgesOnInvalidRosters) |
1057 | +{ |
1058 | + EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ()).Times (0); |
1059 | + ageing.unobserve (mockDamageAgeTracker); |
1060 | + ageing.incrementAges (); |
1061 | +} |
1062 | + |
1063 | +TEST_F (AgeingDamageBuffers, DirtyAreaOnInvalidRosters) |
1064 | +{ |
1065 | + EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (_)).Times (0); |
1066 | + ageing.unobserve (mockDamageAgeTracker); |
1067 | + ageing.markAreaDirty (emptyRegion); |
1068 | +} |
1069 | + |
1070 | +TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnInvalidRosters) |
1071 | +{ |
1072 | + EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (_)).Times (0); |
1073 | + ageing.unobserve (mockDamageAgeTracker); |
1074 | + ageing.subtractObscuredArea (emptyRegion); |
1075 | +} |
1076 | + |
1077 | +TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnInvalidRosters) |
1078 | +{ |
1079 | + EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (_)).Times (0); |
1080 | + ageing.unobserve (mockDamageAgeTracker); |
1081 | + ageing.markAreaDirtyOnLastFrame (emptyRegion); |
1082 | +} |
1083 | + |
1084 | + |
1085 | |
1086 | === modified file 'plugins/composite/src/privates.h' |
1087 | --- plugins/composite/src/privates.h 2012-09-20 09:35:40 +0000 |
1088 | +++ plugins/composite/src/privates.h 2013-04-24 14:57:28 +0000 |
1089 | @@ -36,12 +36,20 @@ |
1090 | #include <map> |
1091 | |
1092 | #include "pixmapbinding.h" |
1093 | +#include "backbuffertracking.h" |
1094 | #include "composite_options.h" |
1095 | |
1096 | extern CompPlugin::VTable *compositeVTable; |
1097 | |
1098 | extern CompWindow *lastDamagedWindow; |
1099 | |
1100 | +enum DamageTracking |
1101 | +{ |
1102 | + DamageForCurrentFrame = 0, |
1103 | + DamageForLastFrame = 1, |
1104 | + DamageFinalPaintRegion |
1105 | +}; |
1106 | + |
1107 | class PrivateCompositeScreen : |
1108 | ScreenInterface, |
1109 | public CompositeOptions |
1110 | @@ -66,6 +74,8 @@ |
1111 | |
1112 | void scheduleRepaint (); |
1113 | |
1114 | + const CompRegion * damageTrackedBuffer (const CompRegion &); |
1115 | + |
1116 | public: |
1117 | |
1118 | CompositeScreen *cScreen; |
1119 | @@ -80,10 +90,12 @@ |
1120 | bool randrExtension; |
1121 | int randrEvent, randrError; |
1122 | |
1123 | - CompRegion damage; |
1124 | + CompRegion lastFrameDamage; |
1125 | unsigned long damageMask; |
1126 | |
1127 | - CompRegion tmpRegion; |
1128 | + CompRegion tmpRegion; |
1129 | + |
1130 | + DamageTracking currentlyTrackingDamage; |
1131 | |
1132 | Window overlay; |
1133 | Window output; |
1134 | @@ -99,6 +111,7 @@ |
1135 | int redrawTime; |
1136 | int optimalRedrawTime; |
1137 | bool scheduled, painting, reschedule; |
1138 | + bool damageRequiresRepaintReschedule; |
1139 | |
1140 | bool slowAnimations; |
1141 | |
1142 | @@ -115,6 +128,9 @@ |
1143 | |
1144 | /* Map Damage handle to its bounding box */ |
1145 | std::map<Damage, XRectangle> damages; |
1146 | + |
1147 | + compiz::composite::buffertracking::AgeingDamageBuffers ageingBuffers; |
1148 | + compiz::composite::buffertracking::FrameRoster roster; |
1149 | }; |
1150 | |
1151 | class PrivateCompositeWindow : |
1152 | |
1153 | === modified file 'plugins/composite/src/screen.cpp' |
1154 | --- plugins/composite/src/screen.cpp 2013-04-19 11:03:09 +0000 |
1155 | +++ plugins/composite/src/screen.cpp 2013-04-24 14:57:28 +0000 |
1156 | @@ -47,6 +47,8 @@ |
1157 | |
1158 | template class WrapableInterface<CompositeScreen, CompositeScreenInterface>; |
1159 | |
1160 | +namespace bt = compiz::composite::buffertracking; |
1161 | + |
1162 | static const int FALLBACK_REFRESH_RATE = 60; /* if all else fails */ |
1163 | |
1164 | CompWindow *lastDamagedWindow = 0; |
1165 | @@ -265,6 +267,15 @@ |
1166 | delete priv; |
1167 | } |
1168 | |
1169 | +namespace |
1170 | +{ |
1171 | +bool alwaysMarkDirty () |
1172 | +{ |
1173 | + return true; |
1174 | +} |
1175 | +} |
1176 | + |
1177 | + |
1178 | PrivateCompositeScreen::PrivateCompositeScreen (CompositeScreen *cs) : |
1179 | cScreen (cs), |
1180 | compositeEvent (0), |
1181 | @@ -282,6 +293,7 @@ |
1182 | randrEvent (0), |
1183 | randrError (0), |
1184 | damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK), |
1185 | + currentlyTrackingDamage (DamageForCurrentFrame), |
1186 | overlay (None), |
1187 | output (None), |
1188 | exposeRects (), |
1189 | @@ -293,12 +305,16 @@ |
1190 | scheduled (false), |
1191 | painting (false), |
1192 | reschedule (false), |
1193 | + damageRequiresRepaintReschedule (true), |
1194 | slowAnimations (false), |
1195 | pHnd (NULL), |
1196 | FPSLimiterMode (CompositeFPSLimiterModeDefault), |
1197 | withDestroyedWindows (), |
1198 | cmSnAtom (0), |
1199 | - newCmSnOwner (None) |
1200 | + newCmSnOwner (None), |
1201 | + roster (*screen, |
1202 | + ageingBuffers, |
1203 | + boost::bind (alwaysMarkDirty)) |
1204 | { |
1205 | gettimeofday (&lastRedraw, 0); |
1206 | // wrap outputChangeNotify |
1207 | @@ -474,22 +490,62 @@ |
1208 | return false; |
1209 | } |
1210 | |
1211 | +const CompRegion * |
1212 | +PrivateCompositeScreen::damageTrackedBuffer (const CompRegion ®ion) |
1213 | +{ |
1214 | + const CompRegion *currentDamage = NULL; |
1215 | + |
1216 | + switch (currentlyTrackingDamage) |
1217 | + { |
1218 | + case DamageForCurrentFrame: |
1219 | + currentDamage = &(roster.currentFrameDamage ()); |
1220 | + ageingBuffers.markAreaDirty (region); |
1221 | + break; |
1222 | + case DamageForLastFrame: |
1223 | + currentDamage = &(lastFrameDamage); |
1224 | + lastFrameDamage += region; |
1225 | + break; |
1226 | + case DamageFinalPaintRegion: |
1227 | + currentDamage = &(tmpRegion); |
1228 | + tmpRegion += region; |
1229 | + break; |
1230 | + default: |
1231 | + compLogMessage ("composite", CompLogLevelFatal, "unreachable section"); |
1232 | + assert (false); |
1233 | + abort (); |
1234 | + } |
1235 | + |
1236 | + assert (currentDamage); |
1237 | + return currentDamage; |
1238 | +} |
1239 | + |
1240 | void |
1241 | CompositeScreen::damageScreen () |
1242 | { |
1243 | + /* Don't tell plugins about damage events when the damage buffer is already full */ |
1244 | bool alreadyDamaged = priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK; |
1245 | + alreadyDamaged |= ((currentDamage () & screen->region ()) == screen->region ()); |
1246 | |
1247 | priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK; |
1248 | priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK; |
1249 | |
1250 | - priv->scheduleRepaint (); |
1251 | + if (priv->damageRequiresRepaintReschedule) |
1252 | + priv->scheduleRepaint (); |
1253 | |
1254 | /* |
1255 | * Call through damageRegion since plugins listening for incoming damage |
1256 | * may need to know that the whole screen was redrawn |
1257 | */ |
1258 | if (!alreadyDamaged) |
1259 | + { |
1260 | damageRegion (CompRegion (0, 0, screen->width (), screen->height ())); |
1261 | + |
1262 | + /* Set the damage region as the fullscreen region, because if |
1263 | + * windows are unredirected we need to correctly subtract from |
1264 | + * it later |
1265 | + */ |
1266 | + priv->damageTrackedBuffer (screen->region ()); |
1267 | + } |
1268 | } |
1269 | |
1270 | void |
1271 | @@ -500,7 +556,12 @@ |
1272 | if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) |
1273 | return; |
1274 | |
1275 | - priv->damage += region; |
1276 | + /* Don't cause repaints to be scheduled for empty damage |
1277 | + * regions */ |
1278 | + if (region.isEmpty ()) |
1279 | + return; |
1280 | + |
1281 | + const CompRegion *currentDamage = priv->damageTrackedBuffer (region); |
1282 | priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK; |
1283 | |
1284 | /* If the number of damage rectangles grows two much between repaints, |
1285 | @@ -509,17 +570,61 @@ |
1286 | * the whole screen if we have a lot of damage rects |
1287 | */ |
1288 | |
1289 | - if (priv->damage.numRects () > 100) |
1290 | + if (currentDamage->numRects () > 100) |
1291 | damageScreen (); |
1292 | |
1293 | - priv->scheduleRepaint (); |
1294 | + if (priv->damageRequiresRepaintReschedule) |
1295 | + priv->scheduleRepaint (); |
1296 | +} |
1297 | + |
1298 | +void |
1299 | +CompositeScreen::damageCutoff () |
1300 | +{ |
1301 | + WRAPABLE_HND_FUNCTN (damageCutoff); |
1302 | } |
1303 | |
1304 | void |
1305 | CompositeScreen::damagePending () |
1306 | { |
1307 | priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK; |
1308 | - priv->scheduleRepaint (); |
1309 | + |
1310 | + if (priv->damageRequiresRepaintReschedule) |
1311 | + priv->scheduleRepaint (); |
1312 | +} |
1313 | + |
1314 | +void |
1315 | +CompositeScreen::applyDamageForFrameAge (unsigned int age) |
1316 | +{ |
1317 | + /* Track into "last frame damage" */ |
1318 | + priv->currentlyTrackingDamage = DamageForLastFrame; |
1319 | + damageRegion (priv->roster.damageForFrameAge (age)); |
1320 | + priv->currentlyTrackingDamage = DamageForCurrentFrame; |
1321 | +} |
1322 | + |
1323 | +unsigned int |
1324 | +CompositeScreen::getFrameAge () |
1325 | +{ |
1326 | + if (priv->pHnd) |
1327 | + return priv->pHnd->getFrameAge (); |
1328 | + |
1329 | + return 1; |
1330 | +} |
1331 | + |
1332 | +void |
1333 | +CompositeScreen::addOverdrawDamageRegion (const CompRegion &r) |
1334 | +{ |
1335 | + priv->ageingBuffers.markAreaDirtyOnLastFrame (r); |
1336 | +} |
1337 | + |
1338 | +typedef CompositeScreen::AreaShouldBeMarkedDirty ShouldMarkDirty; |
1339 | + |
1340 | +CompositeScreen::DamageQuery::Ptr |
1341 | +CompositeScreen::getDamageQuery (const ShouldMarkDirty &callback) |
1342 | +{ |
1343 | + /* No initial damage */ |
1344 | + return bt::FrameRoster::Ptr (new bt::FrameRoster (CompSize (), |
1345 | + priv->ageingBuffers, |
1346 | + callback)); |
1347 | } |
1348 | |
1349 | unsigned int |
1350 | @@ -758,6 +863,12 @@ |
1351 | |
1352 | if (priv->damageMask) |
1353 | { |
1354 | + int timeDiff; |
1355 | + |
1356 | + /* Damage that accumulates here does not require a repaint reschedule |
1357 | + * as it will end up on this frame */ |
1358 | + priv->damageRequiresRepaintReschedule = false; |
1359 | + |
1360 | if (priv->pHnd) |
1361 | priv->pHnd->prepareDrawing (); |
1362 | |
1363 | @@ -792,7 +903,7 @@ |
1364 | continue; |
1365 | |
1366 | if (!CompositeWindow::get (w)->redirected ()) |
1367 | - priv->damage -= w->region (); |
1368 | + priv->ageingBuffers.subtractObscuredArea (w->region ()); |
1369 | |
1370 | break; |
1371 | } |
1372 | @@ -804,7 +915,13 @@ |
1373 | } |
1374 | } |
1375 | |
1376 | - priv->tmpRegion = priv->damage & screen->region (); |
1377 | + /* All further damage is for the next frame now, as |
1378 | + * priv->tmpRegion will be assigned. Notify plugins that do |
1379 | + * damage tracking of this */ |
1380 | + damageCutoff (); |
1381 | + |
1382 | + priv->tmpRegion = (priv->roster.currentFrameDamage () + priv->lastFrameDamage) & screen->region (); |
1383 | + priv->currentlyTrackingDamage = DamageFinalPaintRegion; |
1384 | |
1385 | if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK && |
1386 | priv->tmpRegion == screen->region ()) |
1387 | @@ -826,7 +943,9 @@ |
1388 | XSync (dpy, False); |
1389 | priv->damages.clear (); |
1390 | |
1391 | - priv->damage = CompRegion (); |
1392 | + /* Any more damage requires a repaint reschedule */ |
1393 | + priv->damageRequiresRepaintReschedule = true; |
1394 | + priv->lastFrameDamage = CompRegion (); |
1395 | |
1396 | int mask = priv->damageMask; |
1397 | priv->damageMask = 0; |
1398 | @@ -844,9 +963,13 @@ |
1399 | else |
1400 | outputs.push_back (&screen->fullscreenOutput ()); |
1401 | |
1402 | + priv->currentlyTrackingDamage = DamageForCurrentFrame; |
1403 | + |
1404 | + /* All new damage goes on the next frame */ |
1405 | + priv->ageingBuffers.incrementAges (); |
1406 | + |
1407 | paint (outputs, mask); |
1408 | |
1409 | - |
1410 | donePaint (); |
1411 | |
1412 | priv->outputShapeChanged = false; |
1413 | @@ -1003,8 +1126,12 @@ |
1414 | CompositeScreenInterface::damageRegion (const CompRegion &r) |
1415 | WRAPABLE_DEF (damageRegion, r); |
1416 | |
1417 | +void |
1418 | +CompositeScreenInterface::damageCutoff () |
1419 | + WRAPABLE_DEF (damageCutoff); |
1420 | + |
1421 | const CompRegion & |
1422 | CompositeScreen::currentDamage () const |
1423 | { |
1424 | - return priv->damage; |
1425 | + return priv->roster.currentFrameDamage (); |
1426 | } |
1427 | |
1428 | === modified file 'plugins/kdecompat/src/kdecompat.cpp' |
1429 | --- plugins/kdecompat/src/kdecompat.cpp 2012-08-14 06:33:22 +0000 |
1430 | +++ plugins/kdecompat/src/kdecompat.cpp 2013-04-24 14:57:28 +0000 |
1431 | @@ -196,7 +196,7 @@ |
1432 | if ((!(ks->optionGetPlasmaThumbnails () || mPreviews.empty ()) && |
1433 | !(mSlideData || mSlideData->remaining)) || |
1434 | !window->mapNum () || |
1435 | - (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)) |
1436 | + (mask & PAINT_WINDOW_NO_DRAW_MASKS)) |
1437 | { |
1438 | status = gWindow->glPaint (attrib, transform, region, mask); |
1439 | return status; |
1440 | @@ -210,7 +210,7 @@ |
1441 | CompRect clipBox (window->x (), window->y (), |
1442 | window->width (), window->height ()); |
1443 | |
1444 | - if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) |
1445 | + if (mask & PAINT_WINDOW_NO_DRAW_MASKS) |
1446 | return false; |
1447 | |
1448 | remainder = (float) data->remaining / data->duration; |
1449 | |
1450 | === modified file 'plugins/opengl/include/opengl/opengl.h' |
1451 | --- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000 |
1452 | +++ plugins/opengl/include/opengl/opengl.h 2013-04-24 14:57:28 +0000 |
1453 | @@ -37,6 +37,13 @@ |
1454 | #else |
1455 | #include <GL/gl.h> |
1456 | #include <GL/glx.h> |
1457 | + |
1458 | +/* Some implementations have not yet given a definition |
1459 | + * to GLX_BACK_BUFFER_AGE_EXT but this is the token as defined |
1460 | + * in the spec (https://www.opengl.org/registry/specs/EXT/glx_buffer_age.txt) |
1461 | + */ |
1462 | +#define GLX_BACK_BUFFER_AGE_EXT 0x20F4 |
1463 | + |
1464 | #endif |
1465 | |
1466 | #include <core/size.h> |
1467 | @@ -50,7 +57,7 @@ |
1468 | #include <opengl/programcache.h> |
1469 | #include <opengl/shadercache.h> |
1470 | |
1471 | -#define COMPIZ_OPENGL_ABI 6 |
1472 | +#define COMPIZ_OPENGL_ABI 8 |
1473 | |
1474 | /* |
1475 | * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but |
1476 | @@ -525,6 +532,7 @@ |
1477 | extern bool shaders; |
1478 | extern bool stencilBuffer; |
1479 | extern GLint maxTextureUnits; |
1480 | + extern bool bufferAge; |
1481 | |
1482 | extern bool canDoSaturated; |
1483 | extern bool canDoSlightlySaturated; |
1484 | @@ -663,6 +671,11 @@ |
1485 | unsigned int mask); |
1486 | |
1487 | /** |
1488 | + * Return true if glPaintCompositedOutput is required for this frame |
1489 | + */ |
1490 | + virtual bool glPaintCompositedOutputRequired (); |
1491 | + |
1492 | + /** |
1493 | * Hookable function used by plugins to determine stenciling mask |
1494 | */ |
1495 | virtual void glBufferStencil (const GLMatrix &matrix, |
1496 | @@ -674,7 +687,7 @@ |
1497 | extern template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>; |
1498 | |
1499 | class GLScreen : |
1500 | - public WrapableHandler<GLScreenInterface, 8>, |
1501 | + public WrapableHandler<GLScreenInterface, 9>, |
1502 | public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>, |
1503 | public CompOption::Class |
1504 | { |
1505 | @@ -788,7 +801,9 @@ |
1506 | WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput, |
1507 | const CompRegion &, GLFramebufferObject *, unsigned int); |
1508 | |
1509 | - WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &, |
1510 | + WRAPABLE_HND (7, GLScreenInterface, bool, glPaintCompositedOutputRequired); |
1511 | + |
1512 | + WRAPABLE_HND (8, GLScreenInterface, void, glBufferStencil, const GLMatrix &, |
1513 | GLVertexBuffer &, |
1514 | CompOutput *); |
1515 | |
1516 | |
1517 | === modified file 'plugins/opengl/src/paint.cpp' |
1518 | --- plugins/opengl/src/paint.cpp 2013-01-03 16:05:26 +0000 |
1519 | +++ plugins/opengl/src/paint.cpp 2013-04-24 14:57:28 +0000 |
1520 | @@ -418,11 +418,6 @@ |
1521 | if (w->destroyed ()) |
1522 | continue; |
1523 | |
1524 | - gw = GLWindow::get (w); |
1525 | - |
1526 | - /* Release any queued ConfigureWindow requests now */ |
1527 | - gw->priv->configureLock->release (); |
1528 | - |
1529 | if (unredirected.find (w) != unredirected.end ()) |
1530 | continue; |
1531 | |
1532 | @@ -432,6 +427,8 @@ |
1533 | continue; |
1534 | } |
1535 | |
1536 | + gw = GLWindow::get (w); |
1537 | + |
1538 | const CompRegion &clip = |
1539 | (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ? |
1540 | gw->clip () : region; |
1541 | @@ -629,8 +626,8 @@ |
1542 | if (mask & PAINT_SCREEN_FULL_MASK) |
1543 | { |
1544 | glPaintTransformedOutput (sAttrib, sTransform, |
1545 | - CompRegion (*output), output, mask); |
1546 | - |
1547 | + CompRegionRef (output->region ()), output, mask); |
1548 | + priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ())); |
1549 | return true; |
1550 | } |
1551 | |
1552 | @@ -660,8 +657,9 @@ |
1553 | } |
1554 | else if (mask & PAINT_SCREEN_FULL_MASK) |
1555 | { |
1556 | - glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output), |
1557 | + glPaintTransformedOutput (sAttrib, sTransform, CompRegionRef (output->region ()), |
1558 | output, mask); |
1559 | + priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ())); |
1560 | |
1561 | return true; |
1562 | } |
1563 | @@ -671,6 +669,13 @@ |
1564 | } |
1565 | } |
1566 | |
1567 | +bool |
1568 | +GLScreen::glPaintCompositedOutputRequired () |
1569 | +{ |
1570 | + WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintCompositedOutputRequired); |
1571 | + return false; |
1572 | +} |
1573 | + |
1574 | void |
1575 | GLScreen::glPaintCompositedOutput (const CompRegion ®ion, |
1576 | GLFramebufferObject *fbo, |
1577 | |
1578 | === modified file 'plugins/opengl/src/privates.h' |
1579 | --- plugins/opengl/src/privates.h 2013-01-03 16:05:26 +0000 |
1580 | +++ plugins/opengl/src/privates.h 2013-04-24 14:57:28 +0000 |
1581 | @@ -29,11 +29,13 @@ |
1582 | #define _OPENGL_PRIVATES_H |
1583 | |
1584 | #include <memory> |
1585 | +#include <vector> |
1586 | +#include <tr1/tuple> |
1587 | +#include <boost/shared_ptr.hpp> |
1588 | |
1589 | #include <composite/composite.h> |
1590 | #include <opengl/opengl.h> |
1591 | #include <core/atoms.h> |
1592 | -#include <core/configurerequestbuffer.h> |
1593 | |
1594 | #ifdef USE_GLES |
1595 | #include <opengl/framebufferobject.h> |
1596 | @@ -120,8 +122,26 @@ |
1597 | GLTexture::List textures; |
1598 | }; |
1599 | |
1600 | +class FrameProvider |
1601 | +{ |
1602 | + public: |
1603 | + |
1604 | + typedef boost::shared_ptr <FrameProvider> Ptr; |
1605 | + typedef std::tr1::tuple <GLFramebufferObject *, int> Frame; |
1606 | + |
1607 | + virtual ~FrameProvider () {} |
1608 | + |
1609 | + virtual GLuint getCurrentFrame () = 0; |
1610 | + virtual void endFrame () = 0; |
1611 | + |
1612 | + virtual bool providesPersistence () = 0; |
1613 | + virtual bool alwaysPostprocess () = 0; |
1614 | + virtual void invalidateAll () = 0; |
1615 | +}; |
1616 | + |
1617 | class PrivateGLScreen : |
1618 | public ScreenInterface, |
1619 | + public CompositeScreenInterface, |
1620 | public compiz::composite::PaintHandler, |
1621 | public OpenglOptions |
1622 | { |
1623 | @@ -142,12 +162,17 @@ |
1624 | bool hasVSync (); |
1625 | bool requiredForcedRefreshRate (); |
1626 | |
1627 | + unsigned int getFrameAge (); |
1628 | + |
1629 | void updateRenderMode (); |
1630 | + void updateFrameProvider (); |
1631 | |
1632 | void prepareDrawing (); |
1633 | |
1634 | bool compositingActive (); |
1635 | |
1636 | + void damageCutoff (); |
1637 | + |
1638 | void paintBackground (const GLMatrix &transform, |
1639 | const CompRegion ®ion, |
1640 | bool transformed); |
1641 | @@ -163,6 +188,8 @@ |
1642 | |
1643 | bool driverIsBlacklisted (const char *regex) const; |
1644 | |
1645 | + bool postprocessRequiredForCurrentFrame (); |
1646 | + |
1647 | public: |
1648 | |
1649 | GLScreen *gScreen; |
1650 | @@ -197,7 +224,7 @@ |
1651 | GLXDoubleBuffer doubleBuffer; |
1652 | #endif |
1653 | |
1654 | - GLFramebufferObject *scratchFbo; |
1655 | + boost::shared_ptr <GLFramebufferObject> scratchFbo; |
1656 | CompRegion outputRegion; |
1657 | |
1658 | XRectangle lastViewport; |
1659 | @@ -222,8 +249,10 @@ |
1660 | Pixmap rootPixmapCopy; |
1661 | CompSize rootPixmapSize; |
1662 | |
1663 | + FrameProvider::Ptr frameProvider; |
1664 | const char *glVendor, *glRenderer, *glVersion; |
1665 | |
1666 | + bool postprocessingRequired; |
1667 | mutable CompString prevRegex; |
1668 | mutable bool prevBlacklisted; |
1669 | }; |
1670 | @@ -284,8 +313,6 @@ |
1671 | GLVertexBuffer::AutoProgram *autoProgram; |
1672 | |
1673 | std::list<GLIcon> icons; |
1674 | - |
1675 | - compiz::window::configure_buffers::Releasable::Ptr configureLock; |
1676 | }; |
1677 | |
1678 | #endif |
1679 | |
1680 | === modified file 'plugins/opengl/src/screen.cpp' |
1681 | --- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000 |
1682 | +++ plugins/opengl/src/screen.cpp 2013-04-24 14:57:28 +0000 |
1683 | @@ -186,6 +186,7 @@ |
1684 | bool vboEnabled = false; |
1685 | bool shaders = false; |
1686 | GLint maxTextureUnits = 1; |
1687 | + bool bufferAge = false; |
1688 | |
1689 | bool canDoSaturated = false; |
1690 | bool canDoSlightlySaturated = false; |
1691 | @@ -301,6 +302,52 @@ |
1692 | |
1693 | #ifndef USE_GLES |
1694 | |
1695 | +class BufferAgeFrameProvider : |
1696 | + public FrameProvider |
1697 | +{ |
1698 | + public: |
1699 | + |
1700 | + BufferAgeFrameProvider (Display *disp, |
1701 | + GLXDrawable drawable) : |
1702 | + mDisplay (disp), |
1703 | + mDrawable (drawable) |
1704 | + { |
1705 | + } |
1706 | + |
1707 | + unsigned int getCurrentFrame () |
1708 | + { |
1709 | + unsigned int age = 0; |
1710 | + (*GL::queryDrawable) (mDisplay, |
1711 | + mDrawable, |
1712 | + GLX_BACK_BUFFER_AGE_EXT, |
1713 | + &age); |
1714 | + return age; |
1715 | + } |
1716 | + |
1717 | + void endFrame () |
1718 | + { |
1719 | + } |
1720 | + |
1721 | + void invalidateAll () |
1722 | + { |
1723 | + } |
1724 | + |
1725 | + bool providesPersistence () |
1726 | + { |
1727 | + return true; |
1728 | + } |
1729 | + |
1730 | + bool alwaysPostprocess () |
1731 | + { |
1732 | + return false; |
1733 | + } |
1734 | + |
1735 | + private: |
1736 | + |
1737 | + Display *mDisplay; |
1738 | + GLXDrawable mDrawable; |
1739 | +}; |
1740 | + |
1741 | namespace compiz |
1742 | { |
1743 | namespace opengl |
1744 | @@ -358,6 +405,137 @@ |
1745 | |
1746 | #endif |
1747 | |
1748 | +class UndefinedFrameProvider : |
1749 | + public FrameProvider |
1750 | +{ |
1751 | + public: |
1752 | + |
1753 | + unsigned int getCurrentFrame () |
1754 | + { |
1755 | + return 0; |
1756 | + } |
1757 | + |
1758 | + void endFrame () |
1759 | + { |
1760 | + } |
1761 | + |
1762 | + void invalidateAll () |
1763 | + { |
1764 | + } |
1765 | + |
1766 | + bool providesPersistence () |
1767 | + { |
1768 | + return false; |
1769 | + } |
1770 | + |
1771 | + bool alwaysPostprocess () |
1772 | + { |
1773 | + return false; |
1774 | + } |
1775 | +}; |
1776 | + |
1777 | +class PostprocessFrameProvider : |
1778 | + public FrameProvider |
1779 | +{ |
1780 | + public: |
1781 | + |
1782 | + PostprocessFrameProvider (GLFramebufferObject *object) : |
1783 | + mObject (object), |
1784 | + mAge (0) |
1785 | + { |
1786 | + } |
1787 | + |
1788 | + unsigned int getCurrentFrame () |
1789 | + { |
1790 | + /* We are now using this buffer, reset |
1791 | + * age back to zero */ |
1792 | + unsigned int lastAge = mAge; |
1793 | + mAge = 0; |
1794 | + |
1795 | + return lastAge; |
1796 | + } |
1797 | + |
1798 | + void endFrame () |
1799 | + { |
1800 | + ++mAge; |
1801 | + } |
1802 | + |
1803 | + void invalidateAll () |
1804 | + { |
1805 | + mAge = 0; |
1806 | + } |
1807 | + |
1808 | + bool providesPersistence () |
1809 | + { |
1810 | + return true; |
1811 | + } |
1812 | + |
1813 | + bool alwaysPostprocess () |
1814 | + { |
1815 | + return true; |
1816 | + } |
1817 | + |
1818 | + private: |
1819 | + |
1820 | + GLFramebufferObject *mObject; |
1821 | + unsigned int mAge; |
1822 | +}; |
1823 | + |
1824 | +class OptionalPostprocessFrameProvider : |
1825 | + public FrameProvider |
1826 | +{ |
1827 | + public: |
1828 | + |
1829 | + typedef boost::function <bool ()> PostprocessRequired; |
1830 | + |
1831 | + OptionalPostprocessFrameProvider (const FrameProvider::Ptr &backbuffer, |
1832 | + const FrameProvider::Ptr &scratchbuffer, |
1833 | + const PostprocessRequired &ppRequired) : |
1834 | + mBackbuffer (backbuffer), |
1835 | + mScratchbuffer (scratchbuffer), |
1836 | + mPPRequired (ppRequired) |
1837 | + { |
1838 | + } |
1839 | + |
1840 | + unsigned int getCurrentFrame () |
1841 | + { |
1842 | + if (mPPRequired ()) |
1843 | + return mScratchbuffer->getCurrentFrame (); |
1844 | + else |
1845 | + return mBackbuffer->getCurrentFrame (); |
1846 | + } |
1847 | + |
1848 | + void endFrame () |
1849 | + { |
1850 | + mScratchbuffer->endFrame (); |
1851 | + } |
1852 | + |
1853 | + void invalidateAll () |
1854 | + { |
1855 | + mScratchbuffer->invalidateAll (); |
1856 | + } |
1857 | + |
1858 | + bool providesPersistence () |
1859 | + { |
1860 | + /* We are only as good as the backbuffer is */ |
1861 | + return mBackbuffer->providesPersistence (); |
1862 | + } |
1863 | + |
1864 | + bool alwaysPostprocess () |
1865 | + { |
1866 | + if (mPPRequired ()) |
1867 | + return mScratchbuffer->alwaysPostprocess (); |
1868 | + else |
1869 | + return mBackbuffer->alwaysPostprocess (); |
1870 | + } |
1871 | + |
1872 | + private: |
1873 | + |
1874 | + FrameProvider::Ptr mBackbuffer; |
1875 | + FrameProvider::Ptr mScratchbuffer; |
1876 | + PostprocessRequired mPPRequired; |
1877 | +}; |
1878 | + |
1879 | bool |
1880 | GLScreen::glInitContext (XVisualInfo *visinfo) |
1881 | { |
1882 | @@ -593,6 +771,8 @@ |
1883 | |
1884 | priv->incorrectRefreshRate = false; |
1885 | |
1886 | + priv->frameProvider.reset (new PostprocessFrameProvider ()); |
1887 | + |
1888 | #else |
1889 | |
1890 | Display *dpy = screen->dpy (); |
1891 | @@ -899,12 +1079,17 @@ |
1892 | |
1893 | if (GL::fboSupported) |
1894 | { |
1895 | - priv->scratchFbo = new GLFramebufferObject; |
1896 | + priv->scratchFbo.reset (new GLFramebufferObject ()); |
1897 | priv->scratchFbo->allocate (*screen, NULL, GL_BGRA); |
1898 | } |
1899 | |
1900 | GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram); |
1901 | |
1902 | + /* We need scratchFbo to be set before doing this, and it is common |
1903 | + * to both the GLES and non-GLES codepaths, so using another #ifdef |
1904 | + */ |
1905 | + priv->updateFrameProvider (); |
1906 | + |
1907 | return true; |
1908 | } |
1909 | |
1910 | @@ -993,6 +1178,13 @@ |
1911 | return; |
1912 | } |
1913 | |
1914 | + if (strstr (glxExtensions, "GLX_EXT_buffer_age")) |
1915 | + { |
1916 | + compLogMessage ("opengl", CompLogLevelInfo, |
1917 | + "GLX_EXT_buffer_age is supported"); |
1918 | + GL::bufferAge = true; |
1919 | + } |
1920 | + |
1921 | priv->getProcAddress = (GL::GLXGetProcAddressProc) |
1922 | getProcAddress ("glXGetProcAddressARB"); |
1923 | GL::bindTexImage = (GL::GLXBindTexImageProc) |
1924 | @@ -1209,9 +1401,6 @@ |
1925 | glXDestroyContext (screen->dpy (), priv->ctx); |
1926 | #endif |
1927 | |
1928 | - if (priv->scratchFbo) |
1929 | - delete priv->scratchFbo; |
1930 | - |
1931 | delete priv; |
1932 | } |
1933 | |
1934 | @@ -1233,7 +1422,7 @@ |
1935 | ctx (EGL_NO_CONTEXT), |
1936 | doubleBuffer (screen->dpy (), *screen, surface), |
1937 | #endif |
1938 | - scratchFbo (NULL), |
1939 | + scratchFbo (), |
1940 | outputRegion (), |
1941 | refreshSubBuffer (false), |
1942 | lastMask (0), |
1943 | @@ -1246,13 +1435,16 @@ |
1944 | autoProgram (new GLScreenAutoProgram(gs)), |
1945 | rootPixmapCopy (None), |
1946 | rootPixmapSize (), |
1947 | + frameProvider (), |
1948 | glVendor (NULL), |
1949 | glRenderer (NULL), |
1950 | glVersion (NULL), |
1951 | + postprocessingRequired (false), |
1952 | prevRegex (), |
1953 | prevBlacklisted (false) |
1954 | { |
1955 | ScreenInterface::setHandler (screen); |
1956 | + CompositeScreenInterface::setHandler (cScreen); |
1957 | } |
1958 | |
1959 | PrivateGLScreen::~PrivateGLScreen () |
1960 | @@ -1443,8 +1635,11 @@ |
1961 | { |
1962 | screen->outputChangeNotify (); |
1963 | |
1964 | + frameProvider->invalidateAll (); |
1965 | + |
1966 | if (scratchFbo) |
1967 | scratchFbo->allocate (*screen, NULL, GL_BGRA); |
1968 | + |
1969 | updateView (); |
1970 | } |
1971 | |
1972 | @@ -1669,6 +1864,10 @@ |
1973 | GLScreenInterface::projectionMatrix () |
1974 | WRAPABLE_DEF (projectionMatrix) |
1975 | |
1976 | +bool |
1977 | +GLScreenInterface::glPaintCompositedOutputRequired () |
1978 | + WRAPABLE_DEF (glPaintCompositedOutputRequired) |
1979 | + |
1980 | void |
1981 | GLScreenInterface::glPaintCompositedOutput (const CompRegion ®ion, |
1982 | GLFramebufferObject *fbo, |
1983 | @@ -1977,18 +2176,6 @@ |
1984 | glDepthMask (GL_FALSE); |
1985 | glStencilMask (0); |
1986 | |
1987 | - GLFramebufferObject *oldFbo = NULL; |
1988 | - bool useFbo = false; |
1989 | - |
1990 | - /* Clear the color buffer where appropriate */ |
1991 | - if (GL::fboEnabled && scratchFbo) |
1992 | - { |
1993 | - oldFbo = scratchFbo->bind (); |
1994 | - useFbo = scratchFbo->checkStatus () && scratchFbo->tex (); |
1995 | - if (!useFbo) |
1996 | - GLFramebufferObject::rebind (oldFbo); |
1997 | - } |
1998 | - |
1999 | #ifdef UNSAFE_ARM_SGX_FIXME |
2000 | refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) && |
2001 | !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) && |
2002 | @@ -2006,8 +2193,21 @@ |
2003 | } |
2004 | #endif |
2005 | |
2006 | - CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ? |
2007 | - screen->region () : region; |
2008 | + CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ? |
2009 | + screen->region () : region); |
2010 | + bool useFbo = false; |
2011 | + GLFramebufferObject *oldFbo = NULL; |
2012 | + |
2013 | + postprocessingRequired = gScreen->glPaintCompositedOutputRequired (); |
2014 | + postprocessingRequired |= frameProvider->alwaysPostprocess (); |
2015 | + |
2016 | + /* Clear the color buffer where appropriate */ |
2017 | + if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ())) |
2018 | + { |
2019 | + oldFbo = scratchFbo->bind (); |
2020 | + if (scratchFbo->checkStatus ()) |
2021 | + useFbo = true; |
2022 | + } |
2023 | |
2024 | foreach (CompOutput *output, outputs) |
2025 | { |
2026 | @@ -2034,7 +2234,8 @@ |
2027 | |
2028 | gScreen->glPaintOutput (defaultScreenPaintAttrib, |
2029 | identity, |
2030 | - CompRegion (*output), output, |
2031 | + CompRegion (*output), |
2032 | + output, |
2033 | PAINT_SCREEN_REGION_MASK | |
2034 | PAINT_SCREEN_FULL_MASK); |
2035 | } |
2036 | @@ -2057,7 +2258,9 @@ |
2037 | tmpRegion = CompRegion (*output); |
2038 | #endif |
2039 | |
2040 | - outputRegion = tmpRegion & CompRegion (*output); |
2041 | + /* Clip current paint region to output extents */ |
2042 | + CompRegionRef wholeOutput (output->region ()); |
2043 | + outputRegion = (paintRegion & wholeOutput); |
2044 | |
2045 | if (!gScreen->glPaintOutput (defaultScreenPaintAttrib, |
2046 | identity, |
2047 | @@ -2068,10 +2271,11 @@ |
2048 | |
2049 | gScreen->glPaintOutput (defaultScreenPaintAttrib, |
2050 | identity, |
2051 | - CompRegion (*output), output, |
2052 | + wholeOutput, output, |
2053 | PAINT_SCREEN_FULL_MASK); |
2054 | |
2055 | - tmpRegion += *output; |
2056 | + paintRegion += wholeOutput; |
2057 | + cScreen->addOverdrawDamageRegion (wholeOutput); |
2058 | } |
2059 | } |
2060 | } |
2061 | @@ -2082,13 +2286,18 @@ |
2062 | |
2063 | if (useFbo) |
2064 | { |
2065 | - GLFramebufferObject::rebind (oldFbo); |
2066 | - |
2067 | // FIXME: does not work if screen dimensions exceed max texture size |
2068 | // We should try to use glBlitFramebuffer instead. |
2069 | - gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask); |
2070 | + GLFramebufferObject::rebind (oldFbo); |
2071 | + /* If we must always postprocess, then we don't have any |
2072 | + * "real" backbuffer persistence, redraw the whole thing */ |
2073 | + gScreen->glPaintCompositedOutput (frameProvider->alwaysPostprocess () ? |
2074 | + screen->region () : |
2075 | + paintRegion, scratchFbo.get (), mask); |
2076 | } |
2077 | |
2078 | + frameProvider->endFrame (); |
2079 | + |
2080 | if (cScreen->outputWindowChanged ()) |
2081 | { |
2082 | /* |
2083 | @@ -2100,20 +2309,27 @@ |
2084 | return; |
2085 | } |
2086 | |
2087 | + bool persistence = frameProvider->providesPersistence (); |
2088 | bool alwaysSwap = optionGetAlwaysSwapBuffers (); |
2089 | - bool fullscreen = useFbo || |
2090 | + bool fullscreen = persistence || |
2091 | alwaysSwap || |
2092 | ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) && |
2093 | commonFrontbuffer); |
2094 | |
2095 | doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ()); |
2096 | - doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo); |
2097 | + doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, persistence); |
2098 | doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap); |
2099 | - doubleBuffer.render (tmpRegion, fullscreen); |
2100 | + doubleBuffer.render (paintRegion, fullscreen); |
2101 | |
2102 | lastMask = mask; |
2103 | } |
2104 | |
2105 | +unsigned int |
2106 | +PrivateGLScreen::getFrameAge () |
2107 | +{ |
2108 | + return frameProvider->getCurrentFrame (); |
2109 | +} |
2110 | + |
2111 | bool |
2112 | PrivateGLScreen::hasVSync () |
2113 | { |
2114 | @@ -2138,6 +2354,13 @@ |
2115 | } |
2116 | |
2117 | void |
2118 | +PrivateGLScreen::damageCutoff () |
2119 | +{ |
2120 | + cScreen->applyDamageForFrameAge (frameProvider->getCurrentFrame ()); |
2121 | + cScreen->damageCutoff (); |
2122 | +} |
2123 | + |
2124 | +void |
2125 | PrivateGLScreen::updateRenderMode () |
2126 | { |
2127 | #ifndef USE_GLES |
2128 | @@ -2147,12 +2370,54 @@ |
2129 | } |
2130 | |
2131 | void |
2132 | +PrivateGLScreen::updateFrameProvider () |
2133 | +{ |
2134 | +#ifndef USE_GLES |
2135 | + const Window outputWindow = CompositeScreen::get (screen)->output (); |
2136 | + |
2137 | + if (GL::fboEnabled) |
2138 | + { |
2139 | + if (GL::bufferAge) |
2140 | + { |
2141 | + FrameProvider::Ptr back (new BufferAgeFrameProvider (screen->dpy (), |
2142 | + outputWindow)); |
2143 | + FrameProvider::Ptr scratch (new PostprocessFrameProvider (scratchFbo.get ())); |
2144 | + OptionalPostprocessFrameProvider::PostprocessRequired ppReq |
2145 | + (boost::bind (&PrivateGLScreen::postprocessRequiredForCurrentFrame, |
2146 | + this)); |
2147 | + frameProvider.reset (new OptionalPostprocessFrameProvider (back, |
2148 | + scratch, |
2149 | + ppReq)); |
2150 | + } |
2151 | + else |
2152 | + { |
2153 | + /* Prefer using FBO's instead of switching between a defined/undefined backbuffer */ |
2154 | + frameProvider.reset (new PostprocessFrameProvider (scratchFbo.get ())); |
2155 | + } |
2156 | + } |
2157 | + else |
2158 | + { |
2159 | + if (GL::bufferAge) |
2160 | + frameProvider.reset (new BufferAgeFrameProvider (screen->dpy (), |
2161 | + outputWindow)); |
2162 | + else |
2163 | + frameProvider.reset (new UndefinedFrameProvider ()); |
2164 | + } |
2165 | +#else |
2166 | + frameProvider.reset (new PostprocessFrameProvider (scratchFbo.get ())); |
2167 | +#endif |
2168 | +} |
2169 | + |
2170 | +void |
2171 | PrivateGLScreen::prepareDrawing () |
2172 | { |
2173 | bool wasFboEnabled = GL::fboEnabled; |
2174 | updateRenderMode (); |
2175 | if (wasFboEnabled != GL::fboEnabled) |
2176 | + { |
2177 | + updateFrameProvider (); |
2178 | CompositeScreen::get (screen)->damageScreen (); |
2179 | + } |
2180 | } |
2181 | |
2182 | bool |
2183 | @@ -2170,6 +2435,12 @@ |
2184 | return prevBlacklisted; |
2185 | } |
2186 | |
2187 | +bool |
2188 | +PrivateGLScreen::postprocessRequiredForCurrentFrame () |
2189 | +{ |
2190 | + return postprocessingRequired; |
2191 | +} |
2192 | + |
2193 | GLTexture::BindPixmapHandle |
2194 | GLScreen::registerBindPixmap (GLTexture::BindPixmapProc proc) |
2195 | { |
2196 | @@ -2198,7 +2469,7 @@ |
2197 | GLFramebufferObject * |
2198 | GLScreen::fbo () |
2199 | { |
2200 | - return priv->scratchFbo; |
2201 | + return priv->scratchFbo.get (); |
2202 | } |
2203 | |
2204 | GLTexture * |
2205 | |
2206 | === modified file 'plugins/opengl/src/window.cpp' |
2207 | --- plugins/opengl/src/window.cpp 2013-01-03 16:05:26 +0000 |
2208 | +++ plugins/opengl/src/window.cpp 2013-04-24 14:57:28 +0000 |
2209 | @@ -86,8 +86,7 @@ |
2210 | bindFailed (false), |
2211 | vertexBuffer (new GLVertexBuffer ()), |
2212 | autoProgram(new GLWindowAutoProgram(this)), |
2213 | - icons (), |
2214 | - configureLock (w->obtainLockOnConfigureRequests ()) |
2215 | + icons () |
2216 | { |
2217 | paint.xScale = 1.0f; |
2218 | paint.yScale = 1.0f; |
2219 | |
2220 | === modified file 'plugins/place/src/place.cpp' |
2221 | --- plugins/place/src/place.cpp 2013-04-10 12:27:25 +0000 |
2222 | +++ plugins/place/src/place.cpp 2013-04-24 14:57:28 +0000 |
2223 | @@ -565,7 +565,7 @@ |
2224 | } |
2225 | |
2226 | switch (mode) { |
2227 | - case PlaceOptions::ModeCascade: |
2228 | + case PlaceOptions::ModeCascade: |
2229 | placeCascade (workArea, pos); |
2230 | break; |
2231 | case PlaceOptions::ModeCentered: |
2232 | @@ -1150,7 +1150,6 @@ |
2233 | window->border (), |
2234 | workArea, |
2235 | staticGravity); |
2236 | - |
2237 | } |
2238 | |
2239 | bool |
2240 | |
2241 | === modified file 'plugins/resize/src/resize.cpp' |
2242 | --- plugins/resize/src/resize.cpp 2012-10-19 09:23:11 +0000 |
2243 | +++ plugins/resize/src/resize.cpp 2013-04-24 14:57:28 +0000 |
2244 | @@ -257,7 +257,7 @@ |
2245 | float xScale, yScale; |
2246 | int x, y; |
2247 | |
2248 | - if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) |
2249 | + if (mask & PAINT_WINDOW_NO_DRAW_MASKS) |
2250 | return false; |
2251 | |
2252 | status = gWindow->glPaint (attrib, transform, region, |
2253 | |
2254 | === modified file 'plugins/ring/src/ring.cpp' |
2255 | --- plugins/ring/src/ring.cpp 2013-01-19 11:47:22 +0000 |
2256 | +++ plugins/ring/src/ring.cpp 2013-04-24 14:57:28 +0000 |
2257 | @@ -264,7 +264,7 @@ |
2258 | GLWindowPaintAttrib wAttrib (gWindow->lastPaintAttrib ()); |
2259 | GLMatrix wTransform = transform; |
2260 | |
2261 | - if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) |
2262 | + if (mask & PAINT_WINDOW_NO_DRAW_MASKS) |
2263 | return false; |
2264 | |
2265 | if (mSlot) |
2266 | |
2267 | === modified file 'plugins/scale/src/scale.cpp' |
2268 | --- plugins/scale/src/scale.cpp 2013-01-29 23:16:32 +0000 |
2269 | +++ plugins/scale/src/scale.cpp 2013-04-24 14:57:28 +0000 |
2270 | @@ -384,12 +384,14 @@ |
2271 | |
2272 | status = gWindow->glPaint (sAttrib, transform, region, mask); |
2273 | |
2274 | + mask &= ~(PAINT_WINDOW_NO_CORE_INSTANCE_MASK); |
2275 | + |
2276 | if (scaled) |
2277 | { |
2278 | GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ()); |
2279 | GLMatrix wTransform (transform); |
2280 | |
2281 | - if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) |
2282 | + if (mask & PAINT_WINDOW_NO_DRAW_MASKS) |
2283 | return false; |
2284 | |
2285 | if (window->alpha () || lastAttrib.opacity != OPAQUE) |
2286 | |
2287 | === modified file 'plugins/staticswitcher/src/staticswitcher.cpp' |
2288 | --- plugins/staticswitcher/src/staticswitcher.cpp 2012-12-10 03:28:47 +0000 |
2289 | +++ plugins/staticswitcher/src/staticswitcher.cpp 2013-04-24 14:57:28 +0000 |
2290 | @@ -1246,7 +1246,7 @@ |
2291 | |
2292 | const CompWindow::Geometry &g = window->geometry (); |
2293 | |
2294 | - if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK || |
2295 | + if (mask & PAINT_WINDOW_NO_DRAW_MASKS || |
2296 | sScreen->ignoreSwitcher) |
2297 | return false; |
2298 | |
2299 | |
2300 | === modified file 'plugins/switcher/src/switcher.cpp' |
2301 | --- plugins/switcher/src/switcher.cpp 2012-12-10 03:28:47 +0000 |
2302 | +++ plugins/switcher/src/switcher.cpp 2013-04-24 14:57:28 +0000 |
2303 | @@ -971,7 +971,7 @@ |
2304 | |
2305 | const CompWindow::Geometry &g = window->geometry (); |
2306 | |
2307 | - if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK || |
2308 | + if (mask & PAINT_WINDOW_NO_DRAW_MASKS || |
2309 | sScreen->ignoreSwitcher) |
2310 | return false; |
2311 | |
2312 | |
2313 | === modified file 'plugins/td/src/3d.cpp' |
2314 | --- plugins/td/src/3d.cpp 2013-02-03 17:50:59 +0000 |
2315 | +++ plugins/td/src/3d.cpp 2013-04-24 14:57:28 +0000 |
2316 | @@ -163,7 +163,7 @@ |
2317 | glGetIntegerv (GL_CULL_FACE_MODE, &cull); |
2318 | cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK; |
2319 | |
2320 | - if (ww && wh && !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) && |
2321 | + if (ww && wh && !(mask & PAINT_WINDOW_NO_DRAW_MASKS) && |
2322 | ((cs->paintOrder () == FTB && mFtb) || |
2323 | (cs->paintOrder () == BTF && !mFtb))) |
2324 | { |
2325 | |
2326 | === modified file 'plugins/water/src/water.cpp' |
2327 | --- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000 |
2328 | +++ plugins/water/src/water.cpp 2013-04-24 14:57:28 +0000 |
2329 | @@ -317,6 +317,12 @@ |
2330 | } |
2331 | } |
2332 | |
2333 | +bool |
2334 | +WaterScreen::glPaintCompositedOutputRequired () |
2335 | +{ |
2336 | + return true; |
2337 | +} |
2338 | + |
2339 | void |
2340 | WaterScreen::glPaintCompositedOutput (const CompRegion ®ion, |
2341 | GLFramebufferObject *fbo, |
2342 | @@ -467,6 +473,7 @@ |
2343 | cScreen->preparePaintSetEnabled (this, false); |
2344 | gScreen->glPaintOutputSetEnabled (this, false); |
2345 | gScreen->glPaintCompositedOutputSetEnabled (this, false); |
2346 | + gScreen->glPaintCompositedOutputRequiredSetEnabled (this, false); |
2347 | cScreen->donePaintSetEnabled (this, false); |
2348 | } |
2349 | |
2350 | |
2351 | === modified file 'plugins/water/src/water.h' |
2352 | --- plugins/water/src/water.h 2012-09-07 23:56:21 +0000 |
2353 | +++ plugins/water/src/water.h 2013-04-24 14:57:28 +0000 |
2354 | @@ -64,6 +64,7 @@ |
2355 | |
2356 | void handleEvent (XEvent *); |
2357 | |
2358 | + bool glPaintCompositedOutputRequired (); |
2359 | void glPaintCompositedOutput (const CompRegion ®ion, |
2360 | GLFramebufferObject *fbo, |
2361 | unsigned int mask); |
2362 | |
2363 | === modified file 'src/window.cpp' |
2364 | --- src/window.cpp 2013-03-27 01:55:26 +0000 |
2365 | +++ src/window.cpp 2013-04-24 14:57:28 +0000 |
2366 | @@ -3222,7 +3222,7 @@ |
2367 | if (serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top) |
2368 | frameValueMask &= ~(CWY); |
2369 | |
2370 | - if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2 |
2371 | + if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2 |
2372 | + serverInput.left + serverInput.right) |
2373 | frameValueMask &= ~(CWWidth); |
2374 | |
2375 | @@ -6922,7 +6922,7 @@ |
2376 | * but that's all */ |
2377 | XSelectInput (dpy, screen->root (), SubstructureNotifyMask); |
2378 | |
2379 | - /* Gravity here is assumed to be SouthEast, clients can update |
2380 | + /* Gravity here is assumed to be NorthWest, clients can update |
2381 | * that if need be */ |
2382 | |
2383 | /* Awaiting a new frame to be given to us */ |
FAILED: Continuous integration, rev:3556 jenkins. qa.ubuntu. com/job/ compiz- ci/8/ jenkins. qa.ubuntu. com/job/ compiz- clang-ci/ ./build= pbuilder, distribution= quantal, flavor= amd64/46/ console jenkins. qa.ubuntu. com/job/ compiz- gles-ci/ ./build= pbuilder, distribution= quantal, flavor= amd64/45/ console jenkins. qa.ubuntu. com/job/ compiz- pbuilder/ ./build= pbuilder, distribution= quantal, flavor= amd64/397/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: jenkins. qa.ubuntu. com/job/ compiz- ci/8//rebuild/?
http://