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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1024304
Merge into: lp:compiz/0.9.9
Diff against target: 2635 lines (+1508/-222)
35 files modified
include/core/window.h (+2/-2)
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/doublebuffer/src/double-buffer.cpp (+1/-2)
plugins/opengl/src/framebufferobject.cpp (+1/-1)
plugins/opengl/src/paint.cpp (+11/-3)
plugins/opengl/src/privates.h (+30/-1)
plugins/opengl/src/screen.cpp (+290/-30)
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/event.cpp (+3/-29)
src/option/tests/CMakeLists.txt (+0/-1)
src/option/tests/option.cpp (+0/-4)
src/outputdevices.h (+0/-5)
src/privatewindow.h (+25/-22)
src/tests/CMakeLists.txt (+0/-1)
src/window.cpp (+1/-0)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp (+0/-80)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1024304
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Compiz Maintainers Pending
Esokrates testing, benchmarking Pending
Review via email: mp+148157@code.launchpad.net

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

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

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 :
review: Needs Fixing (continuous-integration)
3564. By Sam Spilsbury

Merge lp:compiz

3565. By Sam Spilsbury

Revert more changes which should not have happened

3566. By Sam Spilsbury

Merge lp:compiz

3567. By Sam Spilsbury

Fix using the postprocess frame provider in situations where that isn't
actually allowed.

3568. By Sam Spilsbury

Merge lp:compiz

Unmerged revisions

3568. By Sam Spilsbury

Merge lp:compiz

3567. By Sam Spilsbury

Fix using the postprocess frame provider in situations where that isn't
actually allowed.

3566. By Sam Spilsbury

Merge lp:compiz

3565. By Sam Spilsbury

Revert more changes which should not have happened

3564. By Sam Spilsbury

Merge lp:compiz

3563. By Sam Spilsbury

Fix broken merge

3562. By Sam Spilsbury

Merge lp:compiz

3561. By Sam Spilsbury

Fix typo

3560. By Sam Spilsbury

Unrevert changes which should not have been reverted

