Merge lp:~compiz-team/compiz/compiz.fix_1024304.1 into lp:compiz/0.9.10

Proposed by Sam Spilsbury
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
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://code.launchpad.net/~smspillaz/nux/nux.fix_1091589/+merge/147543 (WindowThread::PresentWindowsIntersectingGeometryOnThisFrame, WindowThread::ForeignFrameCutoff, WindowThread::ForeignFrameEnded)
2. https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544 (make unity use the new APIs)

Note 2: I don't have any solid numbers on this yet. Daniel reported a 10% difference with redirect-to-fbo-on-each-frame in bug 1024304, so I think that is a good start, because with this branch we are effectively not doing that (on NVIDIA). I've got some testers to gather some more concrete numbers in a few days.

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

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

Compiz framerate graph:

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

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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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://ubuntuone.com/2JNLvWQiYiQmOCAca0bIEn

review: Approve (testing, benchmarking)
Revision history for this message
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.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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.

review: Needs Fixing
Revision history for this message
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://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
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://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
>> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>
>
>
> --
> Sam Spilsbury

--
Sam Spilsbury

Revision history for this message
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.

review: Approve (build&run)
Revision history for this message
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-on-any-damage hook), and those changes are quite substantial.

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 :(

Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal
review: Needs Information
Revision history for this message
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://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544
https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589/+merge/147543

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

@Timo: at the moment, it kinda pulls in https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1040478/+merge/150949 because I wrote https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544 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.

Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal

> @Timo: at the moment, it kinda pulls in https://code.launchpad.net/~compiz-
> team/compiz/compiz.fix_1040478/+merge/150949 because I wrote
> https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544
> 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

Revision history for this message
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://code.launchpad.net/~compiz-
>> team/compiz/compiz.fix_1040478/+merge/150949 because I wrote
>> https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544
>> 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://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
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.

Revision history for this message
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://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>

Revision history for this message
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.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Please re-target this for lp:compiz/0.9.10

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

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

3632. By Sam Spilsbury

Merge lp:compiz

3633. By Sam Spilsbury

Merge lp:compiz

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
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 addOverdrawDamageRegion to recordDamageOnCurrentFrame 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 addOverdrawDamageRegion to recordDamageOnCurrentFrame 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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 &region) = 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 &region) = 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 &reg);
331+ void markAreaDirtyOnLastFrame (const CompRegion &reg);
332+ void subtractObscuredArea (const CompRegion &reg);
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 &reg)
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 &reg)
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 &reg)
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 &reg)
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 &region)
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 */

Subscribers

People subscribed via source and target branches

to all changes: