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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1024304.1
Merge into: lp:compiz/0.9.9
Diff against target: 2339 lines (+1490/-85)
25 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 (+137/-12)
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/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)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1024304.1
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Resubmitting
Andrea Azzarone Needs Information
Timo Jyrinki build&run Approve
PS Jenkins bot (community) continuous-integration Approve
Esokrates testing, benchmarking Pending
Review via email: mp+150951@code.launchpad.net

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

This proposal has been superseded by a proposal from 2013-04-02.

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 :
review: Approve (continuous-integration)
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

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 :

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 :

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 :

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 :

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 :
review: Needs Information
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

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 :

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

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

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 :

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 :

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 :

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 :

Please re-target this for lp:compiz/0.9.10

review: Needs Resubmitting
3629. By Sam Spilsbury

Merge lp:compiz

3630. By Sam Spilsbury

Placement temp

3631. By Sam Spilsbury

Merge lp:compiz

3632. By Sam Spilsbury

Merge lp:compiz

3633. By Sam Spilsbury

Merge lp:compiz

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-01-11 08:28:51 +0000
3+++ plugins/animation/src/animation.cpp 2013-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-02-28 03:45:26 +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-01-28 19:22:29 +0000
1155+++ plugins/composite/src/screen.cpp 2013-02-28 03:45:26 +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@@ -276,6 +278,14 @@
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@@ -294,6 +304,7 @@
1181 randrEvent (0),
1182 randrError (0),
1183 damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK),
1184+ currentlyTrackingDamage (DamageForCurrentFrame),
1185 overlay (None),
1186 output (None),
1187 exposeRects (),
1188@@ -305,12 +316,16 @@
1189 scheduled (false),
1190 painting (false),
1191 reschedule (false),
1192+ damageRequiresRepaintReschedule (true),
1193 slowAnimations (false),
1194 pHnd (NULL),
1195 FPSLimiterMode (CompositeFPSLimiterModeDefault),
1196 withDestroyedWindows (),
1197 cmSnAtom (0),
1198- newCmSnOwner (None)
1199+ newCmSnOwner (None),
1200+ roster (*screen,
1201+ ageingBuffers,
1202+ boost::bind (alwaysMarkDirty))
1203 {
1204 gettimeofday (&lastRedraw, 0);
1205 // wrap outputChangeNotify
1206@@ -491,15 +506,47 @@
1207 return false;
1208 }
1209
1210+const CompRegion *
1211+PrivateCompositeScreen::damageTrackedBuffer (const CompRegion &region)
1212+{
1213+ const CompRegion *currentDamage = NULL;
1214+
1215+ switch (currentlyTrackingDamage)
1216+ {
1217+ case DamageForCurrentFrame:
1218+ currentDamage = &(roster.currentFrameDamage ());
1219+ ageingBuffers.markAreaDirty (region);
1220+ break;
1221+ case DamageForLastFrame:
1222+ currentDamage = &(lastFrameDamage);
1223+ lastFrameDamage += region;
1224+ break;
1225+ case DamageFinalPaintRegion:
1226+ currentDamage = &(tmpRegion);
1227+ tmpRegion += region;
1228+ break;
1229+ default:
1230+ compLogMessage ("composite", CompLogLevelFatal, "unreachable section");
1231+ assert (false);
1232+ abort ();
1233+ }
1234+
1235+ assert (currentDamage);
1236+ return currentDamage;
1237+}
1238+
1239 void
1240 CompositeScreen::damageScreen ()
1241 {
1242+ /* Don't tell plugins about damage events when the damage buffer is already full */
1243 bool alreadyDamaged = priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
1244+ alreadyDamaged |= ((currentDamage () & screen->region ()) == screen->region ());
1245
1246 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
1247 priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
1248
1249- priv->scheduleRepaint ();
1250+ if (priv->damageRequiresRepaintReschedule)
1251+ priv->scheduleRepaint ();
1252
1253 /*
1254 * Call through damageRegion since plugins listening for incoming damage
1255@@ -507,7 +554,15 @@
1256 */
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@@ -518,7 +573,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@@ -526,16 +586,61 @@
1286 in order to make sure we're not having too much overhead, damage
1287 the whole screen if we have a lot of damage rects */
1288
1289- if (priv->damage.numRects () > 100)
1290- damageScreen ();
1291- priv->scheduleRepaint ();
1292+ if (currentDamage->numRects () > 100)
1293+ damageScreen ();
1294+
1295+ if (priv->damageRequiresRepaintReschedule)
1296+ priv->scheduleRepaint ();
1297+}
1298+
1299+void
1300+CompositeScreen::damageCutoff ()
1301+{
1302+ WRAPABLE_HND_FUNCTN (damageCutoff);
1303 }
1304
1305 void
1306 CompositeScreen::damagePending ()
1307 {
1308 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;
1309- priv->scheduleRepaint ();
1310+
1311+ if (priv->damageRequiresRepaintReschedule)
1312+ priv->scheduleRepaint ();
1313+}
1314+
1315+void
1316+CompositeScreen::applyDamageForFrameAge (unsigned int age)
1317+{
1318+ /* Track into "last frame damage" */
1319+ priv->currentlyTrackingDamage = DamageForLastFrame;
1320+ damageRegion (priv->roster.damageForFrameAge (age));
1321+ priv->currentlyTrackingDamage = DamageForCurrentFrame;
1322+}
1323+
1324+unsigned int
1325+CompositeScreen::getFrameAge ()
1326+{
1327+ if (priv->pHnd)
1328+ return priv->pHnd->getFrameAge ();
1329+
1330+ return 1;
1331+}
1332+
1333+void
1334+CompositeScreen::addOverdrawDamageRegion (const CompRegion &r)
1335+{
1336+ priv->ageingBuffers.markAreaDirtyOnLastFrame (r);
1337+}
1338+
1339+typedef CompositeScreen::AreaShouldBeMarkedDirty ShouldMarkDirty;
1340+
1341+CompositeScreen::DamageQuery::Ptr
1342+CompositeScreen::getDamageQuery (const ShouldMarkDirty &callback)
1343+{
1344+ /* No initial damage */
1345+ return bt::FrameRoster::Ptr (new bt::FrameRoster (CompSize (),
1346+ priv->ageingBuffers,
1347+ callback));
1348 }
1349
1350 unsigned int
1351@@ -780,6 +885,10 @@
1352 {
1353 int timeDiff;
1354
1355+ /* Damage that accumulates here does not require a repaint reschedule
1356+ * as it will end up on this frame */
1357+ priv->damageRequiresRepaintReschedule = false;
1358+
1359 if (priv->pHnd)
1360 priv->pHnd->prepareDrawing ();
1361
1362@@ -814,7 +923,7 @@
1363 continue;
1364
1365 if (!CompositeWindow::get (w)->redirected ())
1366- priv->damage -= w->region ();
1367+ priv->ageingBuffers.subtractObscuredArea (w->region ());
1368
1369 break;
1370 }
1371@@ -826,7 +935,13 @@
1372 }
1373 }
1374
1375- priv->tmpRegion = priv->damage & screen->region ();
1376+ /* All further damage is for the next frame now, as
1377+ * priv->tmpRegion will be assigned. Notify plugins that do
1378+ * damage tracking of this */
1379+ damageCutoff ();
1380+
1381+ priv->tmpRegion = (priv->roster.currentFrameDamage () + priv->lastFrameDamage) & screen->region ();
1382+ priv->currentlyTrackingDamage = DamageFinalPaintRegion;
1383
1384 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
1385 {
1386@@ -848,7 +963,9 @@
1387 XSync (dpy, False);
1388 priv->damages.clear ();
1389
1390- priv->damage = CompRegion ();
1391+ /* Any more damage requires a repaint reschedule */
1392+ priv->damageRequiresRepaintReschedule = true;
1393+ priv->lastFrameDamage = CompRegion ();
1394
1395 int mask = priv->damageMask;
1396 priv->damageMask = 0;
1397@@ -864,9 +981,13 @@
1398 else
1399 outputs.push_back (&screen->fullscreenOutput ());
1400
1401+ priv->currentlyTrackingDamage = DamageForCurrentFrame;
1402+
1403+ /* All new damage goes on the next frame */
1404+ priv->ageingBuffers.incrementAges ();
1405+
1406 paint (outputs, mask);
1407
1408-
1409 donePaint ();
1410
1411 priv->outputShapeChanged = false;
1412@@ -1023,8 +1144,12 @@
1413 CompositeScreenInterface::damageRegion (const CompRegion &r)
1414 WRAPABLE_DEF (damageRegion, r);
1415
1416+void
1417+CompositeScreenInterface::damageCutoff ()
1418+ WRAPABLE_DEF (damageCutoff);
1419+
1420 const CompRegion &
1421 CompositeScreen::currentDamage () const
1422 {
1423- return priv->damage;
1424+ return priv->roster.currentFrameDamage ();
1425 }
1426
1427=== modified file 'plugins/kdecompat/src/kdecompat.cpp'
1428--- plugins/kdecompat/src/kdecompat.cpp 2012-08-14 06:33:22 +0000
1429+++ plugins/kdecompat/src/kdecompat.cpp 2013-02-28 03:45:26 +0000
1430@@ -196,7 +196,7 @@
1431 if ((!(ks->optionGetPlasmaThumbnails () || mPreviews.empty ()) &&
1432 !(mSlideData || mSlideData->remaining)) ||
1433 !window->mapNum () ||
1434- (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
1435+ (mask & PAINT_WINDOW_NO_DRAW_MASKS))
1436 {
1437 status = gWindow->glPaint (attrib, transform, region, mask);
1438 return status;
1439@@ -210,7 +210,7 @@
1440 CompRect clipBox (window->x (), window->y (),
1441 window->width (), window->height ());
1442
1443- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
1444+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
1445 return false;
1446
1447 remainder = (float) data->remaining / data->duration;
1448
1449=== modified file 'plugins/opengl/include/opengl/opengl.h'
1450--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
1451+++ plugins/opengl/include/opengl/opengl.h 2013-02-28 03:45:26 +0000
1452@@ -37,6 +37,13 @@
1453 #else
1454 #include <GL/gl.h>
1455 #include <GL/glx.h>
1456+
1457+/* Some implementations have not yet given a definition
1458+ * to GLX_BACK_BUFFER_AGE_EXT but this is the token as defined
1459+ * in the spec (https://www.opengl.org/registry/specs/EXT/glx_buffer_age.txt)
1460+ */
1461+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
1462+
1463 #endif
1464
1465 #include <core/size.h>
1466@@ -50,7 +57,7 @@
1467 #include <opengl/programcache.h>
1468 #include <opengl/shadercache.h>
1469
1470-#define COMPIZ_OPENGL_ABI 6
1471+#define COMPIZ_OPENGL_ABI 8
1472
1473 /*
1474 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
1475@@ -525,6 +532,7 @@
1476 extern bool shaders;
1477 extern bool stencilBuffer;
1478 extern GLint maxTextureUnits;
1479+ extern bool bufferAge;
1480
1481 extern bool canDoSaturated;
1482 extern bool canDoSlightlySaturated;
1483@@ -663,6 +671,11 @@
1484 unsigned int mask);
1485
1486 /**
1487+ * Return true if glPaintCompositedOutput is required for this frame
1488+ */
1489+ virtual bool glPaintCompositedOutputRequired ();
1490+
1491+ /**
1492 * Hookable function used by plugins to determine stenciling mask
1493 */
1494 virtual void glBufferStencil (const GLMatrix &matrix,
1495@@ -674,7 +687,7 @@
1496 extern template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>;
1497
1498 class GLScreen :
1499- public WrapableHandler<GLScreenInterface, 8>,
1500+ public WrapableHandler<GLScreenInterface, 9>,
1501 public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>,
1502 public CompOption::Class
1503 {
1504@@ -788,7 +801,9 @@
1505 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
1506 const CompRegion &, GLFramebufferObject *, unsigned int);
1507
1508- WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
1509+ WRAPABLE_HND (7, GLScreenInterface, bool, glPaintCompositedOutputRequired);
1510+
1511+ WRAPABLE_HND (8, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
1512 GLVertexBuffer &,
1513 CompOutput *);
1514
1515
1516=== modified file 'plugins/opengl/src/paint.cpp'
1517--- plugins/opengl/src/paint.cpp 2013-01-03 16:05:26 +0000
1518+++ plugins/opengl/src/paint.cpp 2013-02-28 03:45:26 +0000
1519@@ -418,11 +418,6 @@
1520 if (w->destroyed ())
1521 continue;
1522
1523- gw = GLWindow::get (w);
1524-
1525- /* Release any queued ConfigureWindow requests now */
1526- gw->priv->configureLock->release ();
1527-
1528 if (unredirected.find (w) != unredirected.end ())
1529 continue;
1530
1531@@ -432,6 +427,8 @@
1532 continue;
1533 }
1534
1535+ gw = GLWindow::get (w);
1536+
1537 const CompRegion &clip =
1538 (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ?
1539 gw->clip () : region;
1540@@ -629,8 +626,8 @@
1541 if (mask & PAINT_SCREEN_FULL_MASK)
1542 {
1543 glPaintTransformedOutput (sAttrib, sTransform,
1544- CompRegion (*output), output, mask);
1545-
1546+ CompRegionRef (output->region ()), output, mask);
1547+ priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
1548 return true;
1549 }
1550
1551@@ -660,8 +657,9 @@
1552 }
1553 else if (mask & PAINT_SCREEN_FULL_MASK)
1554 {
1555- glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output),
1556+ glPaintTransformedOutput (sAttrib, sTransform, CompRegionRef (output->region ()),
1557 output, mask);
1558+ priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
1559
1560 return true;
1561 }
1562@@ -671,6 +669,13 @@
1563 }
1564 }
1565
1566+bool
1567+GLScreen::glPaintCompositedOutputRequired ()
1568+{
1569+ WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintCompositedOutputRequired);
1570+ return false;
1571+}
1572+
1573 void
1574 GLScreen::glPaintCompositedOutput (const CompRegion &region,
1575 GLFramebufferObject *fbo,
1576
1577=== modified file 'plugins/opengl/src/privates.h'
1578--- plugins/opengl/src/privates.h 2013-01-03 16:05:26 +0000
1579+++ plugins/opengl/src/privates.h 2013-02-28 03:45:26 +0000
1580@@ -29,11 +29,13 @@
1581 #define _OPENGL_PRIVATES_H
1582
1583 #include <memory>
1584+#include <vector>
1585+#include <tr1/tuple>
1586+#include <boost/shared_ptr.hpp>
1587
1588 #include <composite/composite.h>
1589 #include <opengl/opengl.h>
1590 #include <core/atoms.h>
1591-#include <core/configurerequestbuffer.h>
1592
1593 #ifdef USE_GLES
1594 #include <opengl/framebufferobject.h>
1595@@ -120,8 +122,26 @@
1596 GLTexture::List textures;
1597 };
1598
1599+class FrameProvider
1600+{
1601+ public:
1602+
1603+ typedef boost::shared_ptr <FrameProvider> Ptr;
1604+ typedef std::tr1::tuple <GLFramebufferObject *, int> Frame;
1605+
1606+ virtual ~FrameProvider () {}
1607+
1608+ virtual GLuint getCurrentFrame () = 0;
1609+ virtual void endFrame () = 0;
1610+
1611+ virtual bool providesPersistence () = 0;
1612+ virtual bool alwaysPostprocess () = 0;
1613+ virtual void invalidateAll () = 0;
1614+};
1615+
1616 class PrivateGLScreen :
1617 public ScreenInterface,
1618+ public CompositeScreenInterface,
1619 public compiz::composite::PaintHandler,
1620 public OpenglOptions
1621 {
1622@@ -142,12 +162,17 @@
1623 bool hasVSync ();
1624 bool requiredForcedRefreshRate ();
1625
1626+ unsigned int getFrameAge ();
1627+
1628 void updateRenderMode ();
1629+ void updateFrameProvider ();
1630
1631 void prepareDrawing ();
1632
1633 bool compositingActive ();
1634
1635+ void damageCutoff ();
1636+
1637 void paintBackground (const GLMatrix &transform,
1638 const CompRegion &region,
1639 bool transformed);
1640@@ -163,6 +188,8 @@
1641
1642 bool driverIsBlacklisted (const char *regex) const;
1643
1644+ bool postprocessRequiredForCurrentFrame ();
1645+
1646 public:
1647
1648 GLScreen *gScreen;
1649@@ -197,7 +224,7 @@
1650 GLXDoubleBuffer doubleBuffer;
1651 #endif
1652
1653- GLFramebufferObject *scratchFbo;
1654+ boost::shared_ptr <GLFramebufferObject> scratchFbo;
1655 CompRegion outputRegion;
1656
1657 XRectangle lastViewport;
1658@@ -222,8 +249,10 @@
1659 Pixmap rootPixmapCopy;
1660 CompSize rootPixmapSize;
1661
1662+ FrameProvider::Ptr frameProvider;
1663 const char *glVendor, *glRenderer, *glVersion;
1664
1665+ bool postprocessingRequired;
1666 mutable CompString prevRegex;
1667 mutable bool prevBlacklisted;
1668 };
1669@@ -284,8 +313,6 @@
1670 GLVertexBuffer::AutoProgram *autoProgram;
1671
1672 std::list<GLIcon> icons;
1673-
1674- compiz::window::configure_buffers::Releasable::Ptr configureLock;
1675 };
1676
1677 #endif
1678
1679=== modified file 'plugins/opengl/src/screen.cpp'
1680--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
1681+++ plugins/opengl/src/screen.cpp 2013-02-28 03:45:26 +0000
1682@@ -186,6 +186,7 @@
1683 bool vboEnabled = false;
1684 bool shaders = false;
1685 GLint maxTextureUnits = 1;
1686+ bool bufferAge = false;
1687
1688 bool canDoSaturated = false;
1689 bool canDoSlightlySaturated = false;
1690@@ -301,6 +302,52 @@
1691
1692 #ifndef USE_GLES
1693
1694+class BufferAgeFrameProvider :
1695+ public FrameProvider
1696+{
1697+ public:
1698+
1699+ BufferAgeFrameProvider (Display *disp,
1700+ GLXDrawable drawable) :
1701+ mDisplay (disp),
1702+ mDrawable (drawable)
1703+ {
1704+ }
1705+
1706+ unsigned int getCurrentFrame ()
1707+ {
1708+ unsigned int age = 0;
1709+ (*GL::queryDrawable) (mDisplay,
1710+ mDrawable,
1711+ GLX_BACK_BUFFER_AGE_EXT,
1712+ &age);
1713+ return age;
1714+ }
1715+
1716+ void endFrame ()
1717+ {
1718+ }
1719+
1720+ void invalidateAll ()
1721+ {
1722+ }
1723+
1724+ bool providesPersistence ()
1725+ {
1726+ return true;
1727+ }
1728+
1729+ bool alwaysPostprocess ()
1730+ {
1731+ return false;
1732+ }
1733+
1734+ private:
1735+
1736+ Display *mDisplay;
1737+ GLXDrawable mDrawable;
1738+};
1739+
1740 namespace compiz
1741 {
1742 namespace opengl
1743@@ -358,6 +405,137 @@
1744
1745 #endif
1746
1747+class UndefinedFrameProvider :
1748+ public FrameProvider
1749+{
1750+ public:
1751+
1752+ unsigned int getCurrentFrame ()
1753+ {
1754+ return 0;
1755+ }
1756+
1757+ void endFrame ()
1758+ {
1759+ }
1760+
1761+ void invalidateAll ()
1762+ {
1763+ }
1764+
1765+ bool providesPersistence ()
1766+ {
1767+ return false;
1768+ }
1769+
1770+ bool alwaysPostprocess ()
1771+ {
1772+ return false;
1773+ }
1774+};
1775+
1776+class PostprocessFrameProvider :
1777+ public FrameProvider
1778+{
1779+ public:
1780+
1781+ PostprocessFrameProvider (GLFramebufferObject *object) :
1782+ mObject (object),
1783+ mAge (0)
1784+ {
1785+ }
1786+
1787+ unsigned int getCurrentFrame ()
1788+ {
1789+ /* We are now using this buffer, reset
1790+ * age back to zero */
1791+ unsigned int lastAge = mAge;
1792+ mAge = 0;
1793+
1794+ return lastAge;
1795+ }
1796+
1797+ void endFrame ()
1798+ {
1799+ ++mAge;
1800+ }
1801+
1802+ void invalidateAll ()
1803+ {
1804+ mAge = 0;
1805+ }
1806+
1807+ bool providesPersistence ()
1808+ {
1809+ return true;
1810+ }
1811+
1812+ bool alwaysPostprocess ()
1813+ {
1814+ return true;
1815+ }
1816+
1817+ private:
1818+
1819+ GLFramebufferObject *mObject;
1820+ unsigned int mAge;
1821+};
1822+
1823+class OptionalPostprocessFrameProvider :
1824+ public FrameProvider
1825+{
1826+ public:
1827+
1828+ typedef boost::function <bool ()> PostprocessRequired;
1829+
1830+ OptionalPostprocessFrameProvider (const FrameProvider::Ptr &backbuffer,
1831+ const FrameProvider::Ptr &scratchbuffer,
1832+ const PostprocessRequired &ppRequired) :
1833+ mBackbuffer (backbuffer),
1834+ mScratchbuffer (scratchbuffer),
1835+ mPPRequired (ppRequired)
1836+ {
1837+ }
1838+
1839+ unsigned int getCurrentFrame ()
1840+ {
1841+ if (mPPRequired ())
1842+ return mScratchbuffer->getCurrentFrame ();
1843+ else
1844+ return mBackbuffer->getCurrentFrame ();
1845+ }
1846+
1847+ void endFrame ()
1848+ {
1849+ mScratchbuffer->endFrame ();
1850+ }
1851+
1852+ void invalidateAll ()
1853+ {
1854+ mScratchbuffer->invalidateAll ();
1855+ }
1856+
1857+ bool providesPersistence ()
1858+ {
1859+ /* We are only as good as the backbuffer is */
1860+ return mBackbuffer->providesPersistence ();
1861+ }
1862+
1863+ bool alwaysPostprocess ()
1864+ {
1865+ if (mPPRequired ())
1866+ return mScratchbuffer->alwaysPostprocess ();
1867+ else
1868+ return mBackbuffer->alwaysPostprocess ();
1869+ }
1870+
1871+ private:
1872+
1873+ FrameProvider::Ptr mBackbuffer;
1874+ FrameProvider::Ptr mScratchbuffer;
1875+ PostprocessRequired mPPRequired;
1876+};
1877+
1878 bool
1879 GLScreen::glInitContext (XVisualInfo *visinfo)
1880 {
1881@@ -593,6 +771,8 @@
1882
1883 priv->incorrectRefreshRate = false;
1884
1885+ priv->frameProvider.reset (new PostprocessFrameProvider ());
1886+
1887 #else
1888
1889 Display *dpy = screen->dpy ();
1890@@ -899,12 +1079,17 @@
1891
1892 if (GL::fboSupported)
1893 {
1894- priv->scratchFbo = new GLFramebufferObject;
1895+ priv->scratchFbo.reset (new GLFramebufferObject ());
1896 priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
1897 }
1898
1899 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
1900
1901+ /* We need scratchFbo to be set before doing this, and it is common
1902+ * to both the GLES and non-GLES codepaths, so using another #ifdef
1903+ */
1904+ priv->updateFrameProvider ();
1905+
1906 return true;
1907 }
1908
1909@@ -993,6 +1178,13 @@
1910 return;
1911 }
1912
1913+ if (strstr (glxExtensions, "GLX_EXT_buffer_age"))
1914+ {
1915+ compLogMessage ("opengl", CompLogLevelInfo,
1916+ "GLX_EXT_buffer_age is supported");
1917+ GL::bufferAge = true;
1918+ }
1919+
1920 priv->getProcAddress = (GL::GLXGetProcAddressProc)
1921 getProcAddress ("glXGetProcAddressARB");
1922 GL::bindTexImage = (GL::GLXBindTexImageProc)
1923@@ -1209,9 +1401,6 @@
1924 glXDestroyContext (screen->dpy (), priv->ctx);
1925 #endif
1926
1927- if (priv->scratchFbo)
1928- delete priv->scratchFbo;
1929-
1930 delete priv;
1931 }
1932
1933@@ -1233,7 +1422,7 @@
1934 ctx (EGL_NO_CONTEXT),
1935 doubleBuffer (screen->dpy (), *screen, surface),
1936 #endif
1937- scratchFbo (NULL),
1938+ scratchFbo (),
1939 outputRegion (),
1940 refreshSubBuffer (false),
1941 lastMask (0),
1942@@ -1246,13 +1435,16 @@
1943 autoProgram (new GLScreenAutoProgram(gs)),
1944 rootPixmapCopy (None),
1945 rootPixmapSize (),
1946+ frameProvider (),
1947 glVendor (NULL),
1948 glRenderer (NULL),
1949 glVersion (NULL),
1950+ postprocessingRequired (false),
1951 prevRegex (),
1952 prevBlacklisted (false)
1953 {
1954 ScreenInterface::setHandler (screen);
1955+ CompositeScreenInterface::setHandler (cScreen);
1956 }
1957
1958 PrivateGLScreen::~PrivateGLScreen ()
1959@@ -1443,8 +1635,11 @@
1960 {
1961 screen->outputChangeNotify ();
1962
1963+ frameProvider->invalidateAll ();
1964+
1965 if (scratchFbo)
1966 scratchFbo->allocate (*screen, NULL, GL_BGRA);
1967+
1968 updateView ();
1969 }
1970
1971@@ -1669,6 +1864,10 @@
1972 GLScreenInterface::projectionMatrix ()
1973 WRAPABLE_DEF (projectionMatrix)
1974
1975+bool
1976+GLScreenInterface::glPaintCompositedOutputRequired ()
1977+ WRAPABLE_DEF (glPaintCompositedOutputRequired)
1978+
1979 void
1980 GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
1981 GLFramebufferObject *fbo,
1982@@ -1977,18 +2176,6 @@
1983 glDepthMask (GL_FALSE);
1984 glStencilMask (0);
1985
1986- GLFramebufferObject *oldFbo = NULL;
1987- bool useFbo = false;
1988-
1989- /* Clear the color buffer where appropriate */
1990- if (GL::fboEnabled && scratchFbo)
1991- {
1992- oldFbo = scratchFbo->bind ();
1993- useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
1994- if (!useFbo)
1995- GLFramebufferObject::rebind (oldFbo);
1996- }
1997-
1998 #ifdef UNSAFE_ARM_SGX_FIXME
1999 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2000 !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2001@@ -2006,8 +2193,21 @@
2002 }
2003 #endif
2004
2005- CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2006- screen->region () : region;
2007+ CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2008+ screen->region () : region);
2009+ bool useFbo = false;
2010+ GLFramebufferObject *oldFbo = NULL;
2011+
2012+ postprocessingRequired = gScreen->glPaintCompositedOutputRequired ();
2013+ postprocessingRequired |= frameProvider->alwaysPostprocess ();
2014+
2015+ /* Clear the color buffer where appropriate */
2016+ if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ()))
2017+ {
2018+ oldFbo = scratchFbo->bind ();
2019+ if (scratchFbo->checkStatus ())
2020+ useFbo = true;
2021+ }
2022
2023 foreach (CompOutput *output, outputs)
2024 {
2025@@ -2034,7 +2234,8 @@
2026
2027 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2028 identity,
2029- CompRegion (*output), output,
2030+ CompRegion (*output),
2031+ output,
2032 PAINT_SCREEN_REGION_MASK |
2033 PAINT_SCREEN_FULL_MASK);
2034 }
2035@@ -2057,7 +2258,9 @@
2036 tmpRegion = CompRegion (*output);
2037 #endif
2038
2039- outputRegion = tmpRegion & CompRegion (*output);
2040+ /* Clip current paint region to output extents */
2041+ CompRegionRef wholeOutput (output->region ());
2042+ outputRegion = (paintRegion & wholeOutput);
2043
2044 if (!gScreen->glPaintOutput (defaultScreenPaintAttrib,
2045 identity,
2046@@ -2068,10 +2271,11 @@
2047
2048 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2049 identity,
2050- CompRegion (*output), output,
2051+ wholeOutput, output,
2052 PAINT_SCREEN_FULL_MASK);
2053
2054- tmpRegion += *output;
2055+ paintRegion += wholeOutput;
2056+ cScreen->addOverdrawDamageRegion (wholeOutput);
2057 }
2058 }
2059 }
2060@@ -2082,13 +2286,18 @@
2061
2062 if (useFbo)
2063 {
2064- GLFramebufferObject::rebind (oldFbo);
2065-
2066 // FIXME: does not work if screen dimensions exceed max texture size
2067 // We should try to use glBlitFramebuffer instead.
2068- gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);
2069+ GLFramebufferObject::rebind (oldFbo);
2070+ /* If we must always postprocess, then we don't have any
2071+ * "real" backbuffer persistence, redraw the whole thing */
2072+ gScreen->glPaintCompositedOutput (frameProvider->alwaysPostprocess () ?
2073+ screen->region () :
2074+ paintRegion, scratchFbo.get (), mask);
2075 }
2076
2077+ frameProvider->endFrame ();
2078+
2079 if (cScreen->outputWindowChanged ())
2080 {
2081 /*
2082@@ -2100,20 +2309,27 @@
2083 return;
2084 }
2085
2086+ bool persistence = frameProvider->providesPersistence ();
2087 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2088- bool fullscreen = useFbo ||
2089+ bool fullscreen = persistence ||
2090 alwaysSwap ||
2091 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2092 commonFrontbuffer);
2093
2094 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2095- doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
2096+ doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, persistence);
2097 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2098- doubleBuffer.render (tmpRegion, fullscreen);
2099+ doubleBuffer.render (paintRegion, fullscreen);
2100
2101 lastMask = mask;
2102 }
2103
2104+unsigned int
2105+PrivateGLScreen::getFrameAge ()
2106+{
2107+ return frameProvider->getCurrentFrame ();
2108+}
2109+
2110 bool
2111 PrivateGLScreen::hasVSync ()
2112 {
2113@@ -2138,6 +2354,13 @@
2114 }
2115
2116 void
2117+PrivateGLScreen::damageCutoff ()
2118+{
2119+ cScreen->applyDamageForFrameAge (frameProvider->getCurrentFrame ());
2120+ cScreen->damageCutoff ();
2121+}
2122+
2123+void
2124 PrivateGLScreen::updateRenderMode ()
2125 {
2126 #ifndef USE_GLES
2127@@ -2147,12 +2370,54 @@
2128 }
2129
2130 void
2131+PrivateGLScreen::updateFrameProvider ()
2132+{
2133+#ifndef USE_GLES
2134+ const Window outputWindow = CompositeScreen::get (screen)->output ();
2135+
2136+ if (GL::fboEnabled)
2137+ {
2138+ if (GL::bufferAge)
2139+ {
2140+ FrameProvider::Ptr back (new BufferAgeFrameProvider (screen->dpy (),
2141+ outputWindow));
2142+ FrameProvider::Ptr scratch (new PostprocessFrameProvider (scratchFbo.get ()));
2143+ OptionalPostprocessFrameProvider::PostprocessRequired ppReq
2144+ (boost::bind (&PrivateGLScreen::postprocessRequiredForCurrentFrame,
2145+ this));
2146+ frameProvider.reset (new OptionalPostprocessFrameProvider (back,
2147+ scratch,
2148+ ppReq));
2149+ }
2150+ else
2151+ {
2152+ /* Prefer using FBO's instead of switching between a defined/undefined backbuffer */
2153+ frameProvider.reset (new PostprocessFrameProvider (scratchFbo.get ()));
2154+ }
2155+ }
2156+ else
2157+ {
2158+ if (GL::bufferAge)
2159+ frameProvider.reset (new BufferAgeFrameProvider (screen->dpy (),
2160+ outputWindow));
2161+ else
2162+ frameProvider.reset (new UndefinedFrameProvider ());
2163+ }
2164+#else
2165+ frameProvider.reset (new PostprocessFrameProvider (scratchFbo.get ()));
2166+#endif
2167+}
2168+
2169+void
2170 PrivateGLScreen::prepareDrawing ()
2171 {
2172 bool wasFboEnabled = GL::fboEnabled;
2173 updateRenderMode ();
2174 if (wasFboEnabled != GL::fboEnabled)
2175+ {
2176+ updateFrameProvider ();
2177 CompositeScreen::get (screen)->damageScreen ();
2178+ }
2179 }
2180
2181 bool
2182@@ -2170,6 +2435,12 @@
2183 return prevBlacklisted;
2184 }
2185
2186+bool
2187+PrivateGLScreen::postprocessRequiredForCurrentFrame ()
2188+{
2189+ return postprocessingRequired;
2190+}
2191+
2192 GLTexture::BindPixmapHandle
2193 GLScreen::registerBindPixmap (GLTexture::BindPixmapProc proc)
2194 {
2195@@ -2198,7 +2469,7 @@
2196 GLFramebufferObject *
2197 GLScreen::fbo ()
2198 {
2199- return priv->scratchFbo;
2200+ return priv->scratchFbo.get ();
2201 }
2202
2203 GLTexture *
2204
2205=== modified file 'plugins/opengl/src/window.cpp'
2206--- plugins/opengl/src/window.cpp 2013-01-03 16:05:26 +0000
2207+++ plugins/opengl/src/window.cpp 2013-02-28 03:45:26 +0000
2208@@ -86,8 +86,7 @@
2209 bindFailed (false),
2210 vertexBuffer (new GLVertexBuffer ()),
2211 autoProgram(new GLWindowAutoProgram(this)),
2212- icons (),
2213- configureLock (w->obtainLockOnConfigureRequests ())
2214+ icons ()
2215 {
2216 paint.xScale = 1.0f;
2217 paint.yScale = 1.0f;
2218
2219=== modified file 'plugins/resize/src/resize.cpp'
2220--- plugins/resize/src/resize.cpp 2012-10-19 09:23:11 +0000
2221+++ plugins/resize/src/resize.cpp 2013-02-28 03:45:26 +0000
2222@@ -257,7 +257,7 @@
2223 float xScale, yScale;
2224 int x, y;
2225
2226- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2227+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2228 return false;
2229
2230 status = gWindow->glPaint (attrib, transform, region,
2231
2232=== modified file 'plugins/ring/src/ring.cpp'
2233--- plugins/ring/src/ring.cpp 2013-01-19 11:47:22 +0000
2234+++ plugins/ring/src/ring.cpp 2013-02-28 03:45:26 +0000
2235@@ -264,7 +264,7 @@
2236 GLWindowPaintAttrib wAttrib (gWindow->lastPaintAttrib ());
2237 GLMatrix wTransform = transform;
2238
2239- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2240+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2241 return false;
2242
2243 if (mSlot)
2244
2245=== modified file 'plugins/scale/src/scale.cpp'
2246--- plugins/scale/src/scale.cpp 2013-01-29 23:16:32 +0000
2247+++ plugins/scale/src/scale.cpp 2013-02-28 03:45:26 +0000
2248@@ -384,12 +384,14 @@
2249
2250 status = gWindow->glPaint (sAttrib, transform, region, mask);
2251
2252+ mask &= ~(PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
2253+
2254 if (scaled)
2255 {
2256 GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());
2257 GLMatrix wTransform (transform);
2258
2259- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2260+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2261 return false;
2262
2263 if (window->alpha () || lastAttrib.opacity != OPAQUE)
2264
2265=== modified file 'plugins/staticswitcher/src/staticswitcher.cpp'
2266--- plugins/staticswitcher/src/staticswitcher.cpp 2012-12-10 03:28:47 +0000
2267+++ plugins/staticswitcher/src/staticswitcher.cpp 2013-02-28 03:45:26 +0000
2268@@ -1246,7 +1246,7 @@
2269
2270 const CompWindow::Geometry &g = window->geometry ();
2271
2272- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
2273+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
2274 sScreen->ignoreSwitcher)
2275 return false;
2276
2277
2278=== modified file 'plugins/switcher/src/switcher.cpp'
2279--- plugins/switcher/src/switcher.cpp 2012-12-10 03:28:47 +0000
2280+++ plugins/switcher/src/switcher.cpp 2013-02-28 03:45:26 +0000
2281@@ -971,7 +971,7 @@
2282
2283 const CompWindow::Geometry &g = window->geometry ();
2284
2285- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
2286+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
2287 sScreen->ignoreSwitcher)
2288 return false;
2289
2290
2291=== modified file 'plugins/td/src/3d.cpp'
2292--- plugins/td/src/3d.cpp 2013-02-03 17:50:59 +0000
2293+++ plugins/td/src/3d.cpp 2013-02-28 03:45:26 +0000
2294@@ -163,7 +163,7 @@
2295 glGetIntegerv (GL_CULL_FACE_MODE, &cull);
2296 cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;
2297
2298- if (ww && wh && !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) &&
2299+ if (ww && wh && !(mask & PAINT_WINDOW_NO_DRAW_MASKS) &&
2300 ((cs->paintOrder () == FTB && mFtb) ||
2301 (cs->paintOrder () == BTF && !mFtb)))
2302 {
2303
2304=== modified file 'plugins/water/src/water.cpp'
2305--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
2306+++ plugins/water/src/water.cpp 2013-02-28 03:45:26 +0000
2307@@ -317,6 +317,12 @@
2308 }
2309 }
2310
2311+bool
2312+WaterScreen::glPaintCompositedOutputRequired ()
2313+{
2314+ return true;
2315+}
2316+
2317 void
2318 WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2319 GLFramebufferObject *fbo,
2320@@ -467,6 +473,7 @@
2321 cScreen->preparePaintSetEnabled (this, false);
2322 gScreen->glPaintOutputSetEnabled (this, false);
2323 gScreen->glPaintCompositedOutputSetEnabled (this, false);
2324+ gScreen->glPaintCompositedOutputRequiredSetEnabled (this, false);
2325 cScreen->donePaintSetEnabled (this, false);
2326 }
2327
2328
2329=== modified file 'plugins/water/src/water.h'
2330--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
2331+++ plugins/water/src/water.h 2013-02-28 03:45:26 +0000
2332@@ -64,6 +64,7 @@
2333
2334 void handleEvent (XEvent *);
2335
2336+ bool glPaintCompositedOutputRequired ();
2337 void glPaintCompositedOutput (const CompRegion &region,
2338 GLFramebufferObject *fbo,
2339 unsigned int mask);

Subscribers

People subscribed via source and target branches