3559. 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 'include/core/window.h'
2--- include/core/window.h 2013-01-03 16:06:41 +0000
3+++ include/core/window.h 2013-02-13 11:42:35 +0000
4@@ -43,12 +43,12 @@
5 #include <core/region.h>
6 #include <core/windowgeometry.h>
7 #include <core/windowextents.h>
8-#include <core/servergrab.h>
9
10 #include <core/wrapsystem.h>
11
12 #include <map>
13
14+class ServerLock;
15 class CompWindow;
16 class CompIcon;
17 class PrivateWindow;
18@@ -434,7 +434,7 @@
19 void moveInputFocusToOtherWindow ();
20
21 /* wraps XConfigureWindow and updates serverGeometry */
22- void configureXWindow (unsigned int valueMask,
23+ void configureXWindow (unsigned int valueMask,
24 XWindowChanges *xwc);
25
26 void restackAndConfigureXWindow (unsigned int valueMask,
27
28=== modified file 'plugins/animation/src/animation.cpp'
29--- plugins/animation/src/animation.cpp 2013-01-11 08:28:51 +0000
30+++ plugins/animation/src/animation.cpp 2013-02-13 11:42:35 +0000
31@@ -1617,7 +1617,7 @@
32 // Is this the first glPaint call this round
33 // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK?
34 if (mPAScreen->mStartingNewPaintRound &&
35- !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
36+ !(mask & PAINT_WINDOW_NO_DRAW_MASKS))
37 {
38 mPAScreen->mStartingNewPaintRound = false;
39
40
41=== modified file 'plugins/composite/CMakeLists.txt'
42--- plugins/composite/CMakeLists.txt 2012-09-25 01:15:36 +0000
43+++ plugins/composite/CMakeLists.txt 2013-02-13 11:42:35 +0000
44@@ -2,9 +2,14 @@
45
46 include (CompizPlugin)
47
48+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
49 include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/pixmapbinding/include)
50+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking/include)
51+
52 link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/pixmapbinding)
53+link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/backbuffertracking)
54
55-compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding)
56+compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding compiz_composite_backbuffertracking)
57
58 add_subdirectory (src/pixmapbinding)
59+add_subdirectory (src/backbuffertracking)
60
61=== added file 'plugins/composite/include/composite/agedamagequery.h'
62--- plugins/composite/include/composite/agedamagequery.h 1970-01-01 00:00:00 +0000
63+++ plugins/composite/include/composite/agedamagequery.h 2013-02-13 11:42:35 +0000
64@@ -0,0 +1,53 @@
65+/*
66+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
67+ *
68+ * Copyright (c) 2012 Sam Spilsbury
69+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
70+ *
71+ * Permission is hereby granted, free of charge, to any person obtaining a
72+ * copy of this software and associated documentation files (the "Software"),
73+ * to deal in the Software without restriction, including without limitation
74+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
75+ * and/or sell copies of the Software, and to permit persons to whom the
76+ * Software is furnished to do so, subject to the following conditions:
77+ *
78+ * The above copyright notice and this permission notice shall be included in
79+ * all copies or substantial portions of the Software.
80+ *
81+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
83+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
85+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
86+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
87+ * DEALINGS IN THE SOFTWARE.
88+ */
89+#ifndef _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H
90+#define _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H
91+
92+#include <boost/shared_ptr.hpp>
93+#include <core/region.h>
94+
95+namespace compiz
96+{
97+namespace composite
98+{
99+namespace buffertracking
100+{
101+class AgeDamageQuery
102+{
103+ public:
104+
105+ typedef boost::shared_ptr <AgeDamageQuery> Ptr;
106+ typedef boost::function <bool (const CompRegion &)> AreaShouldBeMarkedDirty;
107+
108+ virtual ~AgeDamageQuery () {}
109+ virtual CompRegion damageForFrameAge (unsigned int) = 0;
110+ virtual const CompRegion & currentFrameDamage () = 0;
111+};
112+}
113+}
114+}
115+
116+#endif
117+
118
119=== modified file 'plugins/composite/include/composite/composite.h'
120--- plugins/composite/include/composite/composite.h 2012-10-16 05:11:10 +0000
121+++ plugins/composite/include/composite/composite.h 2013-02-13 11:42:35 +0000
122@@ -30,7 +30,7 @@
123
124 #include <X11/extensions/Xcomposite.h>
125
126-#define COMPIZ_COMPOSITE_ABI 5
127+#define COMPIZ_COMPOSITE_ABI 6
128
129 #include "core/pluginclasshandler.h"
130 #include "core/timer.h"
131@@ -38,6 +38,8 @@
132 #include "core/screen.h"
133 #include "core/wrapsystem.h"
134
135+#include "composite/agedamagequery.h"
136+
137 #define COMPOSITE_SCREEN_DAMAGE_PENDING_MASK (1 << 0)
138 #define COMPOSITE_SCREEN_DAMAGE_REGION_MASK (1 << 1)
139 #define COMPOSITE_SCREEN_DAMAGE_ALL_MASK (1 << 2)
140@@ -98,18 +100,19 @@
141 namespace composite
142 {
143 class PaintHandler {
144-public:
145- virtual ~PaintHandler () {};
146-
147- virtual void paintOutputs (CompOutput::ptrList &outputs,
148- unsigned int mask,
149- const CompRegion &region) = 0;
150-
151- virtual bool hasVSync () { return false; };
152- virtual bool requiredForcedRefreshRate () { return false; };
153-
154- virtual void prepareDrawing () {};
155- virtual bool compositingActive () { return false; };
156+ public:
157+ virtual ~PaintHandler () {};
158+
159+ virtual void paintOutputs (CompOutput::ptrList &outputs,
160+ unsigned int mask,
161+ const CompRegion &region) = 0;
162+
163+ virtual bool hasVSync () { return false; };
164+ virtual bool requiredForcedRefreshRate () { return false; };
165+
166+ virtual void prepareDrawing () {};
167+ virtual bool compositingActive () { return false; };
168+ virtual unsigned int getFrameAge () { return 1; }
169 };
170 }
171 }
172@@ -173,12 +176,19 @@
173 * Hookable function to damage regions directly
174 */
175 virtual void damageRegion (const CompRegion &r);
176+
177+ /**
178+ * Hookable function to notify plugins that the last damage
179+ * event for this frame has been received, and all further damage
180+ * events will be for the next frame
181+ */
182+ virtual void damageCutoff ();
183 };
184
185 extern template class PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>;
186
187 class CompositeScreen :
188- public WrapableHandler<CompositeScreenInterface, 7>,
189+ public WrapableHandler<CompositeScreenInterface, 8>,
190 public PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>,
191 public CompOption::Class
192 {
193@@ -203,6 +213,24 @@
194 void damageScreen ();
195
196 void damagePending ();
197+
198+ /**
199+ * Causes the damage that was recorded on N - 1 number of
200+ * frames ago to be added to the current frame, applied
201+ * culmulatively. An age of "zero" means that the entire frame
202+ * is considered undefined and must be completely repaired,
203+ * wheras an age of 1 means that this frame is the same as the
204+ * last frame, so no damage is required.
205+ */
206+ void applyDamageForFrameAge (unsigned int);
207+ unsigned int getFrameAge ();
208+ void addOverdrawDamageRegion (const CompRegion &);
209+
210+ typedef compiz::composite::buffertracking::AgeDamageQuery DamageQuery;
211+ typedef DamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty;
212+
213+ DamageQuery::Ptr
214+ getDamageQuery (const AreaShouldBeMarkedDirty &callback);
215
216
217 unsigned int damageMask ();
218@@ -248,6 +276,7 @@
219 * event loop
220 */
221 WRAPABLE_HND (6, CompositeScreenInterface, void, damageRegion, const CompRegion &);
222+ WRAPABLE_HND (7, CompositeScreenInterface, void, damageCutoff);
223
224 friend class PrivateCompositeDisplay;
225
226@@ -310,6 +339,12 @@
227 */
228 #define PAINT_WINDOW_BLEND_MASK (1 << 19)
229
230+/**
231+ * flags that would indicate the window is never actually drawn
232+ */
233+#define PAINT_WINDOW_NO_DRAW_MASKS (PAINT_WINDOW_OCCLUSION_DETECTION_MASK | \
234+ PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
235+
236 class CompositeWindowInterface;
237 extern template class WrapableInterface<CompositeWindow, CompositeWindowInterface>;
238
239
240=== added directory 'plugins/composite/src/backbuffertracking'
241=== added file 'plugins/composite/src/backbuffertracking/CMakeLists.txt'
242--- plugins/composite/src/backbuffertracking/CMakeLists.txt 1970-01-01 00:00:00 +0000
243+++ plugins/composite/src/backbuffertracking/CMakeLists.txt 2013-02-13 11:42:35 +0000
244@@ -0,0 +1,31 @@
245+INCLUDE_DIRECTORIES (
246+ ${CMAKE_CURRENT_SOURCE_DIR}/../../include
247+ ${CMAKE_CURRENT_SOURCE_DIR}/include
248+ ${CMAKE_CURRENT_SOURCE_DIR}/src
249+
250+ ${Boost_INCLUDE_DIRS}
251+)
252+
253+LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
254+
255+SET(
256+ SRCS
257+ ${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking.cpp
258+)
259+
260+ADD_LIBRARY(
261+ compiz_composite_backbuffertracking STATIC
262+
263+ ${SRCS}
264+)
265+
266+if (COMPIZ_BUILD_TESTING)
267+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
268+endif (COMPIZ_BUILD_TESTING)
269+
270+TARGET_LINK_LIBRARIES(
271+ compiz_composite_backbuffertracking
272+
273+ compiz_size
274+ compiz_core
275+)
276
277=== added directory 'plugins/composite/src/backbuffertracking/include'
278=== added file 'plugins/composite/src/backbuffertracking/include/backbuffertracking.h'
279--- plugins/composite/src/backbuffertracking/include/backbuffertracking.h 1970-01-01 00:00:00 +0000
280+++ plugins/composite/src/backbuffertracking/include/backbuffertracking.h 2013-02-13 11:42:35 +0000
281@@ -0,0 +1,125 @@
282+/*
283+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
284+ *
285+ * Copyright (c) 2012 Sam Spilsbury
286+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
287+ *
288+ * Permission is hereby granted, free of charge, to any person obtaining a
289+ * copy of this software and associated documentation files (the "Software"),
290+ * to deal in the Software without restriction, including without limitation
291+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
292+ * and/or sell copies of the Software, and to permit persons to whom the
293+ * Software is furnished to do so, subject to the following conditions:
294+ *
295+ * The above copyright notice and this permission notice shall be included in
296+ * all copies or substantial portions of the Software.
297+ *
298+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
299+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
300+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
301+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
302+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
303+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
304+ * DEALINGS IN THE SOFTWARE.
305+ */
306+#ifndef _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H
307+#define _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H
308+
309+#include <memory>
310+#include <boost/noncopyable.hpp>
311+#include <boost/shared_ptr.hpp>
312+#include <boost/weak_ptr.hpp>
313+#include <boost/function.hpp>
314+
315+#include <composite/agedamagequery.h>
316+
317+class CompSize;
318+class CompRegion;
319+
320+namespace compiz
321+{
322+namespace composite
323+{
324+namespace buffertracking
325+{
326+class DamageAgeTracking
327+{
328+ public:
329+
330+ virtual ~DamageAgeTracking () {};
331+ virtual void dirtyAreaOnCurrentFrame (const CompRegion &) = 0;
332+ virtual void overdrawRegionOnPaintingFrame (const CompRegion &) = 0;
333+ virtual void subtractObscuredArea (const CompRegion &) = 0;
334+ virtual void incrementFrameAges () = 0;
335+};
336+
337+class AgeingDamageBufferObserver
338+{
339+ public:
340+
341+ virtual ~AgeingDamageBufferObserver () {};
342+ virtual void observe (DamageAgeTracking &damageAgeTracker) = 0;
343+ virtual void unobserve (DamageAgeTracking &damageAgeTracker) = 0;
344+};
345+
346+class AgeingDamageBuffers :
347+ public AgeingDamageBufferObserver,
348+ boost::noncopyable
349+{
350+ public:
351+
352+ AgeingDamageBuffers ();
353+
354+ void observe (DamageAgeTracking &damageAgeTracker);
355+ void unobserve (DamageAgeTracking &damageAgeTracker);
356+ void incrementAges ();
357+ void markAreaDirty (const CompRegion &reg);
358+ void markAreaDirtyOnLastFrame (const CompRegion &reg);
359+ void subtractObscuredArea (const CompRegion &reg);
360+
361+ private:
362+
363+ class Private;
364+ std::auto_ptr <Private> priv;
365+};
366+
367+class FrameRoster :
368+ public DamageAgeTracking,
369+ public AgeDamageQuery,
370+ boost::noncopyable
371+{
372+ public:
373+
374+ typedef AgeDamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty;
375+ typedef boost::shared_ptr <FrameRoster> Ptr;
376+
377+ FrameRoster (const CompSize &size,
378+ AgeingDamageBufferObserver &tracker,
379+ const AreaShouldBeMarkedDirty &shouldMarkDirty);
380+
381+ ~FrameRoster ();
382+
383+ void dirtyAreaOnCurrentFrame (const CompRegion &);
384+ void overdrawRegionOnPaintingFrame (const CompRegion &);
385+ void subtractObscuredArea (const CompRegion &);
386+ void incrementFrameAges ();
387+ CompRegion damageForFrameAge (unsigned int);
388+ const CompRegion & currentFrameDamage ();
389+
390+ class Private;
391+ std::auto_ptr <Private> priv;
392+
393+ static const unsigned int NUM_TRACKED_FRAMES = 10;
394+
395+ static
396+ FrameRoster::Ptr create (const CompSize &size,
397+
398+ const AreaShouldBeMarkedDirty &shouldMarkDirty);
399+
400+ private:
401+
402+};
403+} // namespace buffertracking
404+} // namespace composite
405+} // namespace compiz
406+#endif
407
408=== added directory 'plugins/composite/src/backbuffertracking/src'
409=== added file 'plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp'
410--- plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 1970-01-01 00:00:00 +0000
411+++ plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 2013-02-13 11:42:35 +0000
412@@ -0,0 +1,214 @@
413+/*
414+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
415+ *
416+ * Copyright (c) 2012 Sam Spilsbury
417+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
418+ *
419+ * Permission is hereby granted, free of charge, to any person obtaining a
420+ * copy of this software and associated documentation files (the "Software"),
421+ * to deal in the Software without restriction, including without limitation
422+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
423+ * and/or sell copies of the Software, and to permit persons to whom the
424+ * Software is furnished to do so, subject to the following conditions:
425+ *
426+ * The above copyright notice and this permission notice shall be included in
427+ * all copies or substantial portions of the Software.
428+ *
429+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
430+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
431+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
432+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
433+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
434+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
435+ * DEALINGS IN THE SOFTWARE.
436+ */
437+#include <deque>
438+#include <core/size.h>
439+#include <core/region.h>
440+#include "backbuffertracking.h"
441+#include <cstdio>
442+
443+namespace bt = compiz::composite::buffertracking;
444+
445+class bt::FrameRoster::Private
446+{
447+ public:
448+
449+ Private (const CompSize &size,
450+ bt::AgeingDamageBufferObserver &observer,
451+ const bt::FrameRoster::AreaShouldBeMarkedDirty &shouldBeMarkedDirty) :
452+ screenSize (size),
453+ observer (observer),
454+ shouldBeMarkedDirty (shouldBeMarkedDirty),
455+ oldFrames (1)
456+ {
457+ }
458+
459+ CompSize screenSize;
460+ bt::AgeingDamageBufferObserver &observer;
461+ bt::FrameRoster::AreaShouldBeMarkedDirty shouldBeMarkedDirty;
462+ std::deque <CompRegion> oldFrames;
463+};
464+
465+bt::FrameRoster::FrameRoster (const CompSize &size,
466+ bt::AgeingDamageBufferObserver &tracker,
467+ const AreaShouldBeMarkedDirty &shouldBeMarkedDirty) :
468+ priv (new bt::FrameRoster::Private (size,
469+ tracker,
470+ shouldBeMarkedDirty))
471+{
472+ priv->observer.observe (*this);
473+}
474+
475+bt::FrameRoster::~FrameRoster ()
476+{
477+ priv->observer.unobserve (*this);
478+}
479+
480+CompRegion
481+bt::FrameRoster::damageForFrameAge (unsigned int age)
482+{
483+ if (!age)
484+ return CompRegion (0, 0,
485+ priv->screenSize.width (),
486+ priv->screenSize.height ());
487+
488+ if (age >= priv->oldFrames.size ())
489+ return CompRegion (0, 0,
490+ priv->screenSize.width (),
491+ priv->screenSize.height ());
492+
493+ CompRegion accumulatedDamage;
494+
495+ while (age--)
496+ {
497+ unsigned int frameNum = (priv->oldFrames.size () - age) - 1;
498+ accumulatedDamage += priv->oldFrames[frameNum];
499+ }
500+
501+ return accumulatedDamage;
502+}
503+
504+void
505+bt::FrameRoster::dirtyAreaOnCurrentFrame (const CompRegion &r)
506+{
507+ if (priv->shouldBeMarkedDirty (r))
508+ (*priv->oldFrames.rbegin ()) += r;
509+}
510+
511+void
512+bt::FrameRoster::subtractObscuredArea (const CompRegion &r)
513+{
514+ (*priv->oldFrames.rbegin ()) -= r;
515+}
516+
517+void
518+bt::FrameRoster::overdrawRegionOnPaintingFrame (const CompRegion &r)
519+{
520+ assert (priv->oldFrames.size () > 1);
521+ std::deque <CompRegion>::reverse_iterator it = priv->oldFrames.rbegin ();
522+ ++it;
523+ (*it) += r;
524+}
525+
526+void
527+bt::FrameRoster::incrementFrameAges ()
528+{
529+ priv->oldFrames.push_back (CompRegion ());
530+
531+ /* Get rid of old frames */
532+ if (priv->oldFrames.size () > NUM_TRACKED_FRAMES)
533+ priv->oldFrames.pop_front ();
534+}
535+
536+const CompRegion &
537+bt::FrameRoster::currentFrameDamage ()
538+{
539+ return *priv->oldFrames.rbegin ();
540+}
541+
542+class bt::AgeingDamageBuffers::Private
543+{
544+ public:
545+
546+ std::vector <bt::DamageAgeTracking *> damageAgeTrackers;
547+};
548+
549+bt::AgeingDamageBuffers::AgeingDamageBuffers () :
550+ priv (new bt::AgeingDamageBuffers::Private ())
551+{
552+}
553+
554+void
555+bt::AgeingDamageBuffers::observe (bt::DamageAgeTracking &damageAgeTracker)
556+{
557+ priv->damageAgeTrackers.push_back (&damageAgeTracker);
558+}
559+
560+void
561+bt::AgeingDamageBuffers::unobserve (bt::DamageAgeTracking &damageAgeTracker)
562+{
563+ std::vector <bt::DamageAgeTracking *>::iterator it =
564+ std::find (priv->damageAgeTrackers.begin (),
565+ priv->damageAgeTrackers.end (),
566+ &damageAgeTracker);
567+
568+ if (it != priv->damageAgeTrackers.end ())
569+ priv->damageAgeTrackers.erase (it);
570+}
571+
572+void
573+bt::AgeingDamageBuffers::incrementAges ()
574+{
575+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
576+ priv->damageAgeTrackers.begin ();
577+ it != priv->damageAgeTrackers.end ();
578+ ++it)
579+ {
580+ bt::DamageAgeTracking *tracker = *it;
581+
582+ tracker->incrementFrameAges ();
583+ }
584+}
585+
586+void
587+bt::AgeingDamageBuffers::markAreaDirty (const CompRegion &reg)
588+{
589+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
590+ priv->damageAgeTrackers.begin ();
591+ it != priv->damageAgeTrackers.end ();
592+ ++it)
593+ {
594+ bt::DamageAgeTracking *tracker = *it;
595+
596+ tracker->dirtyAreaOnCurrentFrame (reg);
597+ }
598+}
599+
600+void
601+bt::AgeingDamageBuffers::subtractObscuredArea (const CompRegion &reg)
602+{
603+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
604+ priv->damageAgeTrackers.begin ();
605+ it != priv->damageAgeTrackers.end ();
606+ ++it)
607+ {
608+ bt::DamageAgeTracking *tracker = *it;
609+
610+ tracker->subtractObscuredArea (reg);
611+ }
612+}
613+
614+void
615+bt::AgeingDamageBuffers::markAreaDirtyOnLastFrame (const CompRegion &reg)
616+{
617+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
618+ priv->damageAgeTrackers.begin ();
619+ it != priv->damageAgeTrackers.end ();
620+ ++it)
621+ {
622+ bt::DamageAgeTracking *tracker = *it;
623+
624+ tracker->overdrawRegionOnPaintingFrame (reg);
625+ }
626+}
627
628=== added directory 'plugins/composite/src/backbuffertracking/tests'
629=== added file 'plugins/composite/src/backbuffertracking/tests/CMakeLists.txt'
630--- plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
631+++ plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 2013-02-13 11:42:35 +0000
632@@ -0,0 +1,24 @@
633+find_library (GMOCK_LIBRARY gmock)
634+find_library (GMOCK_MAIN_LIBRARY gmock_main)
635+
636+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
637+ message ("Google Mock and Google Test not found - cannot build tests!")
638+ set (COMPIZ_BUILD_TESTING OFF)
639+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
640+
641+include_directories (${GTEST_INCLUDE_DIRS})
642+
643+link_directories (${COMPIZ_LIBRARY_DIRS})
644+
645+add_executable (compiz_test_composite_backbuffertracking
646+ ${CMAKE_CURRENT_SOURCE_DIR}/test-composite-backbuffertracking.cpp)
647+
648+target_link_libraries (compiz_test_composite_backbuffertracking
649+ compiz_composite_backbuffertracking
650+ ${GTEST_BOTH_LIBRARIES}
651+ ${GMOCK_LIBRARY}
652+ ${GMOCK_MAIN_LIBRARY}
653+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
654+ )
655+
656+compiz_discover_tests (compiz_test_composite_backbuffertracking COVERAGE compiz_composite_backbuffertracking)
657
658=== added file 'plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp'
659--- plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 1970-01-01 00:00:00 +0000
660+++ plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 2013-02-13 11:42:35 +0000
661@@ -0,0 +1,450 @@
662+/*
663+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
664+ *
665+ * Copyright (c) 2012 Sam Spilsbury
666+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
667+ *
668+ * Permission is hereby granted, free of charge, to any person obtaining a
669+ * copy of this software and associated documentation files (the "Software"),
670+ * to deal in the Software without restriction, including without limitation
671+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
672+ * and/or sell copies of the Software, and to permit persons to whom the
673+ * Software is furnished to do so, subject to the following conditions:
674+ *
675+ * The above copyright notice and this permission notice shall be included in
676+ * all copies or substantial portions of the Software.
677+ *
678+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
679+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
680+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
681+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
682+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
683+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
684+ * DEALINGS IN THE SOFTWARE.
685+ */
686+#include <boost/bind.hpp>
687+
688+#include <gtest/gtest.h>
689+#include <gmock/gmock.h>
690+
691+#include <core/region.h>
692+#include <core/size.h>
693+
694+#include "backbuffertracking.h"
695+
696+using ::testing::NiceMock;
697+using ::testing::_;
698+using ::testing::AtLeast;
699+
700+namespace bt = compiz::composite::buffertracking;
701+
702+namespace
703+{
704+class MockAgeingDamageBufferObserver :
705+ public bt::AgeingDamageBufferObserver
706+{
707+ public:
708+
709+ MOCK_METHOD1 (observe, void (bt::DamageAgeTracking &));
710+ MOCK_METHOD1 (unobserve, void (bt::DamageAgeTracking &));
711+};
712+
713+bool alwaysTrackDamage (const CompRegion &)
714+{
715+ return true;
716+}
717+
718+
719+class BackbufferTracking :
720+ public ::testing::Test
721+{
722+ public:
723+
724+ BackbufferTracking () :
725+ screen (1000, 1000),
726+ roster ()
727+ {
728+ }
729+
730+ virtual void SetUp ()
731+ {
732+ SetupRoster ();
733+ }
734+
735+ virtual void SetupRoster ()
736+ {
737+ roster.reset (new bt::FrameRoster (screen,
738+ niceTracker,
739+ boost::bind (alwaysTrackDamage,
740+ _1)));
741+ }
742+
743+ protected:
744+
745+ CompSize screen;
746+ NiceMock <MockAgeingDamageBufferObserver> niceTracker;
747+ bt::FrameRoster::Ptr roster;
748+};
749+
750+class BackbufferTrackingCallbacks :
751+ public BackbufferTracking
752+{
753+ public:
754+
755+ BackbufferTrackingCallbacks () :
756+ shouldDamage (false)
757+ {
758+ }
759+
760+ protected:
761+
762+ void allowDamage (bool allow)
763+ {
764+ shouldDamage = allow;
765+ }
766+
767+ private:
768+
769+ virtual void SetupRoster ()
770+ {
771+ roster.reset (new bt::FrameRoster (screen,
772+ niceTracker,
773+ boost::bind (&BackbufferTrackingCallbacks::shouldDamageCallback,
774+ this, _1)));
775+ }
776+
777+ bool shouldDamageCallback (const CompRegion &)
778+ {
779+ return shouldDamage;
780+ }
781+
782+ bool shouldDamage;
783+};
784+}
785+
786+std::ostream &
787+operator<< (std::ostream &os, const CompRegion &reg)
788+{
789+ os << "Region with Bounding Rectangle : " <<
790+ reg.boundingRect ().x () << " " <<
791+ reg.boundingRect ().y () << " " <<
792+ reg.boundingRect ().width () << " " <<
793+ reg.boundingRect ().height () << std::endl;
794+ CompRect::vector rects (reg.rects ());
795+ for (CompRect::vector::iterator it = rects.begin ();
796+ it != rects.end ();
797+ it++)
798+ os << " - subrectangle: " <<
799+ (*it).x () << " " <<
800+ (*it).y () << " " <<
801+ (*it).width () << " " <<
802+ (*it).height () << " " << std::endl;
803+
804+ return os;
805+}
806+
807+TEST (BackbufferTrackingConstruction, CreateAddsToObserverList)
808+{
809+ MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver;
810+
811+ /* We can't verify the argument here,
812+ * but we can verify the function call */
813+ EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_));
814+ EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_)).Times (AtLeast (0));
815+ bt::FrameRoster roster (CompSize (),
816+ mockAgeingDamageBufferObserver,
817+ boost::bind (alwaysTrackDamage, _1));
818+}
819+
820+TEST (BackbufferTrackingConstruction, DestroyRemovesFromObserverList)
821+{
822+ MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver;
823+
824+ /* We can't verify the argument here,
825+ * but we can verify the function call */
826+ EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_)).Times (AtLeast (0));
827+ EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_));
828+ bt::FrameRoster roster (CompSize (),
829+ mockAgeingDamageBufferObserver,
830+ boost::bind (alwaysTrackDamage, _1));
831+}
832+
833+TEST_F (BackbufferTrackingCallbacks, TrackIntoCurrentIfCallbackTrue)
834+{
835+ allowDamage (true);
836+ CompRegion damage (100, 100, 100, 100);
837+ roster->dirtyAreaOnCurrentFrame (damage);
838+ EXPECT_EQ (damage, roster->currentFrameDamage ());
839+}
840+
841+TEST_F (BackbufferTrackingCallbacks, NoTrackIntoCurrentIfCallbackFalse)
842+{
843+ allowDamage (false);
844+ CompRegion damage (100, 100, 100, 100);
845+ roster->dirtyAreaOnCurrentFrame (damage);
846+ EXPECT_EQ (emptyRegion, roster->currentFrameDamage ());
847+}
848+
849+TEST_F (BackbufferTracking, DirtyAreaSubtraction)
850+{
851+ CompRegion dirty (100, 100, 100, 100);
852+ CompRegion obscured (150, 150, 50, 50);
853+ roster->dirtyAreaOnCurrentFrame (dirty);
854+ roster->subtractObscuredArea (obscured);
855+ EXPECT_EQ (dirty - obscured, roster->currentFrameDamage ());
856+}
857+
858+TEST_F (BackbufferTracking, DirtyAreaForAgeZeroAll)
859+{
860+ EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()),
861+ roster->damageForFrameAge (0));
862+}
863+
864+TEST_F (BackbufferTracking, DirtyAreaAllForOlderThanTrackedAge)
865+{
866+ EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()),
867+ roster->damageForFrameAge (1));
868+}
869+
870+TEST_F (BackbufferTracking, NoDirtyAreaForLastFrame)
871+{
872+ CompRegion all (0, 0, screen.width (), screen.height ());
873+ roster->dirtyAreaOnCurrentFrame (all);
874+ roster->incrementFrameAges ();
875+ EXPECT_EQ (emptyRegion, roster->damageForFrameAge (1));
876+}
877+
878+TEST_F (BackbufferTracking, DirtyAreaIfMoreSinceLastFrame)
879+{
880+ CompRegion all (0, 0, screen.width (), screen.height ());
881+ roster->dirtyAreaOnCurrentFrame (all);
882+ roster->incrementFrameAges ();
883+ roster->dirtyAreaOnCurrentFrame(all);
884+ EXPECT_EQ (all, roster->damageForFrameAge (1));
885+}
886+
887+TEST_F (BackbufferTracking, AddOverdrawRegionForLastFrame)
888+{
889+ CompRegion all (0, 0, screen.width (), screen.height ());
890+ roster->dirtyAreaOnCurrentFrame (all);
891+ roster->incrementFrameAges ();
892+ roster->incrementFrameAges ();
893+ roster->overdrawRegionOnPaintingFrame (all);
894+ EXPECT_EQ (all, roster->damageForFrameAge (2));
895+}
896+
897+TEST_F (BackbufferTracking, TwoFramesAgo)
898+{
899+ CompRegion all (0, 0, screen.width (), screen.height ());
900+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
901+
902+ roster->dirtyAreaOnCurrentFrame (all);
903+ roster->incrementFrameAges ();
904+ roster->dirtyAreaOnCurrentFrame (topleft);
905+ roster->incrementFrameAges ();
906+ EXPECT_EQ (topleft, roster->damageForFrameAge (2));
907+}
908+
909+TEST_F (BackbufferTracking, TwoFramesAgoCulmulative)
910+{
911+ CompRegion all (0, 0, screen.width (), screen.height ());
912+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
913+ CompRegion topright (0, screen.width () / 2,
914+ screen.width () / 2,
915+ screen.height () / 2);
916+
917+ roster->dirtyAreaOnCurrentFrame (all);
918+ roster->incrementFrameAges ();
919+ roster->dirtyAreaOnCurrentFrame (topleft);
920+ roster->dirtyAreaOnCurrentFrame (topright);
921+ roster->incrementFrameAges ();
922+ EXPECT_EQ (topleft + topright, roster->damageForFrameAge (2));
923+}
924+
925+TEST_F (BackbufferTracking, ThreeFramesAgo)
926+{
927+ CompRegion all (0, 0, screen.width (), screen.height ());
928+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
929+ CompRegion bottomright (screen.width () / 2,
930+ screen.height () / 2,
931+ screen.width () / 2,
932+ screen.height () / 2);
933+
934+ roster->dirtyAreaOnCurrentFrame (all);
935+ roster->incrementFrameAges ();
936+ roster->dirtyAreaOnCurrentFrame (topleft);
937+ roster->incrementFrameAges ();
938+ roster->dirtyAreaOnCurrentFrame (bottomright);
939+ roster->incrementFrameAges ();
940+
941+ EXPECT_EQ (topleft + bottomright, roster->damageForFrameAge (3));
942+}
943+
944+/* These are more or less functional tests from this point forward
945+ * just checking a number of different situations */
946+
947+TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFrames)
948+{
949+ CompRegion all (0, 0, screen.width (), screen.height ());
950+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
951+ CompRegion bottomright (screen.width () / 2,
952+ screen.height () / 2,
953+ screen.width () / 2,
954+ screen.height () / 2);
955+ CompRegion topright (screen.width () / 2,
956+ 0,
957+ screen.width () / 2,
958+ screen.height () / 2);
959+
960+ roster->dirtyAreaOnCurrentFrame (all);
961+ roster->incrementFrameAges ();
962+ roster->dirtyAreaOnCurrentFrame (topleft);
963+ roster->incrementFrameAges ();
964+ roster->dirtyAreaOnCurrentFrame (bottomright);
965+ roster->incrementFrameAges ();
966+ roster->dirtyAreaOnCurrentFrame (topright);
967+ roster->incrementFrameAges ();
968+
969+ EXPECT_EQ (topright + bottomright, roster->damageForFrameAge (3));
970+}
971+
972+TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFramesAndOverlap)
973+{
974+ CompRegion all (0, 0, screen.width (), screen.height ());
975+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
976+ CompRegion bottomright (screen.width () / 2,
977+ screen.height () / 2,
978+ screen.width () / 2,
979+ screen.height () / 2);
980+ CompRegion topright (screen.width () / 2,
981+ 0,
982+ screen.width () / 2,
983+ screen.height () / 2);
984+
985+ roster->dirtyAreaOnCurrentFrame (all);
986+ roster->incrementFrameAges ();
987+ roster->dirtyAreaOnCurrentFrame (topleft);
988+ roster->incrementFrameAges ();
989+ roster->dirtyAreaOnCurrentFrame (bottomright);
990+ roster->incrementFrameAges ();
991+ roster->dirtyAreaOnCurrentFrame (bottomright);
992+ roster->incrementFrameAges ();
993+
994+ EXPECT_EQ (bottomright, roster->damageForFrameAge (3));
995+}
996+
997+TEST_F (BackbufferTracking, AllDamageForExceedingMaxTrackedFrames)
998+{
999+ CompRegion all (0, 0, screen.width (), screen.height ());
1000+ CompRegion damage (0, 0, 1, 1);
1001+
1002+ roster->dirtyAreaOnCurrentFrame (all);
1003+
1004+ for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES - 1; ++i)
1005+ {
1006+ roster->incrementFrameAges ();
1007+ roster->dirtyAreaOnCurrentFrame (damage);
1008+ }
1009+
1010+ EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES + 1));
1011+}
1012+
1013+TEST_F (BackbufferTracking, DamageForMaxTrackedFrame)
1014+{
1015+ CompRegion all (0, 0, screen.width (), screen.height ());
1016+ CompRegion damage (0, 0, 1, 1);
1017+
1018+ roster->dirtyAreaOnCurrentFrame (all);
1019+
1020+ for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES + 1; ++i)
1021+ {
1022+ roster->incrementFrameAges ();
1023+ roster->dirtyAreaOnCurrentFrame (damage);
1024+ }
1025+
1026+ EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES));
1027+}
1028+
1029+class MockDamageAgeTracking :
1030+ public bt::DamageAgeTracking
1031+{
1032+ public:
1033+
1034+ typedef boost::shared_ptr <MockDamageAgeTracking> Ptr;
1035+
1036+ MOCK_METHOD0 (incrementFrameAges, void ());
1037+ MOCK_METHOD1 (dirtyAreaOnCurrentFrame, void (const CompRegion &));
1038+ MOCK_METHOD1 (subtractObscuredArea, void (const CompRegion &));
1039+ MOCK_METHOD1 (overdrawRegionOnPaintingFrame, void (const CompRegion &));
1040+};
1041+
1042+class AgeingDamageBuffers :
1043+ public ::testing::Test
1044+{
1045+ public:
1046+
1047+ AgeingDamageBuffers ()
1048+ {
1049+ ageing.observe (mockDamageAgeTracker);
1050+ }
1051+
1052+ MockDamageAgeTracking mockDamageAgeTracker;
1053+ bt::AgeingDamageBuffers ageing;
1054+};
1055+
1056+TEST_F (AgeingDamageBuffers, IncrementAgesOnValidRosters)
1057+{
1058+ EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ());
1059+ ageing.incrementAges ();
1060+}
1061+
1062+TEST_F (AgeingDamageBuffers, DirtyAreaOnValidRosters)
1063+{
1064+ CompRegion dirtyArea (100, 100, 100, 100);
1065+ EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (dirtyArea));
1066+ ageing.markAreaDirty (dirtyArea);
1067+}
1068+
1069+TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnValidRosters)
1070+{
1071+ CompRegion obscuredArea (100, 100, 100, 100);
1072+ EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (obscuredArea));
1073+ ageing.subtractObscuredArea (obscuredArea);
1074+}
1075+
1076+TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnValidRosters)
1077+{
1078+ CompRegion overdrawArea (100, 100, 100, 100);
1079+ EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (overdrawArea));
1080+ ageing.markAreaDirtyOnLastFrame (overdrawArea);
1081+}
1082+
1083+TEST_F (AgeingDamageBuffers, IncrementAgesOnInvalidRosters)
1084+{
1085+ EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ()).Times (0);
1086+ ageing.unobserve (mockDamageAgeTracker);
1087+ ageing.incrementAges ();
1088+}
1089+
1090+TEST_F (AgeingDamageBuffers, DirtyAreaOnInvalidRosters)
1091+{
1092+ EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (_)).Times (0);
1093+ ageing.unobserve (mockDamageAgeTracker);
1094+ ageing.markAreaDirty (emptyRegion);
1095+}
1096+
1097+TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnInvalidRosters)
1098+{
1099+ EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (_)).Times (0);
1100+ ageing.unobserve (mockDamageAgeTracker);
1101+ ageing.subtractObscuredArea (emptyRegion);
1102+}
1103+
1104+TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnInvalidRosters)
1105+{
1106+ EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (_)).Times (0);
1107+ ageing.unobserve (mockDamageAgeTracker);
1108+ ageing.markAreaDirtyOnLastFrame (emptyRegion);
1109+}
1110+
1111+
1112
1113=== modified file 'plugins/composite/src/privates.h'
1114--- plugins/composite/src/privates.h 2012-09-20 09:35:40 +0000
1115+++ plugins/composite/src/privates.h 2013-02-13 11:42:35 +0000
1116@@ -36,12 +36,20 @@
1117 #include <map>
1118
1119 #include "pixmapbinding.h"
1120+#include "backbuffertracking.h"
1121 #include "composite_options.h"
1122
1123 extern CompPlugin::VTable *compositeVTable;
1124
1125 extern CompWindow *lastDamagedWindow;
1126
1127+enum DamageTracking
1128+{
1129+ DamageForCurrentFrame = 0,
1130+ DamageForLastFrame = 1,
1131+ DamageFinalPaintRegion
1132+};
1133+
1134 class PrivateCompositeScreen :
1135 ScreenInterface,
1136 public CompositeOptions
1137@@ -66,6 +74,8 @@
1138
1139 void scheduleRepaint ();
1140
1141+ const CompRegion * damageTrackedBuffer (const CompRegion &);
1142+
1143 public:
1144
1145 CompositeScreen *cScreen;
1146@@ -80,10 +90,12 @@
1147 bool randrExtension;
1148 int randrEvent, randrError;
1149
1150- CompRegion damage;
1151+ CompRegion lastFrameDamage;
1152 unsigned long damageMask;
1153
1154- CompRegion tmpRegion;
1155+ CompRegion tmpRegion;
1156+
1157+ DamageTracking currentlyTrackingDamage;
1158
1159 Window overlay;
1160 Window output;
1161@@ -99,6 +111,7 @@
1162 int redrawTime;
1163 int optimalRedrawTime;
1164 bool scheduled, painting, reschedule;
1165+ bool damageRequiresRepaintReschedule;
1166
1167 bool slowAnimations;
1168
1169@@ -115,6 +128,9 @@
1170
1171 /* Map Damage handle to its bounding box */
1172 std::map<Damage, XRectangle> damages;
1173+
1174+ compiz::composite::buffertracking::AgeingDamageBuffers ageingBuffers;
1175+ compiz::composite::buffertracking::FrameRoster roster;
1176 };
1177
1178 class PrivateCompositeWindow :
1179
1180=== modified file 'plugins/composite/src/screen.cpp'
1181--- plugins/composite/src/screen.cpp 2013-01-28 19:22:29 +0000
1182+++ plugins/composite/src/screen.cpp 2013-02-13 11:42:35 +0000
1183@@ -47,6 +47,8 @@
1184
1185 template class WrapableInterface<CompositeScreen, CompositeScreenInterface>;
1186
1187+namespace bt = compiz::composite::buffertracking;
1188+
1189 static const int FALLBACK_REFRESH_RATE = 60; /* if all else fails */
1190
1191 CompWindow *lastDamagedWindow = 0;
1192@@ -276,6 +278,14 @@
1193 delete priv;
1194 }
1195
1196+namespace
1197+{
1198+bool alwaysMarkDirty ()
1199+{
1200+ return true;
1201+}
1202+}
1203+
1204
1205 PrivateCompositeScreen::PrivateCompositeScreen (CompositeScreen *cs) :
1206 cScreen (cs),
1207@@ -294,6 +304,7 @@
1208 randrEvent (0),
1209 randrError (0),
1210 damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK),
1211+ currentlyTrackingDamage (DamageForCurrentFrame),
1212 overlay (None),
1213 output (None),
1214 exposeRects (),
1215@@ -305,12 +316,16 @@
1216 scheduled (false),
1217 painting (false),
1218 reschedule (false),
1219+ damageRequiresRepaintReschedule (true),
1220 slowAnimations (false),
1221 pHnd (NULL),
1222 FPSLimiterMode (CompositeFPSLimiterModeDefault),
1223 withDestroyedWindows (),
1224 cmSnAtom (0),
1225- newCmSnOwner (None)
1226+ newCmSnOwner (None),
1227+ roster (*screen,
1228+ ageingBuffers,
1229+ boost::bind (alwaysMarkDirty))
1230 {
1231 gettimeofday (&lastRedraw, 0);
1232 // wrap outputChangeNotify
1233@@ -491,15 +506,47 @@
1234 return false;
1235 }
1236
1237+const CompRegion *
1238+PrivateCompositeScreen::damageTrackedBuffer (const CompRegion &region)
1239+{
1240+ const CompRegion *currentDamage = NULL;
1241+
1242+ switch (currentlyTrackingDamage)
1243+ {
1244+ case DamageForCurrentFrame:
1245+ currentDamage = &(roster.currentFrameDamage ());
1246+ ageingBuffers.markAreaDirty (region);
1247+ break;
1248+ case DamageForLastFrame:
1249+ currentDamage = &(lastFrameDamage);
1250+ lastFrameDamage += region;
1251+ break;
1252+ case DamageFinalPaintRegion:
1253+ currentDamage = &(tmpRegion);
1254+ tmpRegion += region;
1255+ break;
1256+ default:
1257+ compLogMessage ("composite", CompLogLevelFatal, "unreachable section");
1258+ assert (false);
1259+ abort ();
1260+ }
1261+
1262+ assert (currentDamage);
1263+ return currentDamage;
1264+}
1265+
1266 void
1267 CompositeScreen::damageScreen ()
1268 {
1269+ /* Don't tell plugins about damage events when the damage buffer is already full */
1270 bool alreadyDamaged = priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
1271+ alreadyDamaged |= ((currentDamage () & screen->region ()) == screen->region ());
1272
1273 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
1274 priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
1275
1276- priv->scheduleRepaint ();
1277+ if (priv->damageRequiresRepaintReschedule)
1278+ priv->scheduleRepaint ();
1279
1280 /*
1281 * Call through damageRegion since plugins listening for incoming damage
1282@@ -507,7 +554,15 @@
1283 */
1284
1285 if (!alreadyDamaged)
1286+ {
1287 damageRegion (CompRegion (0, 0, screen->width (), screen->height ()));
1288+
1289+ /* Set the damage region as the fullscreen region, because if
1290+ * windows are unredirected we need to correctly subtract from
1291+ * it later
1292+ */
1293+ priv->damageTrackedBuffer (screen->region ());
1294+ }
1295 }
1296
1297 void
1298@@ -518,7 +573,12 @@
1299 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
1300 return;
1301
1302- priv->damage += region;
1303+ /* Don't cause repaints to be scheduled for empty damage
1304+ * regions */
1305+ if (region.isEmpty ())
1306+ return;
1307+
1308+ const CompRegion *currentDamage = priv->damageTrackedBuffer (region);
1309 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
1310
1311 /* if the number of damage rectangles grows two much between repaints,
1312@@ -526,16 +586,61 @@
1313 in order to make sure we're not having too much overhead, damage
1314 the whole screen if we have a lot of damage rects */
1315
1316- if (priv->damage.numRects () > 100)
1317- damageScreen ();
1318- priv->scheduleRepaint ();
1319+ if (currentDamage->numRects () > 100)
1320+ damageScreen ();
1321+
1322+ if (priv->damageRequiresRepaintReschedule)
1323+ priv->scheduleRepaint ();
1324+}
1325+
1326+void
1327+CompositeScreen::damageCutoff ()
1328+{
1329+ WRAPABLE_HND_FUNCTN (damageCutoff);
1330 }
1331
1332 void
1333 CompositeScreen::damagePending ()
1334 {
1335 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;
1336- priv->scheduleRepaint ();
1337+
1338+ if (priv->damageRequiresRepaintReschedule)
1339+ priv->scheduleRepaint ();
1340+}
1341+
1342+void
1343+CompositeScreen::applyDamageForFrameAge (unsigned int age)
1344+{
1345+ /* Track into "last frame damage" */
1346+ priv->currentlyTrackingDamage = DamageForLastFrame;
1347+ damageRegion (priv->roster.damageForFrameAge (age));
1348+ priv->currentlyTrackingDamage = DamageForCurrentFrame;
1349+}
1350+
1351+unsigned int
1352+CompositeScreen::getFrameAge ()
1353+{
1354+ if (priv->pHnd)
1355+ return priv->pHnd->getFrameAge ();
1356+
1357+ return 1;
1358+}
1359+
1360+void
1361+CompositeScreen::addOverdrawDamageRegion (const CompRegion &r)
1362+{
1363+ priv->ageingBuffers.markAreaDirtyOnLastFrame (r);
1364+}
1365+
1366+typedef CompositeScreen::AreaShouldBeMarkedDirty ShouldMarkDirty;
1367+
1368+CompositeScreen::DamageQuery::Ptr
1369+CompositeScreen::getDamageQuery (const ShouldMarkDirty &callback)
1370+{
1371+ /* No initial damage */
1372+ return bt::FrameRoster::Ptr (new bt::FrameRoster (CompSize (),
1373+ priv->ageingBuffers,
1374+ callback));
1375 }
1376
1377 unsigned int
1378@@ -780,6 +885,10 @@
1379 {
1380 int timeDiff;
1381
1382+ /* Damage that accumulates here does not require a repaint reschedule
1383+ * as it will end up on this frame */
1384+ priv->damageRequiresRepaintReschedule = false;
1385+
1386 if (priv->pHnd)
1387 priv->pHnd->prepareDrawing ();
1388
1389@@ -814,7 +923,7 @@
1390 continue;
1391
1392 if (!CompositeWindow::get (w)->redirected ())
1393- priv->damage -= w->region ();
1394+ priv->ageingBuffers.subtractObscuredArea (w->region ());
1395
1396 break;
1397 }
1398@@ -826,7 +935,13 @@
1399 }
1400 }
1401
1402- priv->tmpRegion = priv->damage & screen->region ();
1403+ /* All further damage is for the next frame now, as
1404+ * priv->tmpRegion will be assigned. Notify plugins that do
1405+ * damage tracking of this */
1406+ damageCutoff ();
1407+
1408+ priv->tmpRegion = (priv->roster.currentFrameDamage () + priv->lastFrameDamage) & screen->region ();
1409+ priv->currentlyTrackingDamage = DamageFinalPaintRegion;
1410
1411 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
1412 {
1413@@ -848,7 +963,9 @@
1414 XSync (dpy, False);
1415 priv->damages.clear ();
1416
1417- priv->damage = CompRegion ();
1418+ /* Any more damage requires a repaint reschedule */
1419+ priv->damageRequiresRepaintReschedule = true;
1420+ priv->lastFrameDamage = CompRegion ();
1421
1422 int mask = priv->damageMask;
1423 priv->damageMask = 0;
1424@@ -864,9 +981,13 @@
1425 else
1426 outputs.push_back (&screen->fullscreenOutput ());
1427
1428+ priv->currentlyTrackingDamage = DamageForCurrentFrame;
1429+
1430+ /* All new damage goes on the next frame */
1431+ priv->ageingBuffers.incrementAges ();
1432+
1433 paint (outputs, mask);
1434
1435-
1436 donePaint ();
1437
1438 priv->outputShapeChanged = false;
1439@@ -1023,8 +1144,12 @@
1440 CompositeScreenInterface::damageRegion (const CompRegion &r)
1441 WRAPABLE_DEF (damageRegion, r);
1442
1443+void
1444+CompositeScreenInterface::damageCutoff ()
1445+ WRAPABLE_DEF (damageCutoff);
1446+
1447 const CompRegion &
1448 CompositeScreen::currentDamage () const
1449 {
1450- return priv->damage;
1451+ return priv->roster.currentFrameDamage ();
1452 }
1453
1454=== modified file 'plugins/kdecompat/src/kdecompat.cpp'
1455--- plugins/kdecompat/src/kdecompat.cpp 2012-08-14 06:33:22 +0000
1456+++ plugins/kdecompat/src/kdecompat.cpp 2013-02-13 11:42:35 +0000
1457@@ -196,7 +196,7 @@
1458 if ((!(ks->optionGetPlasmaThumbnails () || mPreviews.empty ()) &&
1459 !(mSlideData || mSlideData->remaining)) ||
1460 !window->mapNum () ||
1461- (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
1462+ (mask & PAINT_WINDOW_NO_DRAW_MASKS))
1463 {
1464 status = gWindow->glPaint (attrib, transform, region, mask);
1465 return status;
1466@@ -210,7 +210,7 @@
1467 CompRect clipBox (window->x (), window->y (),
1468 window->width (), window->height ());
1469
1470- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
1471+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
1472 return false;
1473
1474 remainder = (float) data->remaining / data->duration;
1475
1476=== modified file 'plugins/opengl/include/opengl/opengl.h'
1477--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
1478+++ plugins/opengl/include/opengl/opengl.h 2013-02-13 11:42:35 +0000
1479@@ -37,6 +37,13 @@
1480 #else
1481 #include <GL/gl.h>
1482 #include <GL/glx.h>
1483+
1484+/* Some implementations have not yet given a definition
1485+ * to GLX_BACK_BUFFER_AGE_EXT but this is the token as defined
1486+ * in the spec (https://www.opengl.org/registry/specs/EXT/glx_buffer_age.txt)
1487+ */
1488+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
1489+
1490 #endif
1491
1492 #include <core/size.h>
1493@@ -50,7 +57,7 @@
1494 #include <opengl/programcache.h>
1495 #include <opengl/shadercache.h>
1496
1497-#define COMPIZ_OPENGL_ABI 6
1498+#define COMPIZ_OPENGL_ABI 8
1499
1500 /*
1501 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
1502@@ -525,6 +532,7 @@
1503 extern bool shaders;
1504 extern bool stencilBuffer;
1505 extern GLint maxTextureUnits;
1506+ extern bool bufferAge;
1507
1508 extern bool canDoSaturated;
1509 extern bool canDoSlightlySaturated;
1510@@ -663,6 +671,11 @@
1511 unsigned int mask);
1512
1513 /**
1514+ * Return true if glPaintCompositedOutput is required for this frame
1515+ */
1516+ virtual bool glPaintCompositedOutputRequired ();
1517+
1518+ /**
1519 * Hookable function used by plugins to determine stenciling mask
1520 */
1521 virtual void glBufferStencil (const GLMatrix &matrix,
1522@@ -674,7 +687,7 @@
1523 extern template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>;
1524
1525 class GLScreen :
1526- public WrapableHandler<GLScreenInterface, 8>,
1527+ public WrapableHandler<GLScreenInterface, 9>,
1528 public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>,
1529 public CompOption::Class
1530 {
1531@@ -788,7 +801,9 @@
1532 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
1533 const CompRegion &, GLFramebufferObject *, unsigned int);
1534
1535- WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
1536+ WRAPABLE_HND (7, GLScreenInterface, bool, glPaintCompositedOutputRequired);
1537+
1538+ WRAPABLE_HND (8, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
1539 GLVertexBuffer &,
1540 CompOutput *);
1541
1542
1543=== modified file 'plugins/opengl/src/doublebuffer/src/double-buffer.cpp'
1544--- plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-11-09 06:13:00 +0000
1545+++ plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2013-02-13 11:42:35 +0000
1546@@ -26,6 +26,7 @@
1547
1548 #include <cstdlib>
1549 #include <cassert>
1550+#include <cstdio>
1551 #include "opengl/doublebuffer.h"
1552
1553 using namespace compiz::opengl;
1554@@ -77,9 +78,7 @@
1555
1556 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&
1557 !setting[HAVE_PERSISTENT_BACK_BUFFER])
1558- {
1559 copyFrontToBack ();
1560- }
1561 }
1562 else
1563 {
1564
1565=== modified file 'plugins/opengl/src/framebufferobject.cpp'
1566--- plugins/opengl/src/framebufferobject.cpp 2012-08-06 09:44:49 +0000
1567+++ plugins/opengl/src/framebufferobject.cpp 2013-02-13 11:42:35 +0000
1568@@ -131,7 +131,7 @@
1569
1570 (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,
1571 priv->glTex->target (),
1572- priv->glTex->name (), 0);
1573+ priv->glTex->name (), 0);
1574
1575 priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);
1576
1577
1578=== modified file 'plugins/opengl/src/paint.cpp'
1579--- plugins/opengl/src/paint.cpp 2013-01-01 10:04:50 +0000
1580+++ plugins/opengl/src/paint.cpp 2013-02-13 11:42:35 +0000
1581@@ -626,8 +626,8 @@
1582 if (mask & PAINT_SCREEN_FULL_MASK)
1583 {
1584 glPaintTransformedOutput (sAttrib, sTransform,
1585- CompRegion (*output), output, mask);
1586-
1587+ CompRegionRef (output->region ()), output, mask);
1588+ priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
1589 return true;
1590 }
1591
1592@@ -657,8 +657,9 @@
1593 }
1594 else if (mask & PAINT_SCREEN_FULL_MASK)
1595 {
1596- glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output),
1597+ glPaintTransformedOutput (sAttrib, sTransform, CompRegionRef (output->region ()),
1598 output, mask);
1599+ priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
1600
1601 return true;
1602 }
1603@@ -668,6 +669,13 @@
1604 }
1605 }
1606
1607+bool
1608+GLScreen::glPaintCompositedOutputRequired ()
1609+{
1610+ WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintCompositedOutputRequired);
1611+ return false;
1612+}
1613+
1614 void
1615 GLScreen::glPaintCompositedOutput (const CompRegion &region,
1616 GLFramebufferObject *fbo,
1617
1618=== modified file 'plugins/opengl/src/privates.h'
1619--- plugins/opengl/src/privates.h 2013-01-01 09:41:41 +0000
1620+++ plugins/opengl/src/privates.h 2013-02-13 11:42:35 +0000
1621@@ -29,6 +29,9 @@
1622 #define _OPENGL_PRIVATES_H
1623
1624 #include <memory>
1625+#include <vector>
1626+#include <tr1/tuple>
1627+#include <boost/shared_ptr.hpp>
1628
1629 #include <composite/composite.h>
1630 #include <opengl/opengl.h>
1631@@ -119,8 +122,26 @@
1632 GLTexture::List textures;
1633 };
1634
1635+class FrameProvider
1636+{
1637+ public:
1638+
1639+ typedef boost::shared_ptr <FrameProvider> Ptr;
1640+ typedef std::tr1::tuple <GLFramebufferObject *, int> Frame;
1641+
1642+ virtual ~FrameProvider () {}
1643+
1644+ virtual GLuint getCurrentFrame () = 0;
1645+ virtual void endFrame () = 0;
1646+
1647+ virtual bool providesPersistence () = 0;
1648+ virtual bool alwaysPostprocess () = 0;
1649+ virtual void invalidateAll () = 0;
1650+};
1651+
1652 class PrivateGLScreen :
1653 public ScreenInterface,
1654+ public CompositeScreenInterface,
1655 public compiz::composite::PaintHandler,
1656 public OpenglOptions
1657 {
1658@@ -141,12 +162,16 @@
1659 bool hasVSync ();
1660 bool requiredForcedRefreshRate ();
1661
1662+ unsigned int getFrameAge ();
1663+
1664 void updateRenderMode ();
1665
1666 void prepareDrawing ();
1667
1668 bool compositingActive ();
1669
1670+ void damageCutoff ();
1671+
1672 void paintBackground (const GLMatrix &transform,
1673 const CompRegion &region,
1674 bool transformed);
1675@@ -162,6 +187,8 @@
1676
1677 bool driverIsBlacklisted (const char *regex) const;
1678
1679+ bool postprocessRequiredForCurrentFrame ();
1680+
1681 public:
1682
1683 GLScreen *gScreen;
1684@@ -196,7 +223,7 @@
1685 GLXDoubleBuffer doubleBuffer;
1686 #endif
1687
1688- GLFramebufferObject *scratchFbo;
1689+ boost::shared_ptr <GLFramebufferObject> scratchFbo;
1690 CompRegion outputRegion;
1691
1692 XRectangle lastViewport;
1693@@ -221,8 +248,10 @@
1694 Pixmap rootPixmapCopy;
1695 CompSize rootPixmapSize;
1696
1697+ FrameProvider::Ptr frameProvider;
1698 const char *glVendor, *glRenderer, *glVersion;
1699
1700+ bool postprocessingRequired;
1701 mutable CompString prevRegex;
1702 mutable bool prevBlacklisted;
1703 };
1704
1705=== modified file 'plugins/opengl/src/screen.cpp'
1706--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
1707+++ plugins/opengl/src/screen.cpp 2013-02-13 11:42:35 +0000
1708@@ -186,6 +186,7 @@
1709 bool vboEnabled = false;
1710 bool shaders = false;
1711 GLint maxTextureUnits = 1;
1712+ bool bufferAge = false;
1713
1714 bool canDoSaturated = false;
1715 bool canDoSlightlySaturated = false;
1716@@ -301,6 +302,52 @@
1717
1718 #ifndef USE_GLES
1719
1720+class BufferAgeFrameProvider :
1721+ public FrameProvider
1722+{
1723+ public:
1724+
1725+ BufferAgeFrameProvider (Display *disp,
1726+ GLXDrawable drawable) :
1727+ mDisplay (disp),
1728+ mDrawable (drawable)
1729+ {
1730+ }
1731+
1732+ unsigned int getCurrentFrame ()
1733+ {
1734+ unsigned int age = 0;
1735+ (*GL::queryDrawable) (mDisplay,
1736+ mDrawable,
1737+ GLX_BACK_BUFFER_AGE_EXT,
1738+ &age);
1739+ return age;
1740+ }
1741+
1742+ void endFrame ()
1743+ {
1744+ }
1745+
1746+ void invalidateAll ()
1747+ {
1748+ }
1749+
1750+ bool providesPersistence ()
1751+ {
1752+ return true;
1753+ }
1754+
1755+ bool alwaysPostprocess ()
1756+ {
1757+ return false;
1758+ }
1759+
1760+ private:
1761+
1762+ Display *mDisplay;
1763+ GLXDrawable mDrawable;
1764+};
1765+
1766 namespace compiz
1767 {
1768 namespace opengl
1769@@ -358,6 +405,137 @@
1770
1771 #endif
1772
1773+class UndefinedFrameProvider :
1774+ public FrameProvider
1775+{
1776+ public:
1777+
1778+ unsigned int getCurrentFrame ()
1779+ {
1780+ return 0;
1781+ }
1782+
1783+ void endFrame ()
1784+ {
1785+ }
1786+
1787+ void invalidateAll ()
1788+ {
1789+ }
1790+
1791+ bool providesPersistence ()
1792+ {
1793+ return false;
1794+ }
1795+
1796+ bool alwaysPostprocess ()
1797+ {
1798+ return false;
1799+ }
1800+};
1801+
1802+class PostprocessFrameProvider :
1803+ public FrameProvider
1804+{
1805+ public:
1806+
1807+ PostprocessFrameProvider (GLFramebufferObject *object) :
1808+ mObject (object),
1809+ mAge (0)
1810+ {
1811+ }
1812+
1813+ unsigned int getCurrentFrame ()
1814+ {
1815+ /* We are now using this buffer, reset
1816+ * age back to zero */
1817+ unsigned int lastAge = mAge;
1818+ mAge = 0;
1819+
1820+ return lastAge;
1821+ }
1822+
1823+ void endFrame ()
1824+ {
1825+ ++mAge;
1826+ }
1827+
1828+ void invalidateAll ()
1829+ {
1830+ mAge = 0;
1831+ }
1832+
1833+ bool providesPersistence ()
1834+ {
1835+ return true;
1836+ }
1837+
1838+ bool alwaysPostprocess ()
1839+ {
1840+ return true;
1841+ }
1842+
1843+ private:
1844+
1845+ GLFramebufferObject *mObject;
1846+ unsigned int mAge;
1847+};
1848+
1849+class OptionalPostprocessFrameProvider :
1850+ public FrameProvider
1851+{
1852+ public:
1853+
1854+ typedef boost::function <bool ()> PostprocessRequired;
1855+
1856+ OptionalPostprocessFrameProvider (const FrameProvider::Ptr &backbuffer,
1857+ const FrameProvider::Ptr &scratchbuffer,
1858+ const PostprocessRequired &ppRequired) :
1859+ mBackbuffer (backbuffer),
1860+ mScratchbuffer (scratchbuffer),
1861+ mPPRequired (ppRequired)
1862+ {
1863+ }
1864+
1865+ unsigned int getCurrentFrame ()
1866+ {
1867+ if (mPPRequired ())
1868+ return mScratchbuffer->getCurrentFrame ();
1869+ else
1870+ return mBackbuffer->getCurrentFrame ();
1871+ }
1872+
1873+ void endFrame ()
1874+ {
1875+ mScratchbuffer->endFrame ();
1876+ }
1877+
1878+ void invalidateAll ()
1879+ {
1880+ mScratchbuffer->invalidateAll ();
1881+ }
1882+
1883+ bool providesPersistence ()
1884+ {
1885+ /* We are only as good as the backbuffer is */
1886+ return mBackbuffer->providesPersistence ();
1887+ }
1888+
1889+ bool alwaysPostprocess ()
1890+ {
1891+ if (mPPRequired ())
1892+ return mScratchbuffer->alwaysPostprocess ();
1893+ else
1894+ return mBackbuffer->alwaysPostprocess ();
1895+ }
1896+
1897+ private:
1898+
1899+ FrameProvider::Ptr mBackbuffer;
1900+ FrameProvider::Ptr mScratchbuffer;
1901+ PostprocessRequired mPPRequired;
1902+};
1903+
1904 bool
1905 GLScreen::glInitContext (XVisualInfo *visinfo)
1906 {
1907@@ -593,6 +771,8 @@
1908
1909 priv->incorrectRefreshRate = false;
1910
1911+ priv->frameProvider.reset (new PostprocessFrameProvider ());
1912+
1913 #else
1914
1915 Display *dpy = screen->dpy ();
1916@@ -899,12 +1079,48 @@
1917
1918 if (GL::fboSupported)
1919 {
1920- priv->scratchFbo = new GLFramebufferObject;
1921+ priv->scratchFbo.reset (new GLFramebufferObject ());
1922 priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
1923 }
1924
1925 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
1926
1927+ /* We need scratchFbo to be set before doing this, and it is common
1928+ * to both the GLES and non-GLES codepaths, so using another #ifdef
1929+ */
1930+#ifndef USE_GLES
1931+ const Window outputWindow = CompositeScreen::get (screen)->output ();
1932+
1933+ if (GL::fboEnabled)
1934+ {
1935+ if (GL::bufferAge)
1936+ {
1937+ FrameProvider::Ptr back (new BufferAgeFrameProvider (screen->dpy (),
1938+ outputWindow));
1939+ FrameProvider::Ptr scratch (new PostprocessFrameProvider (priv->scratchFbo.get ()));
1940+ OptionalPostprocessFrameProvider::PostprocessRequired ppReq
1941+ (boost::bind (&PrivateGLScreen::postprocessRequiredForCurrentFrame,
1942+ priv));
1943+ priv->frameProvider.reset (new OptionalPostprocessFrameProvider (back,
1944+ scratch,
1945+ ppReq));
1946+ }
1947+ else
1948+ {
1949+ /* Prefer using FBO's instead of switching between a defined/undefined backbuffer */
1950+ priv->frameProvider.reset (new PostprocessFrameProvider (priv->scratchFbo.get ()));
1951+ }
1952+ }
1953+ else
1954+ {
1955+ if (GL::bufferAge)
1956+ priv->frameProvider.reset (new BufferAgeFrameProvider (screen->dpy (),
1957+ outputWindow));
1958+ else
1959+ priv->frameProvider.reset (new UndefinedFrameProvider ());
1960+ }
1961+#endif
1962+
1963 return true;
1964 }
1965
1966@@ -993,6 +1209,13 @@
1967 return;
1968 }
1969
1970+ if (strstr (glxExtensions, "GLX_EXT_buffer_age"))
1971+ {
1972+ compLogMessage ("opengl", CompLogLevelInfo,
1973+ "GLX_EXT_buffer_age is supported");
1974+ GL::bufferAge = true;
1975+ }
1976+
1977 priv->getProcAddress = (GL::GLXGetProcAddressProc)
1978 getProcAddress ("glXGetProcAddressARB");
1979 GL::bindTexImage = (GL::GLXBindTexImageProc)
1980@@ -1209,9 +1432,6 @@
1981 glXDestroyContext (screen->dpy (), priv->ctx);
1982 #endif
1983
1984- if (priv->scratchFbo)
1985- delete priv->scratchFbo;
1986-
1987 delete priv;
1988 }
1989
1990@@ -1233,7 +1453,7 @@
1991 ctx (EGL_NO_CONTEXT),
1992 doubleBuffer (screen->dpy (), *screen, surface),
1993 #endif
1994- scratchFbo (NULL),
1995+ scratchFbo (),
1996 outputRegion (),
1997 refreshSubBuffer (false),
1998 lastMask (0),
1999@@ -1246,13 +1466,16 @@
2000 autoProgram (new GLScreenAutoProgram(gs)),
2001 rootPixmapCopy (None),
2002 rootPixmapSize (),
2003+ frameProvider (),
2004 glVendor (NULL),
2005 glRenderer (NULL),
2006 glVersion (NULL),
2007+ postprocessingRequired (false),
2008 prevRegex (),
2009 prevBlacklisted (false)
2010 {
2011 ScreenInterface::setHandler (screen);
2012+ CompositeScreenInterface::setHandler (cScreen);
2013 }
2014
2015 PrivateGLScreen::~PrivateGLScreen ()
2016@@ -1443,8 +1666,11 @@
2017 {
2018 screen->outputChangeNotify ();
2019
2020+ frameProvider->invalidateAll ();
2021+
2022 if (scratchFbo)
2023 scratchFbo->allocate (*screen, NULL, GL_BGRA);
2024+
2025 updateView ();
2026 }
2027
2028@@ -1669,6 +1895,10 @@
2029 GLScreenInterface::projectionMatrix ()
2030 WRAPABLE_DEF (projectionMatrix)
2031
2032+bool
2033+GLScreenInterface::glPaintCompositedOutputRequired ()
2034+ WRAPABLE_DEF (glPaintCompositedOutputRequired)
2035+
2036 void
2037 GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
2038 GLFramebufferObject *fbo,
2039@@ -1977,18 +2207,6 @@
2040 glDepthMask (GL_FALSE);
2041 glStencilMask (0);
2042
2043- GLFramebufferObject *oldFbo = NULL;
2044- bool useFbo = false;
2045-
2046- /* Clear the color buffer where appropriate */
2047- if (GL::fboEnabled && scratchFbo)
2048- {
2049- oldFbo = scratchFbo->bind ();
2050- useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
2051- if (!useFbo)
2052- GLFramebufferObject::rebind (oldFbo);
2053- }
2054-
2055 #ifdef UNSAFE_ARM_SGX_FIXME
2056 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2057 !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2058@@ -2006,8 +2224,21 @@
2059 }
2060 #endif
2061
2062- CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2063- screen->region () : region;
2064+ CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2065+ screen->region () : region);
2066+ bool useFbo = false;
2067+ GLFramebufferObject *oldFbo = NULL;
2068+
2069+ postprocessingRequired = gScreen->glPaintCompositedOutputRequired ();
2070+ postprocessingRequired |= frameProvider->alwaysPostprocess ();
2071+
2072+ /* Clear the color buffer where appropriate */
2073+ if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ()))
2074+ {
2075+ oldFbo = scratchFbo->bind ();
2076+ if (scratchFbo->checkStatus ())
2077+ useFbo = true;
2078+ }
2079
2080 foreach (CompOutput *output, outputs)
2081 {
2082@@ -2034,7 +2265,8 @@
2083
2084 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2085 identity,
2086- CompRegion (*output), output,
2087+ CompRegion (*output),
2088+ output,
2089 PAINT_SCREEN_REGION_MASK |
2090 PAINT_SCREEN_FULL_MASK);
2091 }
2092@@ -2057,7 +2289,9 @@
2093 tmpRegion = CompRegion (*output);
2094 #endif
2095
2096- outputRegion = tmpRegion & CompRegion (*output);
2097+ /* Clip current paint region to output extents */
2098+ CompRegionRef wholeOutput (output->region ());
2099+ outputRegion = (paintRegion & wholeOutput);
2100
2101 if (!gScreen->glPaintOutput (defaultScreenPaintAttrib,
2102 identity,
2103@@ -2068,10 +2302,11 @@
2104
2105 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2106 identity,
2107- CompRegion (*output), output,
2108+ wholeOutput, output,
2109 PAINT_SCREEN_FULL_MASK);
2110
2111- tmpRegion += *output;
2112+ paintRegion += wholeOutput;
2113+ cScreen->addOverdrawDamageRegion (wholeOutput);
2114 }
2115 }
2116 }
2117@@ -2082,13 +2317,18 @@
2118
2119 if (useFbo)
2120 {
2121- GLFramebufferObject::rebind (oldFbo);
2122-
2123 // FIXME: does not work if screen dimensions exceed max texture size
2124 // We should try to use glBlitFramebuffer instead.
2125- gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);
2126+ GLFramebufferObject::rebind (oldFbo);
2127+ /* If we must always postprocess, then we don't have any
2128+ * "real" backbuffer persistence, redraw the whole thing */
2129+ gScreen->glPaintCompositedOutput (frameProvider->alwaysPostprocess () ?
2130+ screen->region () :
2131+ paintRegion, scratchFbo.get (), mask);
2132 }
2133
2134+ frameProvider->endFrame ();
2135+
2136 if (cScreen->outputWindowChanged ())
2137 {
2138 /*
2139@@ -2100,20 +2340,27 @@
2140 return;
2141 }
2142
2143+ bool persistence = frameProvider->providesPersistence ();
2144 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2145- bool fullscreen = useFbo ||
2146+ bool fullscreen = persistence ||
2147 alwaysSwap ||
2148 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2149 commonFrontbuffer);
2150
2151 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2152- doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
2153+ doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, persistence);
2154 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2155- doubleBuffer.render (tmpRegion, fullscreen);
2156+ doubleBuffer.render (paintRegion, fullscreen);
2157
2158 lastMask = mask;
2159 }
2160
2161+unsigned int
2162+PrivateGLScreen::getFrameAge ()
2163+{
2164+ return frameProvider->getCurrentFrame ();
2165+}
2166+
2167 bool
2168 PrivateGLScreen::hasVSync ()
2169 {
2170@@ -2138,6 +2385,13 @@
2171 }
2172
2173 void
2174+PrivateGLScreen::damageCutoff ()
2175+{
2176+ cScreen->applyDamageForFrameAge (frameProvider->getCurrentFrame ());
2177+ cScreen->damageCutoff ();
2178+}
2179+
2180+void
2181 PrivateGLScreen::updateRenderMode ()
2182 {
2183 #ifndef USE_GLES
2184@@ -2170,6 +2424,12 @@
2185 return prevBlacklisted;
2186 }
2187
2188+bool
2189+PrivateGLScreen::postprocessRequiredForCurrentFrame ()
2190+{
2191+ return postprocessingRequired;
2192+}
2193+
2194 GLTexture::BindPixmapHandle
2195 GLScreen::registerBindPixmap (GLTexture::BindPixmapProc proc)
2196 {
2197@@ -2198,7 +2458,7 @@
2198 GLFramebufferObject *
2199 GLScreen::fbo ()
2200 {
2201- return priv->scratchFbo;
2202+ return priv->scratchFbo.get ();
2203 }
2204
2205 GLTexture *
2206
2207=== modified file 'plugins/resize/src/resize.cpp'
2208--- plugins/resize/src/resize.cpp 2012-10-19 09:23:11 +0000
2209+++ plugins/resize/src/resize.cpp 2013-02-13 11:42:35 +0000
2210@@ -257,7 +257,7 @@
2211 float xScale, yScale;
2212 int x, y;
2213
2214- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2215+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2216 return false;
2217
2218 status = gWindow->glPaint (attrib, transform, region,
2219
2220=== modified file 'plugins/ring/src/ring.cpp'
2221--- plugins/ring/src/ring.cpp 2013-01-19 11:47:22 +0000
2222+++ plugins/ring/src/ring.cpp 2013-02-13 11:42:35 +0000
2223@@ -264,7 +264,7 @@
2224 GLWindowPaintAttrib wAttrib (gWindow->lastPaintAttrib ());
2225 GLMatrix wTransform = transform;
2226
2227- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2228+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2229 return false;
2230
2231 if (mSlot)
2232
2233=== modified file 'plugins/scale/src/scale.cpp'
2234--- plugins/scale/src/scale.cpp 2013-01-29 23:16:32 +0000
2235+++ plugins/scale/src/scale.cpp 2013-02-13 11:42:35 +0000
2236@@ -384,12 +384,14 @@
2237
2238 status = gWindow->glPaint (sAttrib, transform, region, mask);
2239
2240+ mask &= ~(PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
2241+
2242 if (scaled)
2243 {
2244 GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());
2245 GLMatrix wTransform (transform);
2246
2247- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2248+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2249 return false;
2250
2251 if (window->alpha () || lastAttrib.opacity != OPAQUE)
2252
2253=== modified file 'plugins/staticswitcher/src/staticswitcher.cpp'
2254--- plugins/staticswitcher/src/staticswitcher.cpp 2012-12-10 03:28:47 +0000
2255+++ plugins/staticswitcher/src/staticswitcher.cpp 2013-02-13 11:42:35 +0000
2256@@ -1246,7 +1246,7 @@
2257
2258 const CompWindow::Geometry &g = window->geometry ();
2259
2260- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
2261+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
2262 sScreen->ignoreSwitcher)
2263 return false;
2264
2265
2266=== modified file 'plugins/switcher/src/switcher.cpp'
2267--- plugins/switcher/src/switcher.cpp 2012-12-10 03:28:47 +0000
2268+++ plugins/switcher/src/switcher.cpp 2013-02-13 11:42:35 +0000
2269@@ -971,7 +971,7 @@
2270
2271 const CompWindow::Geometry &g = window->geometry ();
2272
2273- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
2274+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
2275 sScreen->ignoreSwitcher)
2276 return false;
2277
2278
2279=== modified file 'plugins/td/src/3d.cpp'
2280--- plugins/td/src/3d.cpp 2013-02-03 17:50:59 +0000
2281+++ plugins/td/src/3d.cpp 2013-02-13 11:42:35 +0000
2282@@ -163,7 +163,7 @@
2283 glGetIntegerv (GL_CULL_FACE_MODE, &cull);
2284 cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;
2285
2286- if (ww && wh && !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) &&
2287+ if (ww && wh && !(mask & PAINT_WINDOW_NO_DRAW_MASKS) &&
2288 ((cs->paintOrder () == FTB && mFtb) ||
2289 (cs->paintOrder () == BTF && !mFtb)))
2290 {
2291
2292=== modified file 'plugins/water/src/water.cpp'
2293--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
2294+++ plugins/water/src/water.cpp 2013-02-13 11:42:35 +0000
2295@@ -317,6 +317,12 @@
2296 }
2297 }
2298
2299+bool
2300+WaterScreen::glPaintCompositedOutputRequired ()
2301+{
2302+ return true;
2303+}
2304+
2305 void
2306 WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2307 GLFramebufferObject *fbo,
2308@@ -467,6 +473,7 @@
2309 cScreen->preparePaintSetEnabled (this, false);
2310 gScreen->glPaintOutputSetEnabled (this, false);
2311 gScreen->glPaintCompositedOutputSetEnabled (this, false);
2312+ gScreen->glPaintCompositedOutputRequiredSetEnabled (this, false);
2313 cScreen->donePaintSetEnabled (this, false);
2314 }
2315
2316
2317=== modified file 'plugins/water/src/water.h'
2318--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
2319+++ plugins/water/src/water.h 2013-02-13 11:42:35 +0000
2320@@ -64,6 +64,7 @@
2321
2322 void handleEvent (XEvent *);
2323
2324+ bool glPaintCompositedOutputRequired ();
2325 void glPaintCompositedOutput (const CompRegion &region,
2326 GLFramebufferObject *fbo,
2327 unsigned int mask);
2328
2329=== modified file 'src/event.cpp'
2330--- src/event.cpp 2013-01-03 16:06:41 +0000
2331+++ src/event.cpp 2013-02-13 11:42:35 +0000
2332@@ -1288,17 +1288,6 @@
2333 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))
2334 privateScreen.setDefaultWindowAttributes (&wa);
2335
2336- /* That being said, we should store as much information as possible
2337- * about it. There may be requests relative to this window that could
2338- * use the data in the XCreateWindowEvent structure, especially the
2339- * override redirect state */
2340- wa.x = event->xcreatewindow.x;
2341- wa.y = event->xcreatewindow.y;
2342- wa.width = event->xcreatewindow.width;
2343- wa.height = event->xcreatewindow.height;
2344- wa.border_width = event->xcreatewindow.border_width;
2345- wa.override_redirect = event->xcreatewindow.override_redirect;
2346-
2347 foreach (CompWindow *w, screen->windows ())
2348 {
2349 if (w->priv->serverFrame == event->xcreatewindow.window)
2350@@ -1478,15 +1467,7 @@
2351 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))
2352 privateScreen.setDefaultWindowAttributes (&wa);
2353
2354- /* That being said, we should store as much information as possible
2355- * about it. There may be requests relative to this window that could
2356- * use the data in the XCreateWindowEvent structure, especially the
2357- * override redirect state */
2358- wa.x = event->xreparent.x;
2359- wa.y = event->xreparent.y;
2360- wa.override_redirect = event->xreparent.override_redirect;
2361-
2362- PrivateWindow::createCompWindow (getTopWindow ()->id (), getTopServerWindow ()->id (), wa, event->xreparent.window);
2363+ PrivateWindow::createCompWindow (getTopWindow ()->id (), getTopServerWindow ()->id (), wa, event->xcreatewindow.window);
2364 break;
2365 }
2366 else
2367@@ -2118,10 +2099,7 @@
2368 ServerLock lock (screen->serverGrabInterface ());
2369
2370 /* This will be the window that we must lower relative to */
2371- CompWindow *sibling =
2372- PrivateWindow::findValidStackSiblingBelow (active,
2373- fsw,
2374- lock);
2375+ CompWindow *sibling = PrivateWindow::findValidStackSiblingBelow (active, fsw, lock);
2376
2377 if (sibling)
2378 {
2379@@ -2199,11 +2177,7 @@
2380 if (w)
2381 {
2382 ServerLock lock (screen->serverGrabInterface ());
2383- if (PrivateWindow::stackDocks (w,
2384- dockWindows,
2385- &xwc,
2386- &mask,
2387- lock))
2388+ if (PrivateWindow::stackDocks (w, dockWindows, &xwc, &mask, lock))
2389 {
2390 Window sibling = xwc.sibling;
2391 xwc.stack_mode = Above;
2392
2393=== modified file 'src/option/tests/CMakeLists.txt'
2394--- src/option/tests/CMakeLists.txt 2012-12-10 13:01:00 +0000
2395+++ src/option/tests/CMakeLists.txt 2013-02-13 11:42:35 +0000
2396@@ -10,7 +10,6 @@
2397 ${compiz_SOURCE_DIR}/src/point/include
2398 ${compiz_SOURCE_DIR}/src/window/geometry/include
2399 ${compiz_SOURCE_DIR}/src/window/extents/include
2400- ${compiz_SOURCE_DIR}/src/servergrab/include
2401 ${COMPIZ_INCLUDE_DIRS}
2402 )
2403
2404
2405=== modified file 'src/option/tests/option.cpp'
2406--- src/option/tests/option.cpp 2012-12-10 13:01:00 +0000
2407+++ src/option/tests/option.cpp 2013-02-13 11:42:35 +0000
2408@@ -1,9 +1,5 @@
2409 #include <gtest/gtest.h>
2410
2411-/* XXX: including core.h means that we pull in
2412- * both window.h and screen.h which are cascading
2413- * includes. We should eliminate this dependency
2414- */
2415 #include "core/core.h"
2416 #include "core/action.h"
2417 #include "core/match.h"
2418
2419=== modified file 'src/outputdevices.h'
2420--- src/outputdevices.h 2012-12-10 13:01:00 +0000
2421+++ src/outputdevices.h 2013-02-13 11:42:35 +0000
2422@@ -25,11 +25,6 @@
2423 #include <core/output.h>
2424 #include <core/rect.h>
2425 #include <core/region.h>
2426-
2427-/* XXX: Including screen.h includes window.h and other unnecessary
2428- * headers which cause cascading header dependencies. We should seek to
2429- * eliminate this dependency
2430- */
2431 #include <core/screen.h>
2432
2433 namespace compiz
2434
2435=== modified file 'src/privatewindow.h'
2436--- src/privatewindow.h 2013-01-03 16:06:41 +0000
2437+++ src/privatewindow.h 2013-02-13 11:42:35 +0000
2438@@ -33,6 +33,8 @@
2439 #include <core/point.h>
2440 #include <core/timer.h>
2441
2442+class ServerLock;
2443+
2444 #include <boost/shared_ptr.hpp>
2445
2446 #define XWINDOWCHANGES_INIT {0, 0, 0, 0, 0, None, 0}
2447@@ -127,22 +129,23 @@
2448
2449 bool isInvisible() const;
2450
2451- static bool stackLayerCheck (CompWindow *w,
2452- Window clientLeader,
2453- CompWindow *below,
2454+ static bool stackLayerCheck (CompWindow *w,
2455+ Window clientLeader,
2456+ CompWindow *below,
2457 const ServerLock &lock);
2458
2459- static bool avoidStackingRelativeTo (CompWindow *w, const ServerLock &lock);
2460+ static bool avoidStackingRelativeTo (CompWindow *w,
2461+ const ServerLock &lock);
2462
2463- static CompWindow * findSiblingBelow (CompWindow *w,
2464- bool aboveFs,
2465+ static CompWindow * findSiblingBelow (CompWindow *w,
2466+ bool aboveFs,
2467 const ServerLock &lock);
2468
2469- static CompWindow * findLowestSiblingBelow (CompWindow *w,
2470+ static CompWindow * findLowestSiblingBelow (CompWindow *w,
2471 const ServerLock &lock);
2472
2473- static bool validSiblingBelow (CompWindow *w,
2474- CompWindow *sibling,
2475+ static bool validSiblingBelow (CompWindow *w,
2476+ CompWindow *sibling,
2477 const ServerLock &lock);
2478
2479 void saveGeometry (int mask);
2480@@ -152,21 +155,21 @@
2481 void reconfigureXWindow (unsigned int valueMask,
2482 XWindowChanges *xwc);
2483
2484- static bool stackDocks (CompWindow *w,
2485- CompWindowList &updateList,
2486- XWindowChanges *xwc,
2487- unsigned int *mask,
2488+ static bool stackDocks (CompWindow *w,
2489+ CompWindowList &updateList,
2490+ XWindowChanges *xwc,
2491+ unsigned int *mask,
2492 const ServerLock &lock);
2493
2494- static bool stackTransients (CompWindow *w,
2495- CompWindow *avoid,
2496- XWindowChanges *xwc,
2497- CompWindowList &updateList,
2498+ static bool stackTransients (CompWindow *w,
2499+ CompWindow *avoid,
2500+ XWindowChanges *xwc,
2501+ CompWindowList &updateList,
2502 const ServerLock &lock);
2503
2504- static void stackAncestors (CompWindow *w,
2505- XWindowChanges *xwc,
2506- CompWindowList &updateList,
2507+ static void stackAncestors (CompWindow *w,
2508+ XWindowChanges *xwc,
2509+ CompWindowList &updateList,
2510 const ServerLock &lock);
2511
2512 static bool isAncestorTo (CompWindow *transient,
2513@@ -179,8 +182,8 @@
2514 int addWindowSizeChanges (XWindowChanges *xwc,
2515 CompWindow::Geometry old);
2516
2517- int addWindowStackChanges (XWindowChanges *xwc,
2518- CompWindow *sibling,
2519+ int addWindowStackChanges (XWindowChanges *xwc,
2520+ CompWindow *sibling,
2521 const ServerLock &lock);
2522
2523 static CompWindow * findValidStackSiblingBelow (CompWindow *w,
2524
2525=== modified file 'src/tests/CMakeLists.txt'
2526--- src/tests/CMakeLists.txt 2013-01-03 16:06:41 +0000
2527+++ src/tests/CMakeLists.txt 2013-02-13 11:42:35 +0000
2528@@ -10,7 +10,6 @@
2529 ${COMPIZ_MAIN_SOURCE_DIR}/pluginclasshandler/include
2530 ${COMPIZ_MAIN_SOURCE_DIR}/window/geometry/include
2531 ${COMPIZ_MAIN_SOURCE_DIR}/window/extents/include
2532- ${COMPIZ_MAIN_SOURCE_DIR}/servergrab/include
2533 ${COMPIZ_INCLUDE_DIRS}
2534 )
2535
2536
2537=== modified file 'src/window.cpp'
2538--- src/window.cpp 2013-02-12 22:02:10 +0000
2539+++ src/window.cpp 2013-02-13 11:42:35 +0000
2540@@ -41,6 +41,7 @@
2541 #include <core/icon.h>
2542 #include <core/atoms.h>
2543 #include "core/windowconstrainment.h"
2544+#include <core/servergrab.h>
2545 #include "privatewindow.h"
2546 #include "privatescreen.h"
2547 #include "privatestackdebugger.h"
2548
2549=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp'
2550--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2012-12-10 12:38:48 +0000
2551+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2013-02-13 11:42:35 +0000
2552@@ -293,83 +293,3 @@
2553 EXPECT_EQ (*it++, w3);
2554 EXPECT_EQ (*it++, w2);
2555 }
2556-
2557-TEST_F (CompizXorgSystemStackingTest, TestCreateRelativeToDestroyedWindowFindsAnotherAppropriatePosition)
2558-{
2559- ::Display *dpy = Display ();
2560- ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
2561-
2562- Window dock = ct::CreateNormalWindow (dpy);
2563-
2564- /* Make it a dock */
2565- MakeDock (dpy, dock);
2566-
2567- /* Immediately map the dock window and clear the event queue for it */
2568- XMapRaised (dpy, dock);
2569-
2570- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, dock, ReparentNotify, -1, -1)));
2571- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, dock, MapNotify, -1, -1)));
2572-
2573- /* Dock window needs to be in the client list */
2574- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
2575- DefaultRootWindow (dpy),
2576- PropertyNotify,
2577- -1,
2578- -1,
2579- matcher)));
2580- std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
2581- ASSERT_EQ (clientList.size (), 1);
2582-
2583- Window w1 = ct::CreateNormalWindow (dpy);
2584- Window w2 = ct::CreateNormalWindow (dpy);
2585-
2586- XMapRaised (dpy, w1);
2587-
2588- /* All reparented and mapped */
2589- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy,w1, ReparentNotify, -1, -1)));
2590- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w1, MapNotify, -1, -1)));
2591-
2592- /* Grab the server so that we can guaruntee that all of these requests
2593- * happen before compiz gets them */
2594- XGrabServer (dpy);
2595- XSync (dpy, false);
2596-
2597- /* Map the second window, so it ideally goes above w1. Compiz will
2598- * receive the MapRequest for this first */
2599- XMapRaised (dpy, w2);
2600-
2601- /* Create window that has w2 as its ideal above-candidate
2602- * (compiz will receive the CreateNotify for this window
2603- * after the MapRequest but before the subsequent MapNotify) */
2604- Window w3 = ct::CreateNormalWindow (dpy);
2605-
2606- XMapRaised (dpy, w3);
2607-
2608- /* Destroy w2 */
2609- XDestroyWindow (dpy, w2);
2610-
2611- XUngrabServer (dpy);
2612- XSync (dpy, false);
2613-
2614- /* Reparented and mapped */
2615- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w3, ReparentNotify, -1, -1)));
2616- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w3, MapNotify, -1, -1)));
2617-
2618- /* Update _NET_CLIENT_LIST_STACKING twice */
2619- ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
2620- DefaultRootWindow (dpy),
2621- PropertyNotify,
2622- -1,
2623- -1,
2624- matcher)));
2625-
2626- /* Check the client list to see that dock > w3 > w1 */
2627- clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
2628-
2629- std::list <Window>::iterator it = clientList.begin ();
2630-
2631- EXPECT_EQ (3, clientList.size ());
2632- EXPECT_EQ (w1, (*it++));
2633- EXPECT_EQ (w3, (*it++));
2634- EXPECT_EQ (dock, (*it++));
2635-}

Subscribers

People subscribed via source and target branches