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: 4049 lines (+1511/-1543)
42 files modified
include/core/CMakeLists.txt (+0/-1)
include/core/configurerequestbuffer.h (+0/-73)
include/core/window.h (+7/-26)
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/composite/src/window.cpp (+5/-1)
plugins/kdecompat/src/kdecompat.cpp (+2/-2)
plugins/move/src/move.cpp (+5/-12)
plugins/move/src/move.h (+0/-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 (+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)
src/CMakeLists.txt (+0/-7)
src/asyncserverwindow.h (+0/-52)
src/configurerequestbuffer-impl.h (+0/-145)
src/configurerequestbuffer.cpp (+0/-363)
src/event.cpp (+1/-1)
src/privatewindow.h (+1/-45)
src/syncserverwindow.h (+0/-49)
src/tests/CMakeLists.txt (+0/-11)
src/tests/test_configurerequestbuffer.cpp (+0/-667)
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
Esokrates testing, benchmarking Pending
Compiz Maintainers Pending
Review via email: mp+148842@code.launchpad.net

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

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

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 :
review: Approve (continuous-integration)
3565. By Sam Spilsbury

Revert more changes which should not have happened

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
3566. By Sam Spilsbury

Merge lp:compiz

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
3567. By Sam Spilsbury

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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
3568. By Sam Spilsbury

Merge lp:compiz

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

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/CMakeLists.txt'
2--- include/core/CMakeLists.txt 2013-01-03 16:05:26 +0000
3+++ include/core/CMakeLists.txt 2013-02-28 03:13:24 +0000
4@@ -1,7 +1,6 @@
5 set (_headers
6 action.h
7 atoms.h
8- configurerequestbuffer.h
9 core.h
10 countedlist.h
11 global.h
12
13=== removed file 'include/core/configurerequestbuffer.h'
14--- include/core/configurerequestbuffer.h 2012-12-13 11:12:32 +0000
15+++ include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000
16@@ -1,73 +0,0 @@
17-/*
18- * Copyright © 2012 Sam Spilsbury
19- *
20- * Permission to use, copy, modify, distribute, and sell this software
21- * and its documentation for any purpose is hereby granted without
22- * fee, provided that the above copyright notice appear in all copies
23- * and that both that copyright notice and this permission notice
24- * appear in supporting documentation, and that the name of
25- * Canonical Ltd. not be used in advertising or publicity pertaining to
26- * distribution of the software without specific, written prior permission.
27- * Canonical Ltd. makes no representations about the suitability of this
28- * software for any purpose. It is provided "as is" without express or
29- * implied warranty.
30- *
31- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
32- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
33- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
34- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
35- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
36- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
37- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38- *
39- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
40- */
41-#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
42-#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
43-
44-#include <boost/shared_ptr.hpp>
45-#include <X11/Xlib.h>
46-#include <syncserverwindow.h>
47-
48-namespace compiz
49-{
50-namespace window
51-{
52-namespace configure_buffers
53-{
54-class Releasable
55-{
56- public:
57-
58- typedef boost::shared_ptr <Releasable> Ptr;
59-
60- virtual void release () = 0;
61-};
62-
63-class Buffer :
64- public SyncServerWindow
65-{
66- public:
67-
68- typedef boost::shared_ptr <Buffer> Ptr;
69-
70- virtual ~Buffer () {}
71-
72- virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
73- virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
74- virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
75-
76- virtual void pushSyntheticConfigureNotify () = 0;
77-
78- virtual Releasable::Ptr obtainLock () = 0;
79-
80- /* This API will all configure requests to be
81- * released. It should only be used in situations
82- * where you have a server grab and need
83- * to have complete sync with the server */
84- virtual void forceRelease () = 0;
85-};
86-}
87-}
88-}
89-#endif
90
91=== modified file 'include/core/window.h'
92--- include/core/window.h 2013-02-10 05:01:50 +0000
93+++ include/core/window.h 2013-02-28 03:13:24 +0000
94@@ -54,26 +54,13 @@
95 class PrivateWindow;
96 struct CompStartupSequence;
97
98-namespace compiz
99-{
100-namespace window
101-{
102-namespace configure_buffers
103-{
104-class Releasable;
105-typedef boost::shared_ptr <Releasable> ReleasablePtr;
106-}
107-}
108-
109-namespace private_screen
110-{
111-class Ping;
112-class GrabManager;
113-class OutputDevices;
114-class WindowManager;
115-class StartupSequence;
116-}
117-}
118+namespace compiz { namespace private_screen {
119+ class Ping;
120+ class GrabManager;
121+ class OutputDevices;
122+ class WindowManager;
123+ class StartupSequence;
124+}}
125
126 #define ROOTPARENT(x) (((x)->frame ()) ? (x)->frame () : (x)->id ())
127
128@@ -542,12 +529,6 @@
129 bool updateStruts ();
130 const CompStruts *struts () const;
131
132- bool queryAttributes (XWindowAttributes &);
133- bool queryFrameAttributes (XWindowAttributes &);
134-
135- compiz::window::configure_buffers::ReleasablePtr
136- obtainLockOnConfigureRequests ();
137-
138 WRAPABLE_HND (0, WindowInterface, void, getOutputExtents,
139 CompWindowExtents&);
140 WRAPABLE_HND (1, WindowInterface, void, getAllowedActions,
141
142=== modified file 'plugins/animation/src/animation.cpp'
143--- plugins/animation/src/animation.cpp 2013-01-11 08:28:51 +0000
144+++ plugins/animation/src/animation.cpp 2013-02-28 03:13:24 +0000
145@@ -1617,7 +1617,7 @@
146 // Is this the first glPaint call this round
147 // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK?
148 if (mPAScreen->mStartingNewPaintRound &&
149- !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
150+ !(mask & PAINT_WINDOW_NO_DRAW_MASKS))
151 {
152 mPAScreen->mStartingNewPaintRound = false;
153
154
155=== modified file 'plugins/composite/CMakeLists.txt'
156--- plugins/composite/CMakeLists.txt 2012-09-25 01:15:36 +0000
157+++ plugins/composite/CMakeLists.txt 2013-02-28 03:13:24 +0000
158@@ -2,9 +2,14 @@
159
160 include (CompizPlugin)
161
162+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
163 include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/pixmapbinding/include)
164+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking/include)
165+
166 link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/pixmapbinding)
167+link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/backbuffertracking)
168
169-compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding)
170+compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding compiz_composite_backbuffertracking)
171
172 add_subdirectory (src/pixmapbinding)
173+add_subdirectory (src/backbuffertracking)
174
175=== added file 'plugins/composite/include/composite/agedamagequery.h'
176--- plugins/composite/include/composite/agedamagequery.h 1970-01-01 00:00:00 +0000
177+++ plugins/composite/include/composite/agedamagequery.h 2013-02-28 03:13:24 +0000
178@@ -0,0 +1,53 @@
179+/*
180+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
181+ *
182+ * Copyright (c) 2012 Sam Spilsbury
183+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
184+ *
185+ * Permission is hereby granted, free of charge, to any person obtaining a
186+ * copy of this software and associated documentation files (the "Software"),
187+ * to deal in the Software without restriction, including without limitation
188+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
189+ * and/or sell copies of the Software, and to permit persons to whom the
190+ * Software is furnished to do so, subject to the following conditions:
191+ *
192+ * The above copyright notice and this permission notice shall be included in
193+ * all copies or substantial portions of the Software.
194+ *
195+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
196+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
198+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
199+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
200+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
201+ * DEALINGS IN THE SOFTWARE.
202+ */
203+#ifndef _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H
204+#define _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H
205+
206+#include <boost/shared_ptr.hpp>
207+#include <core/region.h>
208+
209+namespace compiz
210+{
211+namespace composite
212+{
213+namespace buffertracking
214+{
215+class AgeDamageQuery
216+{
217+ public:
218+
219+ typedef boost::shared_ptr <AgeDamageQuery> Ptr;
220+ typedef boost::function <bool (const CompRegion &)> AreaShouldBeMarkedDirty;
221+
222+ virtual ~AgeDamageQuery () {}
223+ virtual CompRegion damageForFrameAge (unsigned int) = 0;
224+ virtual const CompRegion & currentFrameDamage () = 0;
225+};
226+}
227+}
228+}
229+
230+#endif
231+
232
233=== modified file 'plugins/composite/include/composite/composite.h'
234--- plugins/composite/include/composite/composite.h 2012-10-16 05:11:10 +0000
235+++ plugins/composite/include/composite/composite.h 2013-02-28 03:13:24 +0000
236@@ -30,7 +30,7 @@
237
238 #include <X11/extensions/Xcomposite.h>
239
240-#define COMPIZ_COMPOSITE_ABI 5
241+#define COMPIZ_COMPOSITE_ABI 6
242
243 #include "core/pluginclasshandler.h"
244 #include "core/timer.h"
245@@ -38,6 +38,8 @@
246 #include "core/screen.h"
247 #include "core/wrapsystem.h"
248
249+#include "composite/agedamagequery.h"
250+
251 #define COMPOSITE_SCREEN_DAMAGE_PENDING_MASK (1 << 0)
252 #define COMPOSITE_SCREEN_DAMAGE_REGION_MASK (1 << 1)
253 #define COMPOSITE_SCREEN_DAMAGE_ALL_MASK (1 << 2)
254@@ -98,18 +100,19 @@
255 namespace composite
256 {
257 class PaintHandler {
258-public:
259- virtual ~PaintHandler () {};
260-
261- virtual void paintOutputs (CompOutput::ptrList &outputs,
262- unsigned int mask,
263- const CompRegion &region) = 0;
264-
265- virtual bool hasVSync () { return false; };
266- virtual bool requiredForcedRefreshRate () { return false; };
267-
268- virtual void prepareDrawing () {};
269- virtual bool compositingActive () { return false; };
270+ public:
271+ virtual ~PaintHandler () {};
272+
273+ virtual void paintOutputs (CompOutput::ptrList &outputs,
274+ unsigned int mask,
275+ const CompRegion &region) = 0;
276+
277+ virtual bool hasVSync () { return false; };
278+ virtual bool requiredForcedRefreshRate () { return false; };
279+
280+ virtual void prepareDrawing () {};
281+ virtual bool compositingActive () { return false; };
282+ virtual unsigned int getFrameAge () { return 1; }
283 };
284 }
285 }
286@@ -173,12 +176,19 @@
287 * Hookable function to damage regions directly
288 */
289 virtual void damageRegion (const CompRegion &r);
290+
291+ /**
292+ * Hookable function to notify plugins that the last damage
293+ * event for this frame has been received, and all further damage
294+ * events will be for the next frame
295+ */
296+ virtual void damageCutoff ();
297 };
298
299 extern template class PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>;
300
301 class CompositeScreen :
302- public WrapableHandler<CompositeScreenInterface, 7>,
303+ public WrapableHandler<CompositeScreenInterface, 8>,
304 public PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>,
305 public CompOption::Class
306 {
307@@ -203,6 +213,24 @@
308 void damageScreen ();
309
310 void damagePending ();
311+
312+ /**
313+ * Causes the damage that was recorded on N - 1 number of
314+ * frames ago to be added to the current frame, applied
315+ * culmulatively. An age of "zero" means that the entire frame
316+ * is considered undefined and must be completely repaired,
317+ * wheras an age of 1 means that this frame is the same as the
318+ * last frame, so no damage is required.
319+ */
320+ void applyDamageForFrameAge (unsigned int);
321+ unsigned int getFrameAge ();
322+ void addOverdrawDamageRegion (const CompRegion &);
323+
324+ typedef compiz::composite::buffertracking::AgeDamageQuery DamageQuery;
325+ typedef DamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty;
326+
327+ DamageQuery::Ptr
328+ getDamageQuery (const AreaShouldBeMarkedDirty &callback);
329
330
331 unsigned int damageMask ();
332@@ -248,6 +276,7 @@
333 * event loop
334 */
335 WRAPABLE_HND (6, CompositeScreenInterface, void, damageRegion, const CompRegion &);
336+ WRAPABLE_HND (7, CompositeScreenInterface, void, damageCutoff);
337
338 friend class PrivateCompositeDisplay;
339
340@@ -310,6 +339,12 @@
341 */
342 #define PAINT_WINDOW_BLEND_MASK (1 << 19)
343
344+/**
345+ * flags that would indicate the window is never actually drawn
346+ */
347+#define PAINT_WINDOW_NO_DRAW_MASKS (PAINT_WINDOW_OCCLUSION_DETECTION_MASK | \
348+ PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
349+
350 class CompositeWindowInterface;
351 extern template class WrapableInterface<CompositeWindow, CompositeWindowInterface>;
352
353
354=== added directory 'plugins/composite/src/backbuffertracking'
355=== added file 'plugins/composite/src/backbuffertracking/CMakeLists.txt'
356--- plugins/composite/src/backbuffertracking/CMakeLists.txt 1970-01-01 00:00:00 +0000
357+++ plugins/composite/src/backbuffertracking/CMakeLists.txt 2013-02-28 03:13:24 +0000
358@@ -0,0 +1,31 @@
359+INCLUDE_DIRECTORIES (
360+ ${CMAKE_CURRENT_SOURCE_DIR}/../../include
361+ ${CMAKE_CURRENT_SOURCE_DIR}/include
362+ ${CMAKE_CURRENT_SOURCE_DIR}/src
363+
364+ ${Boost_INCLUDE_DIRS}
365+)
366+
367+LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
368+
369+SET(
370+ SRCS
371+ ${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking.cpp
372+)
373+
374+ADD_LIBRARY(
375+ compiz_composite_backbuffertracking STATIC
376+
377+ ${SRCS}
378+)
379+
380+if (COMPIZ_BUILD_TESTING)
381+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
382+endif (COMPIZ_BUILD_TESTING)
383+
384+TARGET_LINK_LIBRARIES(
385+ compiz_composite_backbuffertracking
386+
387+ compiz_size
388+ compiz_core
389+)
390
391=== added directory 'plugins/composite/src/backbuffertracking/include'
392=== added file 'plugins/composite/src/backbuffertracking/include/backbuffertracking.h'
393--- plugins/composite/src/backbuffertracking/include/backbuffertracking.h 1970-01-01 00:00:00 +0000
394+++ plugins/composite/src/backbuffertracking/include/backbuffertracking.h 2013-02-28 03:13:24 +0000
395@@ -0,0 +1,125 @@
396+/*
397+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
398+ *
399+ * Copyright (c) 2012 Sam Spilsbury
400+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
401+ *
402+ * Permission is hereby granted, free of charge, to any person obtaining a
403+ * copy of this software and associated documentation files (the "Software"),
404+ * to deal in the Software without restriction, including without limitation
405+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
406+ * and/or sell copies of the Software, and to permit persons to whom the
407+ * Software is furnished to do so, subject to the following conditions:
408+ *
409+ * The above copyright notice and this permission notice shall be included in
410+ * all copies or substantial portions of the Software.
411+ *
412+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
413+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
414+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
415+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
416+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
417+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
418+ * DEALINGS IN THE SOFTWARE.
419+ */
420+#ifndef _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H
421+#define _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H
422+
423+#include <memory>
424+#include <boost/noncopyable.hpp>
425+#include <boost/shared_ptr.hpp>
426+#include <boost/weak_ptr.hpp>
427+#include <boost/function.hpp>
428+
429+#include <composite/agedamagequery.h>
430+
431+class CompSize;
432+class CompRegion;
433+
434+namespace compiz
435+{
436+namespace composite
437+{
438+namespace buffertracking
439+{
440+class DamageAgeTracking
441+{
442+ public:
443+
444+ virtual ~DamageAgeTracking () {};
445+ virtual void dirtyAreaOnCurrentFrame (const CompRegion &) = 0;
446+ virtual void overdrawRegionOnPaintingFrame (const CompRegion &) = 0;
447+ virtual void subtractObscuredArea (const CompRegion &) = 0;
448+ virtual void incrementFrameAges () = 0;
449+};
450+
451+class AgeingDamageBufferObserver
452+{
453+ public:
454+
455+ virtual ~AgeingDamageBufferObserver () {};
456+ virtual void observe (DamageAgeTracking &damageAgeTracker) = 0;
457+ virtual void unobserve (DamageAgeTracking &damageAgeTracker) = 0;
458+};
459+
460+class AgeingDamageBuffers :
461+ public AgeingDamageBufferObserver,
462+ boost::noncopyable
463+{
464+ public:
465+
466+ AgeingDamageBuffers ();
467+
468+ void observe (DamageAgeTracking &damageAgeTracker);
469+ void unobserve (DamageAgeTracking &damageAgeTracker);
470+ void incrementAges ();
471+ void markAreaDirty (const CompRegion &reg);
472+ void markAreaDirtyOnLastFrame (const CompRegion &reg);
473+ void subtractObscuredArea (const CompRegion &reg);
474+
475+ private:
476+
477+ class Private;
478+ std::auto_ptr <Private> priv;
479+};
480+
481+class FrameRoster :
482+ public DamageAgeTracking,
483+ public AgeDamageQuery,
484+ boost::noncopyable
485+{
486+ public:
487+
488+ typedef AgeDamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty;
489+ typedef boost::shared_ptr <FrameRoster> Ptr;
490+
491+ FrameRoster (const CompSize &size,
492+ AgeingDamageBufferObserver &tracker,
493+ const AreaShouldBeMarkedDirty &shouldMarkDirty);
494+
495+ ~FrameRoster ();
496+
497+ void dirtyAreaOnCurrentFrame (const CompRegion &);
498+ void overdrawRegionOnPaintingFrame (const CompRegion &);
499+ void subtractObscuredArea (const CompRegion &);
500+ void incrementFrameAges ();
501+ CompRegion damageForFrameAge (unsigned int);
502+ const CompRegion & currentFrameDamage ();
503+
504+ class Private;
505+ std::auto_ptr <Private> priv;
506+
507+ static const unsigned int NUM_TRACKED_FRAMES = 10;
508+
509+ static
510+ FrameRoster::Ptr create (const CompSize &size,
511+
512+ const AreaShouldBeMarkedDirty &shouldMarkDirty);
513+
514+ private:
515+
516+};
517+} // namespace buffertracking
518+} // namespace composite
519+} // namespace compiz
520+#endif
521
522=== added directory 'plugins/composite/src/backbuffertracking/src'
523=== added file 'plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp'
524--- plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 1970-01-01 00:00:00 +0000
525+++ plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 2013-02-28 03:13:24 +0000
526@@ -0,0 +1,214 @@
527+/*
528+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
529+ *
530+ * Copyright (c) 2012 Sam Spilsbury
531+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
532+ *
533+ * Permission is hereby granted, free of charge, to any person obtaining a
534+ * copy of this software and associated documentation files (the "Software"),
535+ * to deal in the Software without restriction, including without limitation
536+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
537+ * and/or sell copies of the Software, and to permit persons to whom the
538+ * Software is furnished to do so, subject to the following conditions:
539+ *
540+ * The above copyright notice and this permission notice shall be included in
541+ * all copies or substantial portions of the Software.
542+ *
543+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
544+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
545+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
546+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
547+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
548+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
549+ * DEALINGS IN THE SOFTWARE.
550+ */
551+#include <deque>
552+#include <core/size.h>
553+#include <core/region.h>
554+#include "backbuffertracking.h"
555+#include <cstdio>
556+
557+namespace bt = compiz::composite::buffertracking;
558+
559+class bt::FrameRoster::Private
560+{
561+ public:
562+
563+ Private (const CompSize &size,
564+ bt::AgeingDamageBufferObserver &observer,
565+ const bt::FrameRoster::AreaShouldBeMarkedDirty &shouldBeMarkedDirty) :
566+ screenSize (size),
567+ observer (observer),
568+ shouldBeMarkedDirty (shouldBeMarkedDirty),
569+ oldFrames (1)
570+ {
571+ }
572+
573+ CompSize screenSize;
574+ bt::AgeingDamageBufferObserver &observer;
575+ bt::FrameRoster::AreaShouldBeMarkedDirty shouldBeMarkedDirty;
576+ std::deque <CompRegion> oldFrames;
577+};
578+
579+bt::FrameRoster::FrameRoster (const CompSize &size,
580+ bt::AgeingDamageBufferObserver &tracker,
581+ const AreaShouldBeMarkedDirty &shouldBeMarkedDirty) :
582+ priv (new bt::FrameRoster::Private (size,
583+ tracker,
584+ shouldBeMarkedDirty))
585+{
586+ priv->observer.observe (*this);
587+}
588+
589+bt::FrameRoster::~FrameRoster ()
590+{
591+ priv->observer.unobserve (*this);
592+}
593+
594+CompRegion
595+bt::FrameRoster::damageForFrameAge (unsigned int age)
596+{
597+ if (!age)
598+ return CompRegion (0, 0,
599+ priv->screenSize.width (),
600+ priv->screenSize.height ());
601+
602+ if (age >= priv->oldFrames.size ())
603+ return CompRegion (0, 0,
604+ priv->screenSize.width (),
605+ priv->screenSize.height ());
606+
607+ CompRegion accumulatedDamage;
608+
609+ while (age--)
610+ {
611+ unsigned int frameNum = (priv->oldFrames.size () - age) - 1;
612+ accumulatedDamage += priv->oldFrames[frameNum];
613+ }
614+
615+ return accumulatedDamage;
616+}
617+
618+void
619+bt::FrameRoster::dirtyAreaOnCurrentFrame (const CompRegion &r)
620+{
621+ if (priv->shouldBeMarkedDirty (r))
622+ (*priv->oldFrames.rbegin ()) += r;
623+}
624+
625+void
626+bt::FrameRoster::subtractObscuredArea (const CompRegion &r)
627+{
628+ (*priv->oldFrames.rbegin ()) -= r;
629+}
630+
631+void
632+bt::FrameRoster::overdrawRegionOnPaintingFrame (const CompRegion &r)
633+{
634+ assert (priv->oldFrames.size () > 1);
635+ std::deque <CompRegion>::reverse_iterator it = priv->oldFrames.rbegin ();
636+ ++it;
637+ (*it) += r;
638+}
639+
640+void
641+bt::FrameRoster::incrementFrameAges ()
642+{
643+ priv->oldFrames.push_back (CompRegion ());
644+
645+ /* Get rid of old frames */
646+ if (priv->oldFrames.size () > NUM_TRACKED_FRAMES)
647+ priv->oldFrames.pop_front ();
648+}
649+
650+const CompRegion &
651+bt::FrameRoster::currentFrameDamage ()
652+{
653+ return *priv->oldFrames.rbegin ();
654+}
655+
656+class bt::AgeingDamageBuffers::Private
657+{
658+ public:
659+
660+ std::vector <bt::DamageAgeTracking *> damageAgeTrackers;
661+};
662+
663+bt::AgeingDamageBuffers::AgeingDamageBuffers () :
664+ priv (new bt::AgeingDamageBuffers::Private ())
665+{
666+}
667+
668+void
669+bt::AgeingDamageBuffers::observe (bt::DamageAgeTracking &damageAgeTracker)
670+{
671+ priv->damageAgeTrackers.push_back (&damageAgeTracker);
672+}
673+
674+void
675+bt::AgeingDamageBuffers::unobserve (bt::DamageAgeTracking &damageAgeTracker)
676+{
677+ std::vector <bt::DamageAgeTracking *>::iterator it =
678+ std::find (priv->damageAgeTrackers.begin (),
679+ priv->damageAgeTrackers.end (),
680+ &damageAgeTracker);
681+
682+ if (it != priv->damageAgeTrackers.end ())
683+ priv->damageAgeTrackers.erase (it);
684+}
685+
686+void
687+bt::AgeingDamageBuffers::incrementAges ()
688+{
689+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
690+ priv->damageAgeTrackers.begin ();
691+ it != priv->damageAgeTrackers.end ();
692+ ++it)
693+ {
694+ bt::DamageAgeTracking *tracker = *it;
695+
696+ tracker->incrementFrameAges ();
697+ }
698+}
699+
700+void
701+bt::AgeingDamageBuffers::markAreaDirty (const CompRegion &reg)
702+{
703+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
704+ priv->damageAgeTrackers.begin ();
705+ it != priv->damageAgeTrackers.end ();
706+ ++it)
707+ {
708+ bt::DamageAgeTracking *tracker = *it;
709+
710+ tracker->dirtyAreaOnCurrentFrame (reg);
711+ }
712+}
713+
714+void
715+bt::AgeingDamageBuffers::subtractObscuredArea (const CompRegion &reg)
716+{
717+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
718+ priv->damageAgeTrackers.begin ();
719+ it != priv->damageAgeTrackers.end ();
720+ ++it)
721+ {
722+ bt::DamageAgeTracking *tracker = *it;
723+
724+ tracker->subtractObscuredArea (reg);
725+ }
726+}
727+
728+void
729+bt::AgeingDamageBuffers::markAreaDirtyOnLastFrame (const CompRegion &reg)
730+{
731+ for (std::vector <bt::DamageAgeTracking *>::iterator it =
732+ priv->damageAgeTrackers.begin ();
733+ it != priv->damageAgeTrackers.end ();
734+ ++it)
735+ {
736+ bt::DamageAgeTracking *tracker = *it;
737+
738+ tracker->overdrawRegionOnPaintingFrame (reg);
739+ }
740+}
741
742=== added directory 'plugins/composite/src/backbuffertracking/tests'
743=== added file 'plugins/composite/src/backbuffertracking/tests/CMakeLists.txt'
744--- plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
745+++ plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 2013-02-28 03:13:24 +0000
746@@ -0,0 +1,24 @@
747+find_library (GMOCK_LIBRARY gmock)
748+find_library (GMOCK_MAIN_LIBRARY gmock_main)
749+
750+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
751+ message ("Google Mock and Google Test not found - cannot build tests!")
752+ set (COMPIZ_BUILD_TESTING OFF)
753+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
754+
755+include_directories (${GTEST_INCLUDE_DIRS})
756+
757+link_directories (${COMPIZ_LIBRARY_DIRS})
758+
759+add_executable (compiz_test_composite_backbuffertracking
760+ ${CMAKE_CURRENT_SOURCE_DIR}/test-composite-backbuffertracking.cpp)
761+
762+target_link_libraries (compiz_test_composite_backbuffertracking
763+ compiz_composite_backbuffertracking
764+ ${GTEST_BOTH_LIBRARIES}
765+ ${GMOCK_LIBRARY}
766+ ${GMOCK_MAIN_LIBRARY}
767+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
768+ )
769+
770+compiz_discover_tests (compiz_test_composite_backbuffertracking COVERAGE compiz_composite_backbuffertracking)
771
772=== added file 'plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp'
773--- plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 1970-01-01 00:00:00 +0000
774+++ plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 2013-02-28 03:13:24 +0000
775@@ -0,0 +1,450 @@
776+/*
777+ * Compiz, composite plugin, GLX_EXT_buffer_age logic
778+ *
779+ * Copyright (c) 2012 Sam Spilsbury
780+ * Authors: Sam Spilsbury <smspillaz@gmail.com>
781+ *
782+ * Permission is hereby granted, free of charge, to any person obtaining a
783+ * copy of this software and associated documentation files (the "Software"),
784+ * to deal in the Software without restriction, including without limitation
785+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
786+ * and/or sell copies of the Software, and to permit persons to whom the
787+ * Software is furnished to do so, subject to the following conditions:
788+ *
789+ * The above copyright notice and this permission notice shall be included in
790+ * all copies or substantial portions of the Software.
791+ *
792+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
793+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
794+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
795+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
796+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
797+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
798+ * DEALINGS IN THE SOFTWARE.
799+ */
800+#include <boost/bind.hpp>
801+
802+#include <gtest/gtest.h>
803+#include <gmock/gmock.h>
804+
805+#include <core/region.h>
806+#include <core/size.h>
807+
808+#include "backbuffertracking.h"
809+
810+using ::testing::NiceMock;
811+using ::testing::_;
812+using ::testing::AtLeast;
813+
814+namespace bt = compiz::composite::buffertracking;
815+
816+namespace
817+{
818+class MockAgeingDamageBufferObserver :
819+ public bt::AgeingDamageBufferObserver
820+{
821+ public:
822+
823+ MOCK_METHOD1 (observe, void (bt::DamageAgeTracking &));
824+ MOCK_METHOD1 (unobserve, void (bt::DamageAgeTracking &));
825+};
826+
827+bool alwaysTrackDamage (const CompRegion &)
828+{
829+ return true;
830+}
831+
832+
833+class BackbufferTracking :
834+ public ::testing::Test
835+{
836+ public:
837+
838+ BackbufferTracking () :
839+ screen (1000, 1000),
840+ roster ()
841+ {
842+ }
843+
844+ virtual void SetUp ()
845+ {
846+ SetupRoster ();
847+ }
848+
849+ virtual void SetupRoster ()
850+ {
851+ roster.reset (new bt::FrameRoster (screen,
852+ niceTracker,
853+ boost::bind (alwaysTrackDamage,
854+ _1)));
855+ }
856+
857+ protected:
858+
859+ CompSize screen;
860+ NiceMock <MockAgeingDamageBufferObserver> niceTracker;
861+ bt::FrameRoster::Ptr roster;
862+};
863+
864+class BackbufferTrackingCallbacks :
865+ public BackbufferTracking
866+{
867+ public:
868+
869+ BackbufferTrackingCallbacks () :
870+ shouldDamage (false)
871+ {
872+ }
873+
874+ protected:
875+
876+ void allowDamage (bool allow)
877+ {
878+ shouldDamage = allow;
879+ }
880+
881+ private:
882+
883+ virtual void SetupRoster ()
884+ {
885+ roster.reset (new bt::FrameRoster (screen,
886+ niceTracker,
887+ boost::bind (&BackbufferTrackingCallbacks::shouldDamageCallback,
888+ this, _1)));
889+ }
890+
891+ bool shouldDamageCallback (const CompRegion &)
892+ {
893+ return shouldDamage;
894+ }
895+
896+ bool shouldDamage;
897+};
898+}
899+
900+std::ostream &
901+operator<< (std::ostream &os, const CompRegion &reg)
902+{
903+ os << "Region with Bounding Rectangle : " <<
904+ reg.boundingRect ().x () << " " <<
905+ reg.boundingRect ().y () << " " <<
906+ reg.boundingRect ().width () << " " <<
907+ reg.boundingRect ().height () << std::endl;
908+ CompRect::vector rects (reg.rects ());
909+ for (CompRect::vector::iterator it = rects.begin ();
910+ it != rects.end ();
911+ it++)
912+ os << " - subrectangle: " <<
913+ (*it).x () << " " <<
914+ (*it).y () << " " <<
915+ (*it).width () << " " <<
916+ (*it).height () << " " << std::endl;
917+
918+ return os;
919+}
920+
921+TEST (BackbufferTrackingConstruction, CreateAddsToObserverList)
922+{
923+ MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver;
924+
925+ /* We can't verify the argument here,
926+ * but we can verify the function call */
927+ EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_));
928+ EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_)).Times (AtLeast (0));
929+ bt::FrameRoster roster (CompSize (),
930+ mockAgeingDamageBufferObserver,
931+ boost::bind (alwaysTrackDamage, _1));
932+}
933+
934+TEST (BackbufferTrackingConstruction, DestroyRemovesFromObserverList)
935+{
936+ MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver;
937+
938+ /* We can't verify the argument here,
939+ * but we can verify the function call */
940+ EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_)).Times (AtLeast (0));
941+ EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_));
942+ bt::FrameRoster roster (CompSize (),
943+ mockAgeingDamageBufferObserver,
944+ boost::bind (alwaysTrackDamage, _1));
945+}
946+
947+TEST_F (BackbufferTrackingCallbacks, TrackIntoCurrentIfCallbackTrue)
948+{
949+ allowDamage (true);
950+ CompRegion damage (100, 100, 100, 100);
951+ roster->dirtyAreaOnCurrentFrame (damage);
952+ EXPECT_EQ (damage, roster->currentFrameDamage ());
953+}
954+
955+TEST_F (BackbufferTrackingCallbacks, NoTrackIntoCurrentIfCallbackFalse)
956+{
957+ allowDamage (false);
958+ CompRegion damage (100, 100, 100, 100);
959+ roster->dirtyAreaOnCurrentFrame (damage);
960+ EXPECT_EQ (emptyRegion, roster->currentFrameDamage ());
961+}
962+
963+TEST_F (BackbufferTracking, DirtyAreaSubtraction)
964+{
965+ CompRegion dirty (100, 100, 100, 100);
966+ CompRegion obscured (150, 150, 50, 50);
967+ roster->dirtyAreaOnCurrentFrame (dirty);
968+ roster->subtractObscuredArea (obscured);
969+ EXPECT_EQ (dirty - obscured, roster->currentFrameDamage ());
970+}
971+
972+TEST_F (BackbufferTracking, DirtyAreaForAgeZeroAll)
973+{
974+ EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()),
975+ roster->damageForFrameAge (0));
976+}
977+
978+TEST_F (BackbufferTracking, DirtyAreaAllForOlderThanTrackedAge)
979+{
980+ EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()),
981+ roster->damageForFrameAge (1));
982+}
983+
984+TEST_F (BackbufferTracking, NoDirtyAreaForLastFrame)
985+{
986+ CompRegion all (0, 0, screen.width (), screen.height ());
987+ roster->dirtyAreaOnCurrentFrame (all);
988+ roster->incrementFrameAges ();
989+ EXPECT_EQ (emptyRegion, roster->damageForFrameAge (1));
990+}
991+
992+TEST_F (BackbufferTracking, DirtyAreaIfMoreSinceLastFrame)
993+{
994+ CompRegion all (0, 0, screen.width (), screen.height ());
995+ roster->dirtyAreaOnCurrentFrame (all);
996+ roster->incrementFrameAges ();
997+ roster->dirtyAreaOnCurrentFrame(all);
998+ EXPECT_EQ (all, roster->damageForFrameAge (1));
999+}
1000+
1001+TEST_F (BackbufferTracking, AddOverdrawRegionForLastFrame)
1002+{
1003+ CompRegion all (0, 0, screen.width (), screen.height ());
1004+ roster->dirtyAreaOnCurrentFrame (all);
1005+ roster->incrementFrameAges ();
1006+ roster->incrementFrameAges ();
1007+ roster->overdrawRegionOnPaintingFrame (all);
1008+ EXPECT_EQ (all, roster->damageForFrameAge (2));
1009+}
1010+
1011+TEST_F (BackbufferTracking, TwoFramesAgo)
1012+{
1013+ CompRegion all (0, 0, screen.width (), screen.height ());
1014+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
1015+
1016+ roster->dirtyAreaOnCurrentFrame (all);
1017+ roster->incrementFrameAges ();
1018+ roster->dirtyAreaOnCurrentFrame (topleft);
1019+ roster->incrementFrameAges ();
1020+ EXPECT_EQ (topleft, roster->damageForFrameAge (2));
1021+}
1022+
1023+TEST_F (BackbufferTracking, TwoFramesAgoCulmulative)
1024+{
1025+ CompRegion all (0, 0, screen.width (), screen.height ());
1026+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
1027+ CompRegion topright (0, screen.width () / 2,
1028+ screen.width () / 2,
1029+ screen.height () / 2);
1030+
1031+ roster->dirtyAreaOnCurrentFrame (all);
1032+ roster->incrementFrameAges ();
1033+ roster->dirtyAreaOnCurrentFrame (topleft);
1034+ roster->dirtyAreaOnCurrentFrame (topright);
1035+ roster->incrementFrameAges ();
1036+ EXPECT_EQ (topleft + topright, roster->damageForFrameAge (2));
1037+}
1038+
1039+TEST_F (BackbufferTracking, ThreeFramesAgo)
1040+{
1041+ CompRegion all (0, 0, screen.width (), screen.height ());
1042+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
1043+ CompRegion bottomright (screen.width () / 2,
1044+ screen.height () / 2,
1045+ screen.width () / 2,
1046+ screen.height () / 2);
1047+
1048+ roster->dirtyAreaOnCurrentFrame (all);
1049+ roster->incrementFrameAges ();
1050+ roster->dirtyAreaOnCurrentFrame (topleft);
1051+ roster->incrementFrameAges ();
1052+ roster->dirtyAreaOnCurrentFrame (bottomright);
1053+ roster->incrementFrameAges ();
1054+
1055+ EXPECT_EQ (topleft + bottomright, roster->damageForFrameAge (3));
1056+}
1057+
1058+/* These are more or less functional tests from this point forward
1059+ * just checking a number of different situations */
1060+
1061+TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFrames)
1062+{
1063+ CompRegion all (0, 0, screen.width (), screen.height ());
1064+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
1065+ CompRegion bottomright (screen.width () / 2,
1066+ screen.height () / 2,
1067+ screen.width () / 2,
1068+ screen.height () / 2);
1069+ CompRegion topright (screen.width () / 2,
1070+ 0,
1071+ screen.width () / 2,
1072+ screen.height () / 2);
1073+
1074+ roster->dirtyAreaOnCurrentFrame (all);
1075+ roster->incrementFrameAges ();
1076+ roster->dirtyAreaOnCurrentFrame (topleft);
1077+ roster->incrementFrameAges ();
1078+ roster->dirtyAreaOnCurrentFrame (bottomright);
1079+ roster->incrementFrameAges ();
1080+ roster->dirtyAreaOnCurrentFrame (topright);
1081+ roster->incrementFrameAges ();
1082+
1083+ EXPECT_EQ (topright + bottomright, roster->damageForFrameAge (3));
1084+}
1085+
1086+TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFramesAndOverlap)
1087+{
1088+ CompRegion all (0, 0, screen.width (), screen.height ());
1089+ CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
1090+ CompRegion bottomright (screen.width () / 2,
1091+ screen.height () / 2,
1092+ screen.width () / 2,
1093+ screen.height () / 2);
1094+ CompRegion topright (screen.width () / 2,
1095+ 0,
1096+ screen.width () / 2,
1097+ screen.height () / 2);
1098+
1099+ roster->dirtyAreaOnCurrentFrame (all);
1100+ roster->incrementFrameAges ();
1101+ roster->dirtyAreaOnCurrentFrame (topleft);
1102+ roster->incrementFrameAges ();
1103+ roster->dirtyAreaOnCurrentFrame (bottomright);
1104+ roster->incrementFrameAges ();
1105+ roster->dirtyAreaOnCurrentFrame (bottomright);
1106+ roster->incrementFrameAges ();
1107+
1108+ EXPECT_EQ (bottomright, roster->damageForFrameAge (3));
1109+}
1110+
1111+TEST_F (BackbufferTracking, AllDamageForExceedingMaxTrackedFrames)
1112+{
1113+ CompRegion all (0, 0, screen.width (), screen.height ());
1114+ CompRegion damage (0, 0, 1, 1);
1115+
1116+ roster->dirtyAreaOnCurrentFrame (all);
1117+
1118+ for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES - 1; ++i)
1119+ {
1120+ roster->incrementFrameAges ();
1121+ roster->dirtyAreaOnCurrentFrame (damage);
1122+ }
1123+
1124+ EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES + 1));
1125+}
1126+
1127+TEST_F (BackbufferTracking, DamageForMaxTrackedFrame)
1128+{
1129+ CompRegion all (0, 0, screen.width (), screen.height ());
1130+ CompRegion damage (0, 0, 1, 1);
1131+
1132+ roster->dirtyAreaOnCurrentFrame (all);
1133+
1134+ for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES + 1; ++i)
1135+ {
1136+ roster->incrementFrameAges ();
1137+ roster->dirtyAreaOnCurrentFrame (damage);
1138+ }
1139+
1140+ EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES));
1141+}
1142+
1143+class MockDamageAgeTracking :
1144+ public bt::DamageAgeTracking
1145+{
1146+ public:
1147+
1148+ typedef boost::shared_ptr <MockDamageAgeTracking> Ptr;
1149+
1150+ MOCK_METHOD0 (incrementFrameAges, void ());
1151+ MOCK_METHOD1 (dirtyAreaOnCurrentFrame, void (const CompRegion &));
1152+ MOCK_METHOD1 (subtractObscuredArea, void (const CompRegion &));
1153+ MOCK_METHOD1 (overdrawRegionOnPaintingFrame, void (const CompRegion &));
1154+};
1155+
1156+class AgeingDamageBuffers :
1157+ public ::testing::Test
1158+{
1159+ public:
1160+
1161+ AgeingDamageBuffers ()
1162+ {
1163+ ageing.observe (mockDamageAgeTracker);
1164+ }
1165+
1166+ MockDamageAgeTracking mockDamageAgeTracker;
1167+ bt::AgeingDamageBuffers ageing;
1168+};
1169+
1170+TEST_F (AgeingDamageBuffers, IncrementAgesOnValidRosters)
1171+{
1172+ EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ());
1173+ ageing.incrementAges ();
1174+}
1175+
1176+TEST_F (AgeingDamageBuffers, DirtyAreaOnValidRosters)
1177+{
1178+ CompRegion dirtyArea (100, 100, 100, 100);
1179+ EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (dirtyArea));
1180+ ageing.markAreaDirty (dirtyArea);
1181+}
1182+
1183+TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnValidRosters)
1184+{
1185+ CompRegion obscuredArea (100, 100, 100, 100);
1186+ EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (obscuredArea));
1187+ ageing.subtractObscuredArea (obscuredArea);
1188+}
1189+
1190+TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnValidRosters)
1191+{
1192+ CompRegion overdrawArea (100, 100, 100, 100);
1193+ EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (overdrawArea));
1194+ ageing.markAreaDirtyOnLastFrame (overdrawArea);
1195+}
1196+
1197+TEST_F (AgeingDamageBuffers, IncrementAgesOnInvalidRosters)
1198+{
1199+ EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ()).Times (0);
1200+ ageing.unobserve (mockDamageAgeTracker);
1201+ ageing.incrementAges ();
1202+}
1203+
1204+TEST_F (AgeingDamageBuffers, DirtyAreaOnInvalidRosters)
1205+{
1206+ EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (_)).Times (0);
1207+ ageing.unobserve (mockDamageAgeTracker);
1208+ ageing.markAreaDirty (emptyRegion);
1209+}
1210+
1211+TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnInvalidRosters)
1212+{
1213+ EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (_)).Times (0);
1214+ ageing.unobserve (mockDamageAgeTracker);
1215+ ageing.subtractObscuredArea (emptyRegion);
1216+}
1217+
1218+TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnInvalidRosters)
1219+{
1220+ EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (_)).Times (0);
1221+ ageing.unobserve (mockDamageAgeTracker);
1222+ ageing.markAreaDirtyOnLastFrame (emptyRegion);
1223+}
1224+
1225+
1226
1227=== modified file 'plugins/composite/src/privates.h'
1228--- plugins/composite/src/privates.h 2012-09-20 09:35:40 +0000
1229+++ plugins/composite/src/privates.h 2013-02-28 03:13:24 +0000
1230@@ -36,12 +36,20 @@
1231 #include <map>
1232
1233 #include "pixmapbinding.h"
1234+#include "backbuffertracking.h"
1235 #include "composite_options.h"
1236
1237 extern CompPlugin::VTable *compositeVTable;
1238
1239 extern CompWindow *lastDamagedWindow;
1240
1241+enum DamageTracking
1242+{
1243+ DamageForCurrentFrame = 0,
1244+ DamageForLastFrame = 1,
1245+ DamageFinalPaintRegion
1246+};
1247+
1248 class PrivateCompositeScreen :
1249 ScreenInterface,
1250 public CompositeOptions
1251@@ -66,6 +74,8 @@
1252
1253 void scheduleRepaint ();
1254
1255+ const CompRegion * damageTrackedBuffer (const CompRegion &);
1256+
1257 public:
1258
1259 CompositeScreen *cScreen;
1260@@ -80,10 +90,12 @@
1261 bool randrExtension;
1262 int randrEvent, randrError;
1263
1264- CompRegion damage;
1265+ CompRegion lastFrameDamage;
1266 unsigned long damageMask;
1267
1268- CompRegion tmpRegion;
1269+ CompRegion tmpRegion;
1270+
1271+ DamageTracking currentlyTrackingDamage;
1272
1273 Window overlay;
1274 Window output;
1275@@ -99,6 +111,7 @@
1276 int redrawTime;
1277 int optimalRedrawTime;
1278 bool scheduled, painting, reschedule;
1279+ bool damageRequiresRepaintReschedule;
1280
1281 bool slowAnimations;
1282
1283@@ -115,6 +128,9 @@
1284
1285 /* Map Damage handle to its bounding box */
1286 std::map<Damage, XRectangle> damages;
1287+
1288+ compiz::composite::buffertracking::AgeingDamageBuffers ageingBuffers;
1289+ compiz::composite::buffertracking::FrameRoster roster;
1290 };
1291
1292 class PrivateCompositeWindow :
1293
1294=== modified file 'plugins/composite/src/screen.cpp'
1295--- plugins/composite/src/screen.cpp 2013-01-28 19:22:29 +0000
1296+++ plugins/composite/src/screen.cpp 2013-02-28 03:13:24 +0000
1297@@ -47,6 +47,8 @@
1298
1299 template class WrapableInterface<CompositeScreen, CompositeScreenInterface>;
1300
1301+namespace bt = compiz::composite::buffertracking;
1302+
1303 static const int FALLBACK_REFRESH_RATE = 60; /* if all else fails */
1304
1305 CompWindow *lastDamagedWindow = 0;
1306@@ -276,6 +278,14 @@
1307 delete priv;
1308 }
1309
1310+namespace
1311+{
1312+bool alwaysMarkDirty ()
1313+{
1314+ return true;
1315+}
1316+}
1317+
1318
1319 PrivateCompositeScreen::PrivateCompositeScreen (CompositeScreen *cs) :
1320 cScreen (cs),
1321@@ -294,6 +304,7 @@
1322 randrEvent (0),
1323 randrError (0),
1324 damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK),
1325+ currentlyTrackingDamage (DamageForCurrentFrame),
1326 overlay (None),
1327 output (None),
1328 exposeRects (),
1329@@ -305,12 +316,16 @@
1330 scheduled (false),
1331 painting (false),
1332 reschedule (false),
1333+ damageRequiresRepaintReschedule (true),
1334 slowAnimations (false),
1335 pHnd (NULL),
1336 FPSLimiterMode (CompositeFPSLimiterModeDefault),
1337 withDestroyedWindows (),
1338 cmSnAtom (0),
1339- newCmSnOwner (None)
1340+ newCmSnOwner (None),
1341+ roster (*screen,
1342+ ageingBuffers,
1343+ boost::bind (alwaysMarkDirty))
1344 {
1345 gettimeofday (&lastRedraw, 0);
1346 // wrap outputChangeNotify
1347@@ -491,15 +506,47 @@
1348 return false;
1349 }
1350
1351+const CompRegion *
1352+PrivateCompositeScreen::damageTrackedBuffer (const CompRegion &region)
1353+{
1354+ const CompRegion *currentDamage = NULL;
1355+
1356+ switch (currentlyTrackingDamage)
1357+ {
1358+ case DamageForCurrentFrame:
1359+ currentDamage = &(roster.currentFrameDamage ());
1360+ ageingBuffers.markAreaDirty (region);
1361+ break;
1362+ case DamageForLastFrame:
1363+ currentDamage = &(lastFrameDamage);
1364+ lastFrameDamage += region;
1365+ break;
1366+ case DamageFinalPaintRegion:
1367+ currentDamage = &(tmpRegion);
1368+ tmpRegion += region;
1369+ break;
1370+ default:
1371+ compLogMessage ("composite", CompLogLevelFatal, "unreachable section");
1372+ assert (false);
1373+ abort ();
1374+ }
1375+
1376+ assert (currentDamage);
1377+ return currentDamage;
1378+}
1379+
1380 void
1381 CompositeScreen::damageScreen ()
1382 {
1383+ /* Don't tell plugins about damage events when the damage buffer is already full */
1384 bool alreadyDamaged = priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
1385+ alreadyDamaged |= ((currentDamage () & screen->region ()) == screen->region ());
1386
1387 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
1388 priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
1389
1390- priv->scheduleRepaint ();
1391+ if (priv->damageRequiresRepaintReschedule)
1392+ priv->scheduleRepaint ();
1393
1394 /*
1395 * Call through damageRegion since plugins listening for incoming damage
1396@@ -507,7 +554,15 @@
1397 */
1398
1399 if (!alreadyDamaged)
1400+ {
1401 damageRegion (CompRegion (0, 0, screen->width (), screen->height ()));
1402+
1403+ /* Set the damage region as the fullscreen region, because if
1404+ * windows are unredirected we need to correctly subtract from
1405+ * it later
1406+ */
1407+ priv->damageTrackedBuffer (screen->region ());
1408+ }
1409 }
1410
1411 void
1412@@ -518,7 +573,12 @@
1413 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
1414 return;
1415
1416- priv->damage += region;
1417+ /* Don't cause repaints to be scheduled for empty damage
1418+ * regions */
1419+ if (region.isEmpty ())
1420+ return;
1421+
1422+ const CompRegion *currentDamage = priv->damageTrackedBuffer (region);
1423 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
1424
1425 /* if the number of damage rectangles grows two much between repaints,
1426@@ -526,16 +586,61 @@
1427 in order to make sure we're not having too much overhead, damage
1428 the whole screen if we have a lot of damage rects */
1429
1430- if (priv->damage.numRects () > 100)
1431- damageScreen ();
1432- priv->scheduleRepaint ();
1433+ if (currentDamage->numRects () > 100)
1434+ damageScreen ();
1435+
1436+ if (priv->damageRequiresRepaintReschedule)
1437+ priv->scheduleRepaint ();
1438+}
1439+
1440+void
1441+CompositeScreen::damageCutoff ()
1442+{
1443+ WRAPABLE_HND_FUNCTN (damageCutoff);
1444 }
1445
1446 void
1447 CompositeScreen::damagePending ()
1448 {
1449 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;
1450- priv->scheduleRepaint ();
1451+
1452+ if (priv->damageRequiresRepaintReschedule)
1453+ priv->scheduleRepaint ();
1454+}
1455+
1456+void
1457+CompositeScreen::applyDamageForFrameAge (unsigned int age)
1458+{
1459+ /* Track into "last frame damage" */
1460+ priv->currentlyTrackingDamage = DamageForLastFrame;
1461+ damageRegion (priv->roster.damageForFrameAge (age));
1462+ priv->currentlyTrackingDamage = DamageForCurrentFrame;
1463+}
1464+
1465+unsigned int
1466+CompositeScreen::getFrameAge ()
1467+{
1468+ if (priv->pHnd)
1469+ return priv->pHnd->getFrameAge ();
1470+
1471+ return 1;
1472+}
1473+
1474+void
1475+CompositeScreen::addOverdrawDamageRegion (const CompRegion &r)
1476+{
1477+ priv->ageingBuffers.markAreaDirtyOnLastFrame (r);
1478+}
1479+
1480+typedef CompositeScreen::AreaShouldBeMarkedDirty ShouldMarkDirty;
1481+
1482+CompositeScreen::DamageQuery::Ptr
1483+CompositeScreen::getDamageQuery (const ShouldMarkDirty &callback)
1484+{
1485+ /* No initial damage */
1486+ return bt::FrameRoster::Ptr (new bt::FrameRoster (CompSize (),
1487+ priv->ageingBuffers,
1488+ callback));
1489 }
1490
1491 unsigned int
1492@@ -780,6 +885,10 @@
1493 {
1494 int timeDiff;
1495
1496+ /* Damage that accumulates here does not require a repaint reschedule
1497+ * as it will end up on this frame */
1498+ priv->damageRequiresRepaintReschedule = false;
1499+
1500 if (priv->pHnd)
1501 priv->pHnd->prepareDrawing ();
1502
1503@@ -814,7 +923,7 @@
1504 continue;
1505
1506 if (!CompositeWindow::get (w)->redirected ())
1507- priv->damage -= w->region ();
1508+ priv->ageingBuffers.subtractObscuredArea (w->region ());
1509
1510 break;
1511 }
1512@@ -826,7 +935,13 @@
1513 }
1514 }
1515
1516- priv->tmpRegion = priv->damage & screen->region ();
1517+ /* All further damage is for the next frame now, as
1518+ * priv->tmpRegion will be assigned. Notify plugins that do
1519+ * damage tracking of this */
1520+ damageCutoff ();
1521+
1522+ priv->tmpRegion = (priv->roster.currentFrameDamage () + priv->lastFrameDamage) & screen->region ();
1523+ priv->currentlyTrackingDamage = DamageFinalPaintRegion;
1524
1525 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
1526 {
1527@@ -848,7 +963,9 @@
1528 XSync (dpy, False);
1529 priv->damages.clear ();
1530
1531- priv->damage = CompRegion ();
1532+ /* Any more damage requires a repaint reschedule */
1533+ priv->damageRequiresRepaintReschedule = true;
1534+ priv->lastFrameDamage = CompRegion ();
1535
1536 int mask = priv->damageMask;
1537 priv->damageMask = 0;
1538@@ -864,9 +981,13 @@
1539 else
1540 outputs.push_back (&screen->fullscreenOutput ());
1541
1542+ priv->currentlyTrackingDamage = DamageForCurrentFrame;
1543+
1544+ /* All new damage goes on the next frame */
1545+ priv->ageingBuffers.incrementAges ();
1546+
1547 paint (outputs, mask);
1548
1549-
1550 donePaint ();
1551
1552 priv->outputShapeChanged = false;
1553@@ -1023,8 +1144,12 @@
1554 CompositeScreenInterface::damageRegion (const CompRegion &r)
1555 WRAPABLE_DEF (damageRegion, r);
1556
1557+void
1558+CompositeScreenInterface::damageCutoff ()
1559+ WRAPABLE_DEF (damageCutoff);
1560+
1561 const CompRegion &
1562 CompositeScreen::currentDamage () const
1563 {
1564- return priv->damage;
1565+ return priv->roster.currentFrameDamage ();
1566 }
1567
1568=== modified file 'plugins/composite/src/window.cpp'
1569--- plugins/composite/src/window.cpp 2013-01-03 16:05:26 +0000
1570+++ plugins/composite/src/window.cpp 2013-02-28 03:13:24 +0000
1571@@ -181,7 +181,11 @@
1572 bool
1573 PrivateCompositeWindow::getAttributes (XWindowAttributes &attr)
1574 {
1575- return window->queryFrameAttributes (attr);
1576+ if (XGetWindowAttributes (screen->dpy (),
1577+ ROOTPARENT (window), &attr))
1578+ return true;
1579+
1580+ return false;
1581 }
1582
1583 bool
1584
1585=== modified file 'plugins/kdecompat/src/kdecompat.cpp'
1586--- plugins/kdecompat/src/kdecompat.cpp 2012-08-14 06:33:22 +0000
1587+++ plugins/kdecompat/src/kdecompat.cpp 2013-02-28 03:13:24 +0000
1588@@ -196,7 +196,7 @@
1589 if ((!(ks->optionGetPlasmaThumbnails () || mPreviews.empty ()) &&
1590 !(mSlideData || mSlideData->remaining)) ||
1591 !window->mapNum () ||
1592- (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
1593+ (mask & PAINT_WINDOW_NO_DRAW_MASKS))
1594 {
1595 status = gWindow->glPaint (attrib, transform, region, mask);
1596 return status;
1597@@ -210,7 +210,7 @@
1598 CompRect clipBox (window->x (), window->y (),
1599 window->width (), window->height ());
1600
1601- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
1602+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
1603 return false;
1604
1605 remainder = (float) data->remaining / data->duration;
1606
1607=== modified file 'plugins/move/src/move.cpp'
1608--- plugins/move/src/move.cpp 2013-01-03 16:05:26 +0000
1609+++ plugins/move/src/move.cpp 2013-02-28 03:13:24 +0000
1610@@ -158,14 +158,6 @@
1611 if (mw->gWindow)
1612 mw->gWindow->glPaintSetEnabled (mw, true);
1613 }
1614-
1615- if (ms->optionGetLazyPositioning ())
1616- {
1617- MOVE_WINDOW (w);
1618-
1619- if (mw->gWindow)
1620- mw->releasable = w->obtainLockOnConfigureRequests ();
1621- }
1622 }
1623 }
1624
1625@@ -181,8 +173,6 @@
1626
1627 if (ms->w)
1628 {
1629- MOVE_WINDOW (ms->w);
1630-
1631 if (state & CompAction::StateCancel)
1632 ms->w->move (ms->savedX - ms->w->geometry ().x (),
1633 ms->savedY - ms->w->geometry ().y (), false);
1634@@ -204,14 +194,14 @@
1635
1636 if (ms->moveOpacity != OPAQUE)
1637 {
1638+ MOVE_WINDOW (ms->w);
1639+
1640 if (mw->cWindow)
1641 mw->cWindow->addDamage ();
1642 if (mw->gWindow)
1643 mw->gWindow->glPaintSetEnabled (mw, false);
1644 }
1645
1646- mw->releasable.reset ();
1647-
1648 ms->w = 0;
1649 ms->releaseButton = 0;
1650 }
1651@@ -499,6 +489,9 @@
1652 w->move (wX + dx - w->geometry ().x (),
1653 wY + dy - w->geometry ().y (), false);
1654
1655+ if (!ms->optionGetLazyPositioning ())
1656+ w->syncPosition ();
1657+
1658 ms->x -= dx;
1659 ms->y -= dy;
1660 }
1661
1662=== modified file 'plugins/move/src/move.h'
1663--- plugins/move/src/move.h 2013-01-03 16:05:26 +0000
1664+++ plugins/move/src/move.h 2013-02-28 03:13:24 +0000
1665@@ -27,7 +27,6 @@
1666
1667 #include <core/screen.h>
1668 #include <core/pluginclasshandler.h>
1669-#include <core/configurerequestbuffer.h>
1670
1671 #include <composite/composite.h>
1672 #include <opengl/opengl.h>
1673@@ -118,7 +117,6 @@
1674 CompWindow *window;
1675 GLWindow *gWindow;
1676 CompositeWindow *cWindow;
1677- compiz::window::configure_buffers::Releasable::Ptr releasable;
1678 };
1679
1680 #define MOVE_SCREEN(s) \
1681
1682=== modified file 'plugins/opengl/include/opengl/opengl.h'
1683--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
1684+++ plugins/opengl/include/opengl/opengl.h 2013-02-28 03:13:24 +0000
1685@@ -37,6 +37,13 @@
1686 #else
1687 #include <GL/gl.h>
1688 #include <GL/glx.h>
1689+
1690+/* Some implementations have not yet given a definition
1691+ * to GLX_BACK_BUFFER_AGE_EXT but this is the token as defined
1692+ * in the spec (https://www.opengl.org/registry/specs/EXT/glx_buffer_age.txt)
1693+ */
1694+#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
1695+
1696 #endif
1697
1698 #include <core/size.h>
1699@@ -50,7 +57,7 @@
1700 #include <opengl/programcache.h>
1701 #include <opengl/shadercache.h>
1702
1703-#define COMPIZ_OPENGL_ABI 6
1704+#define COMPIZ_OPENGL_ABI 8
1705
1706 /*
1707 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
1708@@ -525,6 +532,7 @@
1709 extern bool shaders;
1710 extern bool stencilBuffer;
1711 extern GLint maxTextureUnits;
1712+ extern bool bufferAge;
1713
1714 extern bool canDoSaturated;
1715 extern bool canDoSlightlySaturated;
1716@@ -663,6 +671,11 @@
1717 unsigned int mask);
1718
1719 /**
1720+ * Return true if glPaintCompositedOutput is required for this frame
1721+ */
1722+ virtual bool glPaintCompositedOutputRequired ();
1723+
1724+ /**
1725 * Hookable function used by plugins to determine stenciling mask
1726 */
1727 virtual void glBufferStencil (const GLMatrix &matrix,
1728@@ -674,7 +687,7 @@
1729 extern template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>;
1730
1731 class GLScreen :
1732- public WrapableHandler<GLScreenInterface, 8>,
1733+ public WrapableHandler<GLScreenInterface, 9>,
1734 public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>,
1735 public CompOption::Class
1736 {
1737@@ -788,7 +801,9 @@
1738 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
1739 const CompRegion &, GLFramebufferObject *, unsigned int);
1740
1741- WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
1742+ WRAPABLE_HND (7, GLScreenInterface, bool, glPaintCompositedOutputRequired);
1743+
1744+ WRAPABLE_HND (8, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
1745 GLVertexBuffer &,
1746 CompOutput *);
1747
1748
1749=== modified file 'plugins/opengl/src/doublebuffer/src/double-buffer.cpp'
1750--- plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-11-09 06:13:00 +0000
1751+++ plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2013-02-28 03:13:24 +0000
1752@@ -26,6 +26,7 @@
1753
1754 #include <cstdlib>
1755 #include <cassert>
1756+#include <cstdio>
1757 #include "opengl/doublebuffer.h"
1758
1759 using namespace compiz::opengl;
1760@@ -77,9 +78,7 @@
1761
1762 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&
1763 !setting[HAVE_PERSISTENT_BACK_BUFFER])
1764- {
1765 copyFrontToBack ();
1766- }
1767 }
1768 else
1769 {
1770
1771=== modified file 'plugins/opengl/src/framebufferobject.cpp'
1772--- plugins/opengl/src/framebufferobject.cpp 2012-08-06 09:44:49 +0000
1773+++ plugins/opengl/src/framebufferobject.cpp 2013-02-28 03:13:24 +0000
1774@@ -131,7 +131,7 @@
1775
1776 (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,
1777 priv->glTex->target (),
1778- priv->glTex->name (), 0);
1779+ priv->glTex->name (), 0);
1780
1781 priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);
1782
1783
1784=== modified file 'plugins/opengl/src/paint.cpp'
1785--- plugins/opengl/src/paint.cpp 2013-01-03 16:05:26 +0000
1786+++ plugins/opengl/src/paint.cpp 2013-02-28 03:13:24 +0000
1787@@ -418,11 +418,6 @@
1788 if (w->destroyed ())
1789 continue;
1790
1791- gw = GLWindow::get (w);
1792-
1793- /* Release any queued ConfigureWindow requests now */
1794- gw->priv->configureLock->release ();
1795-
1796 if (unredirected.find (w) != unredirected.end ())
1797 continue;
1798
1799@@ -432,6 +427,8 @@
1800 continue;
1801 }
1802
1803+ gw = GLWindow::get (w);
1804+
1805 const CompRegion &clip =
1806 (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ?
1807 gw->clip () : region;
1808@@ -629,8 +626,8 @@
1809 if (mask & PAINT_SCREEN_FULL_MASK)
1810 {
1811 glPaintTransformedOutput (sAttrib, sTransform,
1812- CompRegion (*output), output, mask);
1813-
1814+ CompRegionRef (output->region ()), output, mask);
1815+ priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
1816 return true;
1817 }
1818
1819@@ -660,8 +657,9 @@
1820 }
1821 else if (mask & PAINT_SCREEN_FULL_MASK)
1822 {
1823- glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output),
1824+ glPaintTransformedOutput (sAttrib, sTransform, CompRegionRef (output->region ()),
1825 output, mask);
1826+ priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
1827
1828 return true;
1829 }
1830@@ -671,6 +669,13 @@
1831 }
1832 }
1833
1834+bool
1835+GLScreen::glPaintCompositedOutputRequired ()
1836+{
1837+ WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintCompositedOutputRequired);
1838+ return false;
1839+}
1840+
1841 void
1842 GLScreen::glPaintCompositedOutput (const CompRegion &region,
1843 GLFramebufferObject *fbo,
1844
1845=== modified file 'plugins/opengl/src/privates.h'
1846--- plugins/opengl/src/privates.h 2013-01-03 16:05:26 +0000
1847+++ plugins/opengl/src/privates.h 2013-02-28 03:13:24 +0000
1848@@ -29,11 +29,13 @@
1849 #define _OPENGL_PRIVATES_H
1850
1851 #include <memory>
1852+#include <vector>
1853+#include <tr1/tuple>
1854+#include <boost/shared_ptr.hpp>
1855
1856 #include <composite/composite.h>
1857 #include <opengl/opengl.h>
1858 #include <core/atoms.h>
1859-#include <core/configurerequestbuffer.h>
1860
1861 #ifdef USE_GLES
1862 #include <opengl/framebufferobject.h>
1863@@ -120,8 +122,26 @@
1864 GLTexture::List textures;
1865 };
1866
1867+class FrameProvider
1868+{
1869+ public:
1870+
1871+ typedef boost::shared_ptr <FrameProvider> Ptr;
1872+ typedef std::tr1::tuple <GLFramebufferObject *, int> Frame;
1873+
1874+ virtual ~FrameProvider () {}
1875+
1876+ virtual GLuint getCurrentFrame () = 0;
1877+ virtual void endFrame () = 0;
1878+
1879+ virtual bool providesPersistence () = 0;
1880+ virtual bool alwaysPostprocess () = 0;
1881+ virtual void invalidateAll () = 0;
1882+};
1883+
1884 class PrivateGLScreen :
1885 public ScreenInterface,
1886+ public CompositeScreenInterface,
1887 public compiz::composite::PaintHandler,
1888 public OpenglOptions
1889 {
1890@@ -142,12 +162,17 @@
1891 bool hasVSync ();
1892 bool requiredForcedRefreshRate ();
1893
1894+ unsigned int getFrameAge ();
1895+
1896 void updateRenderMode ();
1897+ void updateFrameProvider ();
1898
1899 void prepareDrawing ();
1900
1901 bool compositingActive ();
1902
1903+ void damageCutoff ();
1904+
1905 void paintBackground (const GLMatrix &transform,
1906 const CompRegion &region,
1907 bool transformed);
1908@@ -163,6 +188,8 @@
1909
1910 bool driverIsBlacklisted (const char *regex) const;
1911
1912+ bool postprocessRequiredForCurrentFrame ();
1913+
1914 public:
1915
1916 GLScreen *gScreen;
1917@@ -197,7 +224,7 @@
1918 GLXDoubleBuffer doubleBuffer;
1919 #endif
1920
1921- GLFramebufferObject *scratchFbo;
1922+ boost::shared_ptr <GLFramebufferObject> scratchFbo;
1923 CompRegion outputRegion;
1924
1925 XRectangle lastViewport;
1926@@ -222,8 +249,10 @@
1927 Pixmap rootPixmapCopy;
1928 CompSize rootPixmapSize;
1929
1930+ FrameProvider::Ptr frameProvider;
1931 const char *glVendor, *glRenderer, *glVersion;
1932
1933+ bool postprocessingRequired;
1934 mutable CompString prevRegex;
1935 mutable bool prevBlacklisted;
1936 };
1937@@ -284,8 +313,6 @@
1938 GLVertexBuffer::AutoProgram *autoProgram;
1939
1940 std::list<GLIcon> icons;
1941-
1942- compiz::window::configure_buffers::Releasable::Ptr configureLock;
1943 };
1944
1945 #endif
1946
1947=== modified file 'plugins/opengl/src/screen.cpp'
1948--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
1949+++ plugins/opengl/src/screen.cpp 2013-02-28 03:13:24 +0000
1950@@ -186,6 +186,7 @@
1951 bool vboEnabled = false;
1952 bool shaders = false;
1953 GLint maxTextureUnits = 1;
1954+ bool bufferAge = false;
1955
1956 bool canDoSaturated = false;
1957 bool canDoSlightlySaturated = false;
1958@@ -301,6 +302,52 @@
1959
1960 #ifndef USE_GLES
1961
1962+class BufferAgeFrameProvider :
1963+ public FrameProvider
1964+{
1965+ public:
1966+
1967+ BufferAgeFrameProvider (Display *disp,
1968+ GLXDrawable drawable) :
1969+ mDisplay (disp),
1970+ mDrawable (drawable)
1971+ {
1972+ }
1973+
1974+ unsigned int getCurrentFrame ()
1975+ {
1976+ unsigned int age = 0;
1977+ (*GL::queryDrawable) (mDisplay,
1978+ mDrawable,
1979+ GLX_BACK_BUFFER_AGE_EXT,
1980+ &age);
1981+ return age;
1982+ }
1983+
1984+ void endFrame ()
1985+ {
1986+ }
1987+
1988+ void invalidateAll ()
1989+ {
1990+ }
1991+
1992+ bool providesPersistence ()
1993+ {
1994+ return true;
1995+ }
1996+
1997+ bool alwaysPostprocess ()
1998+ {
1999+ return false;
2000+ }
2001+
2002+ private:
2003+
2004+ Display *mDisplay;
2005+ GLXDrawable mDrawable;
2006+};
2007+
2008 namespace compiz
2009 {
2010 namespace opengl
2011@@ -358,6 +405,137 @@
2012
2013 #endif
2014
2015+class UndefinedFrameProvider :
2016+ public FrameProvider
2017+{
2018+ public:
2019+
2020+ unsigned int getCurrentFrame ()
2021+ {
2022+ return 0;
2023+ }
2024+
2025+ void endFrame ()
2026+ {
2027+ }
2028+
2029+ void invalidateAll ()
2030+ {
2031+ }
2032+
2033+ bool providesPersistence ()
2034+ {
2035+ return false;
2036+ }
2037+
2038+ bool alwaysPostprocess ()
2039+ {
2040+ return false;
2041+ }
2042+};
2043+
2044+class PostprocessFrameProvider :
2045+ public FrameProvider
2046+{
2047+ public:
2048+
2049+ PostprocessFrameProvider (GLFramebufferObject *object) :
2050+ mObject (object),
2051+ mAge (0)
2052+ {
2053+ }
2054+
2055+ unsigned int getCurrentFrame ()
2056+ {
2057+ /* We are now using this buffer, reset
2058+ * age back to zero */
2059+ unsigned int lastAge = mAge;
2060+ mAge = 0;
2061+
2062+ return lastAge;
2063+ }
2064+
2065+ void endFrame ()
2066+ {
2067+ ++mAge;
2068+ }
2069+
2070+ void invalidateAll ()
2071+ {
2072+ mAge = 0;
2073+ }
2074+
2075+ bool providesPersistence ()
2076+ {
2077+ return true;
2078+ }
2079+
2080+ bool alwaysPostprocess ()
2081+ {
2082+ return true;
2083+ }
2084+
2085+ private:
2086+
2087+ GLFramebufferObject *mObject;
2088+ unsigned int mAge;
2089+};
2090+
2091+class OptionalPostprocessFrameProvider :
2092+ public FrameProvider
2093+{
2094+ public:
2095+
2096+ typedef boost::function <bool ()> PostprocessRequired;
2097+
2098+ OptionalPostprocessFrameProvider (const FrameProvider::Ptr &backbuffer,
2099+ const FrameProvider::Ptr &scratchbuffer,
2100+ const PostprocessRequired &ppRequired) :
2101+ mBackbuffer (backbuffer),
2102+ mScratchbuffer (scratchbuffer),
2103+ mPPRequired (ppRequired)
2104+ {
2105+ }
2106+
2107+ unsigned int getCurrentFrame ()
2108+ {
2109+ if (mPPRequired ())
2110+ return mScratchbuffer->getCurrentFrame ();
2111+ else
2112+ return mBackbuffer->getCurrentFrame ();
2113+ }
2114+
2115+ void endFrame ()
2116+ {
2117+ mScratchbuffer->endFrame ();
2118+ }
2119+
2120+ void invalidateAll ()
2121+ {
2122+ mScratchbuffer->invalidateAll ();
2123+ }
2124+
2125+ bool providesPersistence ()
2126+ {
2127+ /* We are only as good as the backbuffer is */
2128+ return mBackbuffer->providesPersistence ();
2129+ }
2130+
2131+ bool alwaysPostprocess ()
2132+ {
2133+ if (mPPRequired ())
2134+ return mScratchbuffer->alwaysPostprocess ();
2135+ else
2136+ return mBackbuffer->alwaysPostprocess ();
2137+ }
2138+
2139+ private:
2140+
2141+ FrameProvider::Ptr mBackbuffer;
2142+ FrameProvider::Ptr mScratchbuffer;
2143+ PostprocessRequired mPPRequired;
2144+};
2145+
2146 bool
2147 GLScreen::glInitContext (XVisualInfo *visinfo)
2148 {
2149@@ -593,6 +771,8 @@
2150
2151 priv->incorrectRefreshRate = false;
2152
2153+ priv->frameProvider.reset (new PostprocessFrameProvider ());
2154+
2155 #else
2156
2157 Display *dpy = screen->dpy ();
2158@@ -899,12 +1079,17 @@
2159
2160 if (GL::fboSupported)
2161 {
2162- priv->scratchFbo = new GLFramebufferObject;
2163+ priv->scratchFbo.reset (new GLFramebufferObject ());
2164 priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
2165 }
2166
2167 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
2168
2169+ /* We need scratchFbo to be set before doing this, and it is common
2170+ * to both the GLES and non-GLES codepaths, so using another #ifdef
2171+ */
2172+ priv->updateFrameProvider ();
2173+
2174 return true;
2175 }
2176
2177@@ -993,6 +1178,13 @@
2178 return;
2179 }
2180
2181+ if (strstr (glxExtensions, "GLX_EXT_buffer_age"))
2182+ {
2183+ compLogMessage ("opengl", CompLogLevelInfo,
2184+ "GLX_EXT_buffer_age is supported");
2185+ GL::bufferAge = true;
2186+ }
2187+
2188 priv->getProcAddress = (GL::GLXGetProcAddressProc)
2189 getProcAddress ("glXGetProcAddressARB");
2190 GL::bindTexImage = (GL::GLXBindTexImageProc)
2191@@ -1209,9 +1401,6 @@
2192 glXDestroyContext (screen->dpy (), priv->ctx);
2193 #endif
2194
2195- if (priv->scratchFbo)
2196- delete priv->scratchFbo;
2197-
2198 delete priv;
2199 }
2200
2201@@ -1233,7 +1422,7 @@
2202 ctx (EGL_NO_CONTEXT),
2203 doubleBuffer (screen->dpy (), *screen, surface),
2204 #endif
2205- scratchFbo (NULL),
2206+ scratchFbo (),
2207 outputRegion (),
2208 refreshSubBuffer (false),
2209 lastMask (0),
2210@@ -1246,13 +1435,16 @@
2211 autoProgram (new GLScreenAutoProgram(gs)),
2212 rootPixmapCopy (None),
2213 rootPixmapSize (),
2214+ frameProvider (),
2215 glVendor (NULL),
2216 glRenderer (NULL),
2217 glVersion (NULL),
2218+ postprocessingRequired (false),
2219 prevRegex (),
2220 prevBlacklisted (false)
2221 {
2222 ScreenInterface::setHandler (screen);
2223+ CompositeScreenInterface::setHandler (cScreen);
2224 }
2225
2226 PrivateGLScreen::~PrivateGLScreen ()
2227@@ -1443,8 +1635,11 @@
2228 {
2229 screen->outputChangeNotify ();
2230
2231+ frameProvider->invalidateAll ();
2232+
2233 if (scratchFbo)
2234 scratchFbo->allocate (*screen, NULL, GL_BGRA);
2235+
2236 updateView ();
2237 }
2238
2239@@ -1669,6 +1864,10 @@
2240 GLScreenInterface::projectionMatrix ()
2241 WRAPABLE_DEF (projectionMatrix)
2242
2243+bool
2244+GLScreenInterface::glPaintCompositedOutputRequired ()
2245+ WRAPABLE_DEF (glPaintCompositedOutputRequired)
2246+
2247 void
2248 GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
2249 GLFramebufferObject *fbo,
2250@@ -1977,18 +2176,6 @@
2251 glDepthMask (GL_FALSE);
2252 glStencilMask (0);
2253
2254- GLFramebufferObject *oldFbo = NULL;
2255- bool useFbo = false;
2256-
2257- /* Clear the color buffer where appropriate */
2258- if (GL::fboEnabled && scratchFbo)
2259- {
2260- oldFbo = scratchFbo->bind ();
2261- useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
2262- if (!useFbo)
2263- GLFramebufferObject::rebind (oldFbo);
2264- }
2265-
2266 #ifdef UNSAFE_ARM_SGX_FIXME
2267 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2268 !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2269@@ -2006,8 +2193,21 @@
2270 }
2271 #endif
2272
2273- CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2274- screen->region () : region;
2275+ CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2276+ screen->region () : region);
2277+ bool useFbo = false;
2278+ GLFramebufferObject *oldFbo = NULL;
2279+
2280+ postprocessingRequired = gScreen->glPaintCompositedOutputRequired ();
2281+ postprocessingRequired |= frameProvider->alwaysPostprocess ();
2282+
2283+ /* Clear the color buffer where appropriate */
2284+ if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ()))
2285+ {
2286+ oldFbo = scratchFbo->bind ();
2287+ if (scratchFbo->checkStatus ())
2288+ useFbo = true;
2289+ }
2290
2291 foreach (CompOutput *output, outputs)
2292 {
2293@@ -2034,7 +2234,8 @@
2294
2295 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2296 identity,
2297- CompRegion (*output), output,
2298+ CompRegion (*output),
2299+ output,
2300 PAINT_SCREEN_REGION_MASK |
2301 PAINT_SCREEN_FULL_MASK);
2302 }
2303@@ -2057,7 +2258,9 @@
2304 tmpRegion = CompRegion (*output);
2305 #endif
2306
2307- outputRegion = tmpRegion & CompRegion (*output);
2308+ /* Clip current paint region to output extents */
2309+ CompRegionRef wholeOutput (output->region ());
2310+ outputRegion = (paintRegion & wholeOutput);
2311
2312 if (!gScreen->glPaintOutput (defaultScreenPaintAttrib,
2313 identity,
2314@@ -2068,10 +2271,11 @@
2315
2316 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2317 identity,
2318- CompRegion (*output), output,
2319+ wholeOutput, output,
2320 PAINT_SCREEN_FULL_MASK);
2321
2322- tmpRegion += *output;
2323+ paintRegion += wholeOutput;
2324+ cScreen->addOverdrawDamageRegion (wholeOutput);
2325 }
2326 }
2327 }
2328@@ -2082,13 +2286,18 @@
2329
2330 if (useFbo)
2331 {
2332- GLFramebufferObject::rebind (oldFbo);
2333-
2334 // FIXME: does not work if screen dimensions exceed max texture size
2335 // We should try to use glBlitFramebuffer instead.
2336- gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);
2337+ GLFramebufferObject::rebind (oldFbo);
2338+ /* If we must always postprocess, then we don't have any
2339+ * "real" backbuffer persistence, redraw the whole thing */
2340+ gScreen->glPaintCompositedOutput (frameProvider->alwaysPostprocess () ?
2341+ screen->region () :
2342+ paintRegion, scratchFbo.get (), mask);
2343 }
2344
2345+ frameProvider->endFrame ();
2346+
2347 if (cScreen->outputWindowChanged ())
2348 {
2349 /*
2350@@ -2100,20 +2309,27 @@
2351 return;
2352 }
2353
2354+ bool persistence = frameProvider->providesPersistence ();
2355 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2356- bool fullscreen = useFbo ||
2357+ bool fullscreen = persistence ||
2358 alwaysSwap ||
2359 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2360 commonFrontbuffer);
2361
2362 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2363- doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
2364+ doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, persistence);
2365 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2366- doubleBuffer.render (tmpRegion, fullscreen);
2367+ doubleBuffer.render (paintRegion, fullscreen);
2368
2369 lastMask = mask;
2370 }
2371
2372+unsigned int
2373+PrivateGLScreen::getFrameAge ()
2374+{
2375+ return frameProvider->getCurrentFrame ();
2376+}
2377+
2378 bool
2379 PrivateGLScreen::hasVSync ()
2380 {
2381@@ -2138,6 +2354,13 @@
2382 }
2383
2384 void
2385+PrivateGLScreen::damageCutoff ()
2386+{
2387+ cScreen->applyDamageForFrameAge (frameProvider->getCurrentFrame ());
2388+ cScreen->damageCutoff ();
2389+}
2390+
2391+void
2392 PrivateGLScreen::updateRenderMode ()
2393 {
2394 #ifndef USE_GLES
2395@@ -2147,12 +2370,54 @@
2396 }
2397
2398 void
2399+PrivateGLScreen::updateFrameProvider ()
2400+{
2401+#ifndef USE_GLES
2402+ const Window outputWindow = CompositeScreen::get (screen)->output ();
2403+
2404+ if (GL::fboEnabled)
2405+ {
2406+ if (GL::bufferAge)
2407+ {
2408+ FrameProvider::Ptr back (new BufferAgeFrameProvider (screen->dpy (),
2409+ outputWindow));
2410+ FrameProvider::Ptr scratch (new PostprocessFrameProvider (scratchFbo.get ()));
2411+ OptionalPostprocessFrameProvider::PostprocessRequired ppReq
2412+ (boost::bind (&PrivateGLScreen::postprocessRequiredForCurrentFrame,
2413+ this));
2414+ frameProvider.reset (new OptionalPostprocessFrameProvider (back,
2415+ scratch,
2416+ ppReq));
2417+ }
2418+ else
2419+ {
2420+ /* Prefer using FBO's instead of switching between a defined/undefined backbuffer */
2421+ frameProvider.reset (new PostprocessFrameProvider (scratchFbo.get ()));
2422+ }
2423+ }
2424+ else
2425+ {
2426+ if (GL::bufferAge)
2427+ frameProvider.reset (new BufferAgeFrameProvider (screen->dpy (),
2428+ outputWindow));
2429+ else
2430+ frameProvider.reset (new UndefinedFrameProvider ());
2431+ }
2432+#else
2433+ frameProvider.reset (new PostprocessFrameProvider (scratchFbo.get ()));
2434+#endif
2435+}
2436+
2437+void
2438 PrivateGLScreen::prepareDrawing ()
2439 {
2440 bool wasFboEnabled = GL::fboEnabled;
2441 updateRenderMode ();
2442 if (wasFboEnabled != GL::fboEnabled)
2443+ {
2444+ updateFrameProvider ();
2445 CompositeScreen::get (screen)->damageScreen ();
2446+ }
2447 }
2448
2449 bool
2450@@ -2170,6 +2435,12 @@
2451 return prevBlacklisted;
2452 }
2453
2454+bool
2455+PrivateGLScreen::postprocessRequiredForCurrentFrame ()
2456+{
2457+ return postprocessingRequired;
2458+}
2459+
2460 GLTexture::BindPixmapHandle
2461 GLScreen::registerBindPixmap (GLTexture::BindPixmapProc proc)
2462 {
2463@@ -2198,7 +2469,7 @@
2464 GLFramebufferObject *
2465 GLScreen::fbo ()
2466 {
2467- return priv->scratchFbo;
2468+ return priv->scratchFbo.get ();
2469 }
2470
2471 GLTexture *
2472
2473=== modified file 'plugins/opengl/src/window.cpp'
2474--- plugins/opengl/src/window.cpp 2013-01-03 16:05:26 +0000
2475+++ plugins/opengl/src/window.cpp 2013-02-28 03:13:24 +0000
2476@@ -86,8 +86,7 @@
2477 bindFailed (false),
2478 vertexBuffer (new GLVertexBuffer ()),
2479 autoProgram(new GLWindowAutoProgram(this)),
2480- icons (),
2481- configureLock (w->obtainLockOnConfigureRequests ())
2482+ icons ()
2483 {
2484 paint.xScale = 1.0f;
2485 paint.yScale = 1.0f;
2486
2487=== modified file 'plugins/resize/src/resize.cpp'
2488--- plugins/resize/src/resize.cpp 2012-10-19 09:23:11 +0000
2489+++ plugins/resize/src/resize.cpp 2013-02-28 03:13:24 +0000
2490@@ -257,7 +257,7 @@
2491 float xScale, yScale;
2492 int x, y;
2493
2494- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2495+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2496 return false;
2497
2498 status = gWindow->glPaint (attrib, transform, region,
2499
2500=== modified file 'plugins/ring/src/ring.cpp'
2501--- plugins/ring/src/ring.cpp 2013-01-19 11:47:22 +0000
2502+++ plugins/ring/src/ring.cpp 2013-02-28 03:13:24 +0000
2503@@ -264,7 +264,7 @@
2504 GLWindowPaintAttrib wAttrib (gWindow->lastPaintAttrib ());
2505 GLMatrix wTransform = transform;
2506
2507- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2508+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2509 return false;
2510
2511 if (mSlot)
2512
2513=== modified file 'plugins/scale/src/scale.cpp'
2514--- plugins/scale/src/scale.cpp 2013-01-29 23:16:32 +0000
2515+++ plugins/scale/src/scale.cpp 2013-02-28 03:13:24 +0000
2516@@ -384,12 +384,14 @@
2517
2518 status = gWindow->glPaint (sAttrib, transform, region, mask);
2519
2520+ mask &= ~(PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
2521+
2522 if (scaled)
2523 {
2524 GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());
2525 GLMatrix wTransform (transform);
2526
2527- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2528+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
2529 return false;
2530
2531 if (window->alpha () || lastAttrib.opacity != OPAQUE)
2532
2533=== modified file 'plugins/staticswitcher/src/staticswitcher.cpp'
2534--- plugins/staticswitcher/src/staticswitcher.cpp 2012-12-10 03:28:47 +0000
2535+++ plugins/staticswitcher/src/staticswitcher.cpp 2013-02-28 03:13:24 +0000
2536@@ -1246,7 +1246,7 @@
2537
2538 const CompWindow::Geometry &g = window->geometry ();
2539
2540- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
2541+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
2542 sScreen->ignoreSwitcher)
2543 return false;
2544
2545
2546=== modified file 'plugins/switcher/src/switcher.cpp'
2547--- plugins/switcher/src/switcher.cpp 2012-12-10 03:28:47 +0000
2548+++ plugins/switcher/src/switcher.cpp 2013-02-28 03:13:24 +0000
2549@@ -971,7 +971,7 @@
2550
2551 const CompWindow::Geometry &g = window->geometry ();
2552
2553- if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||
2554+ if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
2555 sScreen->ignoreSwitcher)
2556 return false;
2557
2558
2559=== modified file 'plugins/td/src/3d.cpp'
2560--- plugins/td/src/3d.cpp 2013-02-03 17:50:59 +0000
2561+++ plugins/td/src/3d.cpp 2013-02-28 03:13:24 +0000
2562@@ -163,7 +163,7 @@
2563 glGetIntegerv (GL_CULL_FACE_MODE, &cull);
2564 cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;
2565
2566- if (ww && wh && !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) &&
2567+ if (ww && wh && !(mask & PAINT_WINDOW_NO_DRAW_MASKS) &&
2568 ((cs->paintOrder () == FTB && mFtb) ||
2569 (cs->paintOrder () == BTF && !mFtb)))
2570 {
2571
2572=== modified file 'plugins/water/src/water.cpp'
2573--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
2574+++ plugins/water/src/water.cpp 2013-02-28 03:13:24 +0000
2575@@ -317,6 +317,12 @@
2576 }
2577 }
2578
2579+bool
2580+WaterScreen::glPaintCompositedOutputRequired ()
2581+{
2582+ return true;
2583+}
2584+
2585 void
2586 WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2587 GLFramebufferObject *fbo,
2588@@ -467,6 +473,7 @@
2589 cScreen->preparePaintSetEnabled (this, false);
2590 gScreen->glPaintOutputSetEnabled (this, false);
2591 gScreen->glPaintCompositedOutputSetEnabled (this, false);
2592+ gScreen->glPaintCompositedOutputRequiredSetEnabled (this, false);
2593 cScreen->donePaintSetEnabled (this, false);
2594 }
2595
2596
2597=== modified file 'plugins/water/src/water.h'
2598--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
2599+++ plugins/water/src/water.h 2013-02-28 03:13:24 +0000
2600@@ -64,6 +64,7 @@
2601
2602 void handleEvent (XEvent *);
2603
2604+ bool glPaintCompositedOutputRequired ();
2605 void glPaintCompositedOutput (const CompRegion &region,
2606 GLFramebufferObject *fbo,
2607 unsigned int mask);
2608
2609=== modified file 'src/CMakeLists.txt'
2610--- src/CMakeLists.txt 2013-01-03 16:05:26 +0000
2611+++ src/CMakeLists.txt 2013-02-28 03:13:24 +0000
2612@@ -160,12 +160,6 @@
2613 compiz_window_geometry
2614 )
2615
2616-add_library (compiz_configurerequestbuffer STATIC
2617- configurerequestbuffer.cpp)
2618-
2619-target_link_libraries (compiz_configurerequestbuffer
2620- compiz_window_geometry)
2621-
2622 # workaround for build race
2623 add_dependencies (compiz core-xml-file)
2624
2625@@ -198,7 +192,6 @@
2626 compiz_servergrab
2627 compiz_output
2628 compiz_outputdevices
2629- compiz_configurerequestbuffer
2630 -Wl,-no-whole-archive
2631 # ${CORE_MOD_LIBRARIES}
2632 )
2633
2634=== removed file 'src/asyncserverwindow.h'
2635--- src/asyncserverwindow.h 2012-12-13 11:12:32 +0000
2636+++ src/asyncserverwindow.h 1970-01-01 00:00:00 +0000
2637@@ -1,52 +0,0 @@
2638-/*
2639- * Copyright © 2012 Sam Spilsbury
2640- *
2641- * Permission to use, copy, modify, distribute, and sell this software
2642- * and its documentation for any purpose is hereby granted without
2643- * fee, provided that the above copyright notice appear in all copies
2644- * and that both that copyright notice and this permission notice
2645- * appear in supporting documentation, and that the name of
2646- * Canonical Ltd. not be used in advertising or publicity pertaining to
2647- * distribution of the software without specific, written prior permission.
2648- * Canonical Ltd. makes no representations about the suitability of this
2649- * software for any purpose. It is provided "as is" without express or
2650- * implied warranty.
2651- *
2652- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2653- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2654- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2655- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2656- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2657- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2658- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2659- *
2660- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2661- */
2662-#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H
2663-#define _COMPIZ_ASYNC_SERVER_WINDOW_H
2664-
2665-#include <X11/Xlib.h>
2666-
2667-namespace compiz
2668-{
2669-namespace window
2670-{
2671-class AsyncServerWindow
2672-{
2673- public:
2674-
2675- virtual ~AsyncServerWindow () {};
2676-
2677- virtual int requestConfigureOnClient (const XWindowChanges &xwc,
2678- unsigned int valueMask) = 0;
2679- virtual int requestConfigureOnWrapper (const XWindowChanges &xwc,
2680- unsigned int valueMask) = 0;
2681- virtual int requestConfigureOnFrame (const XWindowChanges &xwc,
2682- unsigned int valueMask) = 0;
2683- virtual void sendSyntheticConfigureNotify () = 0;
2684- virtual bool hasCustomShape () const = 0;
2685-};
2686-}
2687-}
2688-
2689-#endif
2690
2691=== removed file 'src/configurerequestbuffer-impl.h'
2692--- src/configurerequestbuffer-impl.h 2012-12-13 11:12:32 +0000
2693+++ src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000
2694@@ -1,145 +0,0 @@
2695-/*
2696- * Copyright © 2012 Sam Spilsbury
2697- *
2698- * Permission to use, copy, modify, distribute, and sell this software
2699- * and its documentation for any purpose is hereby granted without
2700- * fee, provided that the above copyright notice appear in all copies
2701- * and that both that copyright notice and this permission notice
2702- * appear in supporting documentation, and that the name of
2703- * Canonical Ltd. not be used in advertising or publicity pertaining to
2704- * distribution of the software without specific, written prior permission.
2705- * Canonical Ltd. makes no representations about the suitability of this
2706- * software for any purpose. It is provided "as is" without express or
2707- * implied warranty.
2708- *
2709- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2710- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2711- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2712- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2713- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2714- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2715- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2716- *
2717- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2718- */
2719-#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
2720-#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
2721-
2722-#include <memory>
2723-#include <vector>
2724-#include <boost/weak_ptr.hpp>
2725-#include <boost/shared_ptr.hpp>
2726-#include <boost/function.hpp>
2727-#include <X11/Xlib.h>
2728-
2729-#include <core/configurerequestbuffer.h>
2730-
2731-namespace compiz
2732-{
2733-namespace window
2734-{
2735-class AsyncServerWindow;
2736-namespace configure_buffers
2737-{
2738-
2739-class Lockable
2740-{
2741- public:
2742-
2743- typedef boost::shared_ptr <Lockable> Ptr;
2744- typedef boost::weak_ptr <Lockable> Weak;
2745-
2746- virtual ~Lockable () {}
2747-
2748- virtual void lock () = 0;
2749-};
2750-
2751-class BufferLock :
2752- public Lockable,
2753- public Releasable
2754-{
2755- public:
2756- typedef boost::shared_ptr <BufferLock> Ptr;
2757-
2758- virtual ~BufferLock () {}
2759-};
2760-
2761-class CountedFreeze
2762-{
2763- public:
2764-
2765- virtual ~CountedFreeze () {}
2766-
2767- virtual void freeze () = 0;
2768- virtual void release () = 0;
2769-
2770- virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0;
2771-};
2772-
2773-class ConfigureRequestBuffer :
2774- public CountedFreeze,
2775- public Buffer
2776-{
2777- public:
2778-
2779- typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory;
2780-
2781- void freeze ();
2782- void release ();
2783-
2784- void untrackLock (compiz::window::configure_buffers::BufferLock *lock);
2785-
2786- void pushClientRequest (const XWindowChanges &xwc, unsigned int mask);
2787- void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask);
2788- void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask);
2789- void pushSyntheticConfigureNotify ();
2790- compiz::window::configure_buffers::Releasable::Ptr obtainLock ();
2791-
2792- /* Implement getAttributes and require that
2793- * the queue is released before calling through
2794- * to the SyncServerWindow */
2795- bool queryAttributes (XWindowAttributes &attrib);
2796- bool queryFrameAttributes (XWindowAttributes &attrib);
2797- XRectangle * queryShapeRectangles (int kind,
2798- int *count,
2799- int *ordering);
2800-
2801- void forceRelease ();
2802-
2803- static compiz::window::configure_buffers::Buffer::Ptr
2804- Create (AsyncServerWindow *asyncServerWindow,
2805- SyncServerWindow *syncServerWindow,
2806- const LockFactory &factory);
2807-
2808- private:
2809-
2810- ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
2811- SyncServerWindow *syncServerWindow,
2812- const LockFactory &factory);
2813-
2814- class Private;
2815- std::auto_ptr <Private> priv;
2816-};
2817-
2818-class ConfigureBufferLock :
2819- public compiz::window::configure_buffers::BufferLock
2820-{
2821- public:
2822-
2823- typedef boost::shared_ptr <ConfigureBufferLock> Ptr;
2824-
2825- ConfigureBufferLock (CountedFreeze *);
2826- ~ConfigureBufferLock ();
2827-
2828- void lock ();
2829- void release ();
2830-
2831- private:
2832-
2833- class Private;
2834- std::auto_ptr <Private> priv;
2835-};
2836-}
2837-}
2838-}
2839-#endif
2840
2841=== removed file 'src/configurerequestbuffer.cpp'
2842--- src/configurerequestbuffer.cpp 2013-02-14 12:12:53 +0000
2843+++ src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
2844@@ -1,363 +0,0 @@
2845-/*
2846- * Copyright © 2012 Sam Spilsbury
2847- *
2848- * Permission to use, copy, modify, distribute, and sell this software
2849- * and its documentation for any purpose is hereby granted without
2850- * fee, provided that the above copyright notice appear in all copies
2851- * and that both that copyright notice and this permission notice
2852- * appear in supporting documentation, and that the name of
2853- * Canonical Ltd. not be used in advertising or publicity pertaining to
2854- * distribution of the software without specific, written prior permission.
2855- * Canonical Ltd. makes no representations about the suitability of this
2856- * software for any purpose. It is provided "as is" without express or
2857- * implied warranty.
2858- *
2859- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2860- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2861- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2862- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2863- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2864- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2865- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2866- *
2867- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2868- */
2869-#include <cstdio>
2870-#include <cassert>
2871-#include <boost/foreach.hpp>
2872-#include <boost/weak_ptr.hpp>
2873-#include <boost/bind.hpp>
2874-#include "asyncserverwindow.h"
2875-#include "configurerequestbuffer-impl.h"
2876-
2877-#ifndef foreach
2878-#define foreach BOOST_FOREACH
2879-#endif
2880-
2881-namespace crb = compiz::window::configure_buffers;
2882-namespace cw = compiz::window;
2883-
2884-class crb::ConfigureRequestBuffer::Private
2885-{
2886- public:
2887-
2888- typedef crb::Lockable::Weak LockObserver;
2889-
2890- Private (cw::AsyncServerWindow *asyncServerWindow,
2891- cw::SyncServerWindow *syncServerWindow,
2892- const crb::ConfigureRequestBuffer::LockFactory &lockFactory) :
2893- clientChangeMask (0),
2894- wrapperChangeMask (0),
2895- frameChangeMask (0),
2896- sendSyntheticConfigure (false),
2897- lockCount (0),
2898- asyncServerWindow (asyncServerWindow),
2899- syncServerWindow (syncServerWindow),
2900- lockFactory (lockFactory)
2901- {
2902- }
2903-
2904- void dispatchConfigure (bool force = false);
2905-
2906- XWindowChanges clientChanges;
2907- unsigned int clientChangeMask;
2908-
2909- XWindowChanges wrapperChanges;
2910- unsigned int wrapperChangeMask;
2911-
2912- XWindowChanges frameChanges;
2913- unsigned int frameChangeMask;
2914-
2915- bool sendSyntheticConfigure;
2916-
2917- unsigned int lockCount;
2918-
2919- cw::AsyncServerWindow *asyncServerWindow;
2920- cw::SyncServerWindow *syncServerWindow;
2921-
2922- crb::ConfigureRequestBuffer::LockFactory lockFactory;
2923- std::vector <LockObserver> locks;
2924-};
2925-
2926-void
2927-crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force)
2928-{
2929- const unsigned int allEventMasks = 0x7f;
2930- bool immediate = frameChangeMask & (CWStackMode | CWSibling);
2931-
2932- /* This is a stop-gap solution for not having a plugin API to
2933- * query the window shape. Once we have that, we can safely
2934- * remove these and require the queue to be unlocked when that
2935- * happens. Its a separate unit of work for improving resize
2936- * performance anyways.
2937- */
2938- immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth));
2939- immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
2940- immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
2941- immediate |= force;
2942-
2943- bool clientDispatch = (clientChangeMask & allEventMasks);
2944- bool wrapperDispatch = (wrapperChangeMask & allEventMasks);
2945- bool frameDispatch = (frameChangeMask & allEventMasks);
2946-
2947- bool dispatch = !lockCount && (clientDispatch ||
2948- wrapperDispatch ||
2949- frameDispatch ||
2950- sendSyntheticConfigure);
2951-
2952- if (dispatch || immediate)
2953- {
2954- if (frameDispatch)
2955- {
2956- asyncServerWindow->requestConfigureOnFrame (frameChanges,
2957- frameChangeMask);
2958- frameChangeMask = 0;
2959- }
2960-
2961- if (wrapperDispatch)
2962- {
2963- asyncServerWindow->requestConfigureOnWrapper (wrapperChanges,
2964- wrapperChangeMask);
2965- wrapperChangeMask = 0;
2966- }
2967-
2968- if (clientDispatch)
2969- {
2970- asyncServerWindow->requestConfigureOnClient (clientChanges,
2971- clientChangeMask);
2972- clientChangeMask = 0;
2973- }
2974-
2975- if (sendSyntheticConfigure)
2976- {
2977- asyncServerWindow->sendSyntheticConfigureNotify ();
2978- sendSyntheticConfigure = false;
2979- }
2980-
2981- foreach (const LockObserver &lock, locks)
2982- {
2983- crb::Lockable::Ptr strongLock (lock.lock ());
2984-
2985- /* We might be in a lock's destructor so check
2986- * if this can really be re-locked, if not, its
2987- * no big deal as the lock is going away anyways
2988- */
2989- if (strongLock)
2990- strongLock->lock ();
2991- }
2992- }
2993-}
2994-
2995-void
2996-crb::ConfigureRequestBuffer::freeze ()
2997-{
2998- priv->lockCount++;
2999-
3000- assert (priv->lockCount <= priv->locks.size ());
3001-}
3002-
3003-void
3004-crb::ConfigureRequestBuffer::release ()
3005-{
3006- assert (priv->lockCount);
3007-
3008- priv->lockCount--;
3009-
3010- priv->dispatchConfigure ();
3011-}
3012-
3013-namespace
3014-{
3015-void applyChangeToXWC (const XWindowChanges &from,
3016- XWindowChanges &to,
3017- unsigned int mask)
3018-{
3019- if (mask & CWX)
3020- to.x = from.x;
3021-
3022- if (mask & CWY)
3023- to.y = from.y;
3024-
3025- if (mask & CWWidth)
3026- to.width = from.width;
3027-
3028- if (mask & CWHeight)
3029- to.height = from.height;
3030-
3031- if (mask & CWBorderWidth)
3032- to.border_width = from.border_width;
3033-
3034- if (mask & CWSibling)
3035- to.sibling = from.sibling;
3036-
3037- if (mask & CWStackMode)
3038- to.stack_mode = from.stack_mode;
3039-}
3040-}
3041-
3042-void
3043-crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc,
3044- unsigned int mask)
3045-{
3046- applyChangeToXWC (xwc, priv->clientChanges, mask);
3047- priv->clientChangeMask |= mask;
3048-
3049- priv->dispatchConfigure ();
3050-}
3051-
3052-void
3053-crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc,
3054- unsigned int mask)
3055-{
3056- applyChangeToXWC (xwc, priv->wrapperChanges, mask);
3057- priv->wrapperChangeMask |= mask;
3058-
3059- priv->dispatchConfigure ();
3060-}
3061-
3062-void
3063-crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc,
3064- unsigned int mask)
3065-{
3066- applyChangeToXWC (xwc, priv->frameChanges, mask);
3067- priv->frameChangeMask |= mask;
3068-
3069- priv->dispatchConfigure ();
3070-}
3071-
3072-void
3073-crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify ()
3074-{
3075- priv->sendSyntheticConfigure = true;
3076-
3077- priv->dispatchConfigure ();
3078-}
3079-
3080-crb::Releasable::Ptr
3081-crb::ConfigureRequestBuffer::obtainLock ()
3082-{
3083- crb::BufferLock::Ptr lock (priv->lockFactory (this));
3084-
3085- priv->locks.push_back (crb::Lockable::Weak (lock));
3086- lock->lock ();
3087-
3088- return lock;
3089-}
3090-
3091-namespace
3092-{
3093-bool isLock (const crb::Lockable::Weak &lockable,
3094- crb::BufferLock *lock)
3095-{
3096- crb::Lockable::Ptr strongLockable (lockable.lock ());
3097-
3098- /* Asserting that the lock did not go away without telling
3099- * us first */
3100- assert (strongLockable.get ());
3101-
3102- if (strongLockable.get () == lock)
3103- return true;
3104-
3105- return false;
3106-}
3107-}
3108-
3109-void
3110-crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock)
3111-{
3112- std::remove_if (priv->locks.begin (),
3113- priv->locks.end (),
3114- boost::bind (isLock, _1, lock));
3115-}
3116-
3117-bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib)
3118-{
3119- priv->dispatchConfigure (true);
3120- return priv->syncServerWindow->queryAttributes (attrib);
3121-}
3122-
3123-bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib)
3124-{
3125- priv->dispatchConfigure (true);
3126- return priv->syncServerWindow->queryFrameAttributes (attrib);
3127-}
3128-
3129-/* This is more or less of a stop-gap for the fact that
3130- * when resizing window we re-query the window shape
3131- * and apply that to the frame. That's a separate unit of
3132- * work and should be dealt with separately. For now, force
3133- * a release of the queue whenever we do that so that
3134- * XShapeGetRectangles doesn't return an unexpected value
3135- */
3136-XRectangle *
3137-crb::ConfigureRequestBuffer::queryShapeRectangles (int kind,
3138- int *count,
3139- int *ordering)
3140-{
3141- priv->dispatchConfigure (true);
3142- return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering);
3143-}
3144-
3145-void crb::ConfigureRequestBuffer::forceRelease ()
3146-{
3147- priv->dispatchConfigure (true);
3148-}
3149-
3150-crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
3151- SyncServerWindow *syncServerWindow,
3152- const crb::ConfigureRequestBuffer::LockFactory &factory) :
3153- priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory))
3154-{
3155-}
3156-
3157-compiz::window::configure_buffers::Buffer::Ptr
3158-crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow,
3159- SyncServerWindow *syncServerWindow,
3160- const LockFactory &factory)
3161-{
3162- return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow,
3163- syncServerWindow,
3164- factory));
3165-}
3166-
3167-class crb::ConfigureBufferLock::Private
3168-{
3169- public:
3170-
3171- Private (crb::CountedFreeze *freezable) :
3172- freezable (freezable),
3173- armed (false)
3174- {
3175- }
3176-
3177- crb::CountedFreeze *freezable;
3178- bool armed;
3179-};
3180-
3181-crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) :
3182- priv (new crb::ConfigureBufferLock::Private (freezable))
3183-{
3184-}
3185-
3186-crb::ConfigureBufferLock::~ConfigureBufferLock ()
3187-{
3188- release ();
3189-}
3190-
3191-void
3192-crb::ConfigureBufferLock::lock ()
3193-{
3194- if (!priv->armed)
3195- priv->freezable->freeze ();
3196-
3197- priv->armed = true;
3198-}
3199-
3200-void
3201-crb::ConfigureBufferLock::release ()
3202-{
3203- if (priv->armed)
3204- priv->freezable->release ();
3205-
3206- priv->armed = false;
3207-}
3208
3209=== modified file 'src/event.cpp'
3210--- src/event.cpp 2013-02-10 05:01:50 +0000
3211+++ src/event.cpp 2013-02-28 03:13:24 +0000
3212@@ -1947,7 +1947,7 @@
3213
3214 /* We should check the override_redirect flag here, because the
3215 client might have changed it while being unmapped. */
3216- if (w->queryAttributes (attr))
3217+ if (XGetWindowAttributes (privateScreen.dpy, w->id (), &attr))
3218 w->priv->setOverrideRedirect (attr.override_redirect != 0);
3219
3220 if (w->state () & CompWindowStateHiddenMask)
3221
3222=== modified file 'src/privatewindow.h'
3223--- src/privatewindow.h 2013-02-10 05:01:50 +0000
3224+++ src/privatewindow.h 2013-02-28 03:13:24 +0000
3225@@ -35,11 +35,6 @@
3226
3227 #include <boost/shared_ptr.hpp>
3228
3229-#include <core/configurerequestbuffer.h>
3230-
3231-#include "syncserverwindow.h"
3232-#include "asyncserverwindow.h"
3233-
3234 #define XWINDOWCHANGES_INIT {0, 0, 0, 0, 0, None, 0}
3235
3236 namespace compiz {namespace X11
3237@@ -112,47 +107,12 @@
3238
3239 typedef CompWindowExtents CompFullscreenMonitorSet;
3240
3241-class X11SyncServerWindow :
3242- public compiz::window::SyncServerWindow
3243-{
3244- public:
3245-
3246- X11SyncServerWindow (Display *dpy,
3247- const Window *w,
3248- const Window *frame);
3249-
3250- bool queryAttributes (XWindowAttributes &attrib);
3251- bool queryFrameAttributes (XWindowAttributes &attrib);
3252- XRectangle * queryShapeRectangles(int kind, int *count, int *ordering);
3253-
3254- private:
3255-
3256- Display *mDpy;
3257- const Window *mWindow;
3258- const Window *mFrame;
3259-};
3260-
3261-class PrivateWindow :
3262- public compiz::window::SyncServerWindow,
3263- public compiz::window::AsyncServerWindow
3264-{
3265+class PrivateWindow {
3266
3267 public:
3268 PrivateWindow ();
3269 ~PrivateWindow ();
3270
3271- bool queryAttributes (XWindowAttributes &attrib);
3272- bool queryFrameAttributes (XWindowAttributes &attrib);
3273- XRectangle * queryShapeRectangles (int kind, int *count, int *ordering);
3274- int requestConfigureOnClient (const XWindowChanges &xwc,
3275- unsigned int valueMask);
3276- int requestConfigureOnWrapper (const XWindowChanges &xwc,
3277- unsigned int valueMask);
3278- int requestConfigureOnFrame (const XWindowChanges &xwc,
3279- unsigned int valueMask);
3280- void sendSyntheticConfigureNotify ();
3281- bool hasCustomShape () const;
3282-
3283 void recalcNormalHints ();
3284
3285 void updateFrameWindow ();
3286@@ -422,7 +382,6 @@
3287
3288 CompWindowExtents input;
3289 CompWindowExtents serverInput;
3290- CompWindowExtents lastServerInput;
3291 CompWindowExtents border;
3292 CompWindowExtents output;
3293
3294@@ -448,9 +407,6 @@
3295 Time lastCloseRequestTime;
3296
3297 bool nextMoveImmediate;
3298-
3299- X11SyncServerWindow syncServerWindow;
3300- compiz::window::configure_buffers::Buffer::Ptr configureBuffer;
3301 };
3302
3303 #endif
3304
3305=== removed file 'src/serverwindow.h'
3306=== removed file 'src/syncserverwindow.h'
3307--- src/syncserverwindow.h 2012-12-13 11:12:32 +0000
3308+++ src/syncserverwindow.h 1970-01-01 00:00:00 +0000
3309@@ -1,49 +0,0 @@
3310-/*
3311- * Copyright © 2012 Sam Spilsbury
3312- *
3313- * Permission to use, copy, modify, distribute, and sell this software
3314- * and its documentation for any purpose is hereby granted without
3315- * fee, provided that the above copyright notice appear in all copies
3316- * and that both that copyright notice and this permission notice
3317- * appear in supporting documentation, and that the name of
3318- * Canonical Ltd. not be used in advertising or publicity pertaining to
3319- * distribution of the software without specific, written prior permission.
3320- * Canonical Ltd. makes no representations about the suitability of this
3321- * software for any purpose. It is provided "as is" without express or
3322- * implied warranty.
3323- *
3324- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3325- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
3326- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3327- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
3328- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
3329- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
3330- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3331- *
3332- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
3333- */
3334-#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H
3335-#define _COMPIZ_SYNC_SERVER_WINDOW_H
3336-
3337-#include <X11/Xlib.h>
3338-
3339-namespace compiz
3340-{
3341-namespace window
3342-{
3343-class SyncServerWindow
3344-{
3345- public:
3346-
3347- virtual ~SyncServerWindow () {}
3348-
3349- virtual bool queryAttributes (XWindowAttributes &attrib) = 0;
3350- virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0;
3351- virtual XRectangle * queryShapeRectangles (int kind,
3352- int *count,
3353- int *ordering) = 0;
3354-};
3355-}
3356-}
3357-
3358-#endif
3359
3360=== modified file 'src/tests/CMakeLists.txt'
3361--- src/tests/CMakeLists.txt 2013-02-10 05:01:50 +0000
3362+++ src/tests/CMakeLists.txt 2013-02-28 03:13:24 +0000
3363@@ -30,14 +30,3 @@
3364
3365 compiz_discover_tests(compiz_test_outputdevices COVERAGE compiz_core)
3366
3367-add_executable (compiz_test_configurerequestbuffer
3368- test_configurerequestbuffer.cpp)
3369-
3370-target_link_libraries (compiz_test_configurerequestbuffer
3371- compiz_configurerequestbuffer
3372- ${GTEST_BOTH_LIBRARIES}
3373- ${GMOCK_MAIN_LIBRARY}
3374- ${GMOCK_LIBRARY}
3375-)
3376-
3377-compiz_discover_tests(compiz_test_configurerequestbuffer COVERAGE compiz_configurerequestbuffer)
3378
3379=== removed file 'src/tests/test_configurerequestbuffer.cpp'
3380--- src/tests/test_configurerequestbuffer.cpp 2012-12-13 14:07:01 +0000
3381+++ src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
3382@@ -1,667 +0,0 @@
3383-/*
3384- * Copyright © 2012 Sam Spilsbury
3385- *
3386- * Permission to use, copy, modify, distribute, and sell this software
3387- * and its documentation for any purpose is hereby granted without
3388- * fee, provided that the above copyright notice appear in all copies
3389- * and that both that copyright notice and this permission notice
3390- * appear in supporting documentation, and that the name of
3391- * Canonical Ltd. not be used in advertising or publicity pertaining to
3392- * distribution of the software without specific, written prior permission.
3393- * Canonical Ltd. makes no representations about the suitability of this
3394- * software for any purpose. It is provided "as is" without express or
3395- * implied warranty.
3396- *
3397- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3398- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
3399- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3400- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
3401- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
3402- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
3403- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3404- *
3405- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
3406- */
3407-#include <deque>
3408-#include <boost/shared_ptr.hpp>
3409-#include <boost/make_shared.hpp>
3410-#include <boost/bind.hpp>
3411-#include <gmock/gmock.h>
3412-#include <gtest/gtest.h>
3413-#include <X11/Xlib.h>
3414-
3415-#include "configurerequestbuffer-impl.h"
3416-#include "asyncserverwindow.h"
3417-
3418-namespace crb = compiz::window::configure_buffers;
3419-namespace cw = compiz::window;
3420-
3421-using testing::_;
3422-using testing::NiceMock;
3423-using testing::Return;
3424-using testing::Invoke;
3425-using testing::WithArgs;
3426-using testing::SetArgReferee;
3427-using testing::DoAll;
3428-using testing::InSequence;
3429-using testing::ReturnNull;
3430-using testing::IsNull;
3431-
3432-class MockAsyncServerWindow :
3433- public cw::AsyncServerWindow
3434-{
3435- public:
3436-
3437- MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int));
3438- MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int));
3439- MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int));
3440- MOCK_METHOD0 (sendSyntheticConfigureNotify, void ());
3441- MOCK_CONST_METHOD0 (hasCustomShape, bool ());
3442-};
3443-
3444-class MockSyncServerWindow :
3445- public cw::SyncServerWindow
3446-{
3447- public:
3448-
3449- MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &));
3450- MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &));
3451- MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *));
3452-};
3453-
3454-namespace
3455-{
3456-int REQUEST_X = 1;
3457-int REQUEST_Y = 2;
3458-int REQUEST_WIDTH = 3;
3459-int REQUEST_HEIGHT = 4;
3460-int REQUEST_BORDER = 5;
3461-
3462-Window REQUEST_ABOVE = 6;
3463-unsigned int REQUEST_MODE = 7;
3464-
3465-crb::BufferLock::Ptr
3466-CreateNormalLock (crb::CountedFreeze *cf)
3467-{
3468- return boost::make_shared <crb::ConfigureBufferLock> (cf);
3469-}
3470-
3471-}
3472-
3473-MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges")
3474-{
3475- if (vm & CWX)
3476- if (xwc.x != arg.x)
3477- return false;
3478-
3479- if (vm & CWY)
3480- if (xwc.y != arg.y)
3481- return false;
3482-
3483- if (vm & CWWidth)
3484- if (xwc.width != arg.width)
3485- return false;
3486-
3487- if (vm & CWHeight)
3488- if (xwc.height != arg.height)
3489- return false;
3490-
3491- if (vm & CWBorderWidth)
3492- if (xwc.border_width != arg.border_width)
3493- return false;
3494-
3495- if (vm & CWStackMode)
3496- if (xwc.stack_mode != arg.stack_mode)
3497- return false;
3498-
3499- if (vm & CWSibling)
3500- if (xwc.sibling != arg.sibling)
3501- return false;
3502-
3503- return true;
3504-}
3505-
3506-class ConfigureRequestBuffer :
3507- public testing::Test
3508-{
3509- public:
3510-
3511- ConfigureRequestBuffer ()
3512- {
3513- /* Initialize xwc, we control it
3514- * through the value masks */
3515- xwc.x = REQUEST_X;
3516- xwc.y = REQUEST_Y;
3517- xwc.width = REQUEST_WIDTH;
3518- xwc.height = REQUEST_HEIGHT;
3519- xwc.border_width = REQUEST_BORDER;
3520- xwc.sibling = REQUEST_ABOVE;
3521- xwc.stack_mode = REQUEST_MODE;
3522- }
3523-
3524- protected:
3525-
3526- XWindowChanges xwc;
3527- MockAsyncServerWindow asyncServerWindow;
3528- MockSyncServerWindow syncServerWindow;
3529-};
3530-
3531-class ConfigureRequestBufferDispatch :
3532- public ConfigureRequestBuffer
3533-{
3534- protected:
3535-
3536- ConfigureRequestBufferDispatch () :
3537- ConfigureRequestBuffer (),
3538- factory (boost::bind (CreateNormalLock, _1)),
3539- buffer (
3540- crb::ConfigureRequestBuffer::Create (&asyncServerWindow,
3541- &syncServerWindow,
3542- factory))
3543- {
3544- }
3545-
3546- crb::ConfigureRequestBuffer::LockFactory factory;
3547- crb::Buffer::Ptr buffer;
3548-};
3549-
3550-TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify)
3551-{
3552- EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ());
3553-
3554- buffer->pushSyntheticConfigureNotify ();
3555-}
3556-
3557-TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate)
3558-{
3559- unsigned int valueMask = CWX | CWY | CWBorderWidth |
3560- CWSibling | CWStackMode;
3561-
3562- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
3563- valueMask));
3564-
3565- buffer->pushClientRequest (xwc, valueMask);
3566-}
3567-
3568-TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate)
3569-{
3570- unsigned int valueMask = CWX | CWY | CWBorderWidth |
3571- CWSibling | CWStackMode;
3572-
3573- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
3574- valueMask));
3575-
3576- buffer->pushWrapperRequest (xwc, valueMask);
3577-}
3578-
3579-TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate)
3580-{
3581- unsigned int valueMask = CWX | CWY | CWBorderWidth |
3582- CWSibling | CWStackMode;
3583-
3584- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3585- valueMask));
3586-
3587- buffer->pushFrameRequest (xwc, valueMask);
3588-}
3589-
3590-TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked)
3591-{
3592- crb::Releasable::Ptr lock (buffer->obtainLock ());
3593-
3594- unsigned int valueMask = 0;
3595-
3596- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3597-
3598- buffer->pushFrameRequest (xwc, valueMask);
3599-}
3600-
3601-TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked)
3602-{
3603- crb::Releasable::Ptr lock (buffer->obtainLock ());
3604-
3605- unsigned int valueMask = CWX;
3606-
3607- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3608-
3609- buffer->pushFrameRequest (xwc, valueMask);
3610-
3611- valueMask |= CWY;
3612-
3613- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3614-
3615- buffer->pushFrameRequest (xwc, valueMask);
3616-
3617- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3618- valueMask));
3619-
3620- lock->release ();
3621-}
3622-
3623-/*
3624- * This test is disabled until we can expose the QueryShapeRectangles API
3625- * to plugins
3626- */
3627-TEST_F (ConfigureRequestBufferDispatch, DISABLED_PushUpdateLockedReleaseInOrder)
3628-{
3629- crb::Releasable::Ptr lock (buffer->obtainLock ());
3630-
3631- unsigned int valueMask = CWX | CWY;
3632-
3633- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3634- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0);
3635- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0);
3636-
3637- buffer->pushClientRequest (xwc, valueMask);
3638- buffer->pushWrapperRequest (xwc, 0);
3639- buffer->pushFrameRequest (xwc, 0);
3640-
3641- InSequence s;
3642-
3643- /* Always frame -> wrapper -> client */
3644- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3645- valueMask));
3646- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
3647- valueMask));
3648- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
3649- valueMask));
3650-
3651- lock->release ();
3652-}
3653-
3654-TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer)
3655-{
3656- crb::Releasable::Ptr lock (buffer->obtainLock ());
3657-
3658- unsigned int valueMask = CWX | CWY;
3659-
3660- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3661-
3662- buffer->pushFrameRequest (xwc, valueMask);
3663-
3664- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3665- valueMask));
3666-
3667- lock->release ();
3668-}
3669-
3670-TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer)
3671-{
3672- crb::Releasable::Ptr lock (buffer->obtainLock ());
3673-
3674- unsigned int valueMask = CWX | CWY;
3675-
3676- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3677-
3678- buffer->pushFrameRequest (xwc, valueMask);
3679-
3680- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3681- valueMask));
3682-}
3683-
3684-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack)
3685-{
3686- crb::Releasable::Ptr lock (buffer->obtainLock ());
3687-
3688- unsigned int valueMask = CWStackMode | CWSibling;
3689-
3690- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3691- valueMask));
3692-
3693- buffer->pushFrameRequest (xwc, valueMask);
3694-}
3695-
3696-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWindowSizeChange)
3697-{
3698- crb::Releasable::Ptr lock (buffer->obtainLock ());
3699-
3700- unsigned int valueMask = CWWidth | CWHeight | CWBorderWidth;
3701-
3702- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3703- valueMask));
3704-
3705- buffer->pushFrameRequest (xwc, valueMask);
3706-}
3707-
3708-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnClientReposition)
3709-{
3710- crb::Releasable::Ptr lock (buffer->obtainLock ());
3711-
3712- unsigned int valueMask = CWX | CWY;
3713-
3714- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
3715- valueMask));
3716-
3717- buffer->pushClientRequest (xwc, valueMask);
3718-}
3719-
3720-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWrapperReposition)
3721-{
3722- crb::Releasable::Ptr lock (buffer->obtainLock ());
3723-
3724- unsigned int valueMask = CWX | CWY;
3725-
3726- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
3727- valueMask));
3728-
3729- buffer->pushWrapperRequest (xwc, valueMask);
3730-}
3731-
3732-namespace
3733-{
3734-class MockLock :
3735- public crb::BufferLock
3736-{
3737- public:
3738-
3739- /* We're currently importing the locks statefulness and coupling
3740- * the caller with that */
3741- MockLock () :
3742- armed (false)
3743- {
3744- ON_CALL (*this, lock ()).WillByDefault (
3745- Invoke (this, &MockLock::FreezeIfUnarmed));
3746- ON_CALL (*this, release ()).WillByDefault (
3747- Invoke (this, &MockLock::ReleaseIfArmed));
3748- }
3749-
3750- void OperateOver (crb::CountedFreeze *cf)
3751- {
3752- countedFreeze = cf;
3753- }
3754-
3755- void FreezeIfUnarmed ()
3756- {
3757- if (!armed)
3758- {
3759- countedFreeze->freeze ();
3760- armed = true;
3761- }
3762- }
3763-
3764- void ReleaseIfArmed ()
3765- {
3766- if (armed)
3767- {
3768- countedFreeze->release ();
3769- armed = false;
3770- }
3771- }
3772-
3773- typedef boost::shared_ptr <MockLock> Ptr;
3774-
3775- MOCK_METHOD0 (lock, void ());
3776- MOCK_METHOD0 (release, void ());
3777-
3778- private:
3779-
3780- crb::CountedFreeze *countedFreeze;
3781- bool armed;
3782-};
3783-
3784-class MockLockFactory
3785-{
3786- public:
3787-
3788- crb::BufferLock::Ptr
3789- CreateMockLock (crb::CountedFreeze *cf)
3790- {
3791- MockLock::Ptr mockLock (locks.front ());
3792- mockLock->OperateOver (cf);
3793-
3794- locks.pop_front ();
3795-
3796- return mockLock;
3797- }
3798-
3799- void
3800- QueueLockForCreation (const MockLock::Ptr &lock)
3801- {
3802- locks.push_back (lock);
3803- }
3804-
3805- private:
3806-
3807- std::deque <MockLock::Ptr> locks;
3808-};
3809-}
3810-
3811-class ConfigureRequestBufferLockBehaviour :
3812- public ConfigureRequestBuffer
3813-{
3814- public:
3815-
3816- ConfigureRequestBufferLockBehaviour () :
3817- ConfigureRequestBuffer (),
3818- lock (boost::make_shared <MockLock> ()),
3819- factory (
3820- boost::bind (&MockLockFactory::CreateMockLock,
3821- &mockLockFactory,
3822- _1)),
3823- buffer (
3824- crb::ConfigureRequestBuffer::Create (
3825- &asyncServerWindow,
3826- &syncServerWindow,
3827- factory))
3828-
3829- {
3830- mockLockFactory.QueueLockForCreation (lock);
3831- }
3832-
3833- protected:
3834-
3835- typedef NiceMock <MockAsyncServerWindow> NiceServerWindow;
3836- typedef crb::ConfigureRequestBuffer::LockFactory LockFactory;
3837-
3838- MockLock::Ptr lock;
3839- MockLockFactory mockLockFactory;
3840-
3841- LockFactory factory;
3842- crb::Buffer::Ptr buffer;
3843-};
3844-
3845-TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease)
3846-{
3847- EXPECT_CALL (*lock, lock ());
3848- crb::Releasable::Ptr releasable (buffer->obtainLock ());
3849-
3850- unsigned int valueMask = CWX | CWY;
3851-
3852- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3853-
3854- buffer->pushFrameRequest (xwc, valueMask);
3855-
3856- /* We are releasing this lock */
3857- EXPECT_CALL (*lock, release ());
3858-
3859- /* Now the buffer will dispatch is configure request */
3860- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
3861-
3862- /* Rearm locks on release */
3863- EXPECT_CALL (*lock, lock ());
3864-
3865- /* Directly release the queue */
3866- releasable->release ();
3867-}
3868-
3869-TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired)
3870-{
3871- /* Locks get armed on construction */
3872- EXPECT_CALL (*lock, lock ());
3873- crb::Releasable::Ptr releasable (buffer->obtainLock ());
3874-
3875- /* No call to requestConfigureOnFrame if there's nothing to be configured */
3876- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3877-
3878- /* We are releasing this lock */
3879- EXPECT_CALL (*lock, release ());
3880-
3881- /* No rearm - we haven't released the whole buffer */
3882- EXPECT_CALL (*lock, lock ()).Times (0);
3883-
3884- /* Directly release the queue */
3885- releasable->release ();
3886-}
3887-
3888-TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady)
3889-{
3890- /* Locks get armed on construction */
3891- EXPECT_CALL (*lock, lock ());
3892- crb::Releasable::Ptr releasable (buffer->obtainLock ());
3893-
3894- /* We are releasing this lock */
3895- EXPECT_CALL (*lock, release ());
3896-
3897- /* No call to requestConfigureOnFrame if there's nothing to be configured */
3898- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3899-
3900- /* No rearm - we haven't released it */
3901- EXPECT_CALL (*lock, lock ()).Times (0);
3902-
3903- /* Directly release the queue */
3904- releasable->release ();
3905-
3906- /* Since we're now going to push something to a queue
3907- * that's effectively not locked, the locks should now
3908- * be released */
3909- unsigned int valueMask = CWX | CWY;
3910-
3911- /* Now rearm it */
3912- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
3913- EXPECT_CALL (*lock, lock ());
3914-
3915- buffer->pushFrameRequest (xwc, valueMask);
3916-}
3917-
3918-TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease)
3919-{
3920- MockLock::Ptr second (boost::make_shared <MockLock> ());
3921- mockLockFactory.QueueLockForCreation (second);
3922-
3923- /* Locks get armed on construction */
3924- EXPECT_CALL (*lock, lock ());
3925- EXPECT_CALL (*second, lock ());
3926-
3927- crb::Releasable::Ptr releasable (buffer->obtainLock ());
3928- crb::Releasable::Ptr otherReleasable (buffer->obtainLock ());
3929-
3930- /* We are releasing this lock */
3931- EXPECT_CALL (*lock, release ());
3932-
3933- /* No call to requestConfigureOnFrame if there's nothing to be configured */
3934- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3935-
3936- /* No rearm - we haven't released it */
3937- EXPECT_CALL (*lock, lock ()).Times (0);
3938-
3939- releasable->release ();
3940-}
3941-
3942-TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm)
3943-{
3944- /* Locks get armed on construction */
3945- EXPECT_CALL (*lock, lock ());
3946-
3947- crb::Releasable::Ptr releasable (buffer->obtainLock ());
3948-
3949- unsigned int valueMask = CWX | CWY;
3950-
3951- /* Queue locked */
3952- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3953-
3954- buffer->pushFrameRequest (xwc, valueMask);
3955-
3956- /* Queue forceably unlocked, locks rearmed */
3957- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
3958- EXPECT_CALL (*lock, lock ());
3959-
3960- /* Expect a call to XGetWindowAttributes */
3961- EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _))
3962- .WillOnce (
3963- ReturnNull ());
3964-
3965- int a, b;
3966-
3967- EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ());
3968-}
3969-
3970-TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm)
3971-{
3972- /* Locks get armed on construction */
3973- EXPECT_CALL (*lock, lock ());
3974-
3975- crb::Releasable::Ptr releasable (buffer->obtainLock ());
3976-
3977- unsigned int valueMask = CWX | CWY;
3978-
3979- /* Queue locked */
3980- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3981-
3982- buffer->pushFrameRequest (xwc, valueMask);
3983-
3984- /* Queue forceably unlocked, locks rearmed */
3985- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
3986- EXPECT_CALL (*lock, lock ());
3987-
3988- /* Expect a call to XGetWindowAttributes */
3989- XWindowAttributes xwa;
3990- EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
3991- .WillOnce (
3992- DoAll (
3993- SetArgReferee <0> (xwa),
3994- Return (true)));
3995-
3996- buffer->queryFrameAttributes (xwa);
3997-}
3998-
3999-TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm)
4000-{
4001- /* Locks get armed on construction */
4002- EXPECT_CALL (*lock, lock ());
4003-
4004- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4005-
4006- unsigned int valueMask = CWX | CWY;
4007-
4008- /* Queue locked */
4009- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4010-
4011- buffer->pushFrameRequest (xwc, valueMask);
4012-
4013- /* Queue forceably unlocked, locks rearmed */
4014- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4015- EXPECT_CALL (*lock, lock ());
4016-
4017- /* Expect a call to XGetWindowAttributes */
4018- XWindowAttributes xwa;
4019- EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
4020- .WillOnce (
4021- DoAll (
4022- SetArgReferee <0> (xwa),
4023- Return (true)));
4024-
4025- buffer->queryFrameAttributes (xwa);
4026-}
4027-
4028-TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm)
4029-{
4030- /* Locks get armed on construction */
4031- EXPECT_CALL (*lock, lock ());
4032-
4033- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4034-
4035- unsigned int valueMask = CWX | CWY;
4036-
4037- /* Queue locked */
4038- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4039-
4040- buffer->pushFrameRequest (xwc, valueMask);
4041-
4042- /* Queue forceably unlocked, locks rearmed */
4043- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4044- EXPECT_CALL (*lock, lock ());
4045-
4046- /* Force release */
4047- buffer->forceRelease ();
4048-}
4049-

Subscribers

People subscribed via source and target branches