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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1024304
Merge into: lp:compiz/0.9.9
Diff against target: 2635 lines (+1508/-222)
35 files modified
include/core/window.h (+2/-2)
plugins/animation/src/animation.cpp (+1/-1)
plugins/composite/CMakeLists.txt (+6/-1)
plugins/composite/include/composite/agedamagequery.h (+53/-0)
plugins/composite/include/composite/composite.h (+49/-14)
plugins/composite/src/backbuffertracking/CMakeLists.txt (+31/-0)
plugins/composite/src/backbuffertracking/include/backbuffertracking.h (+125/-0)
plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp (+214/-0)
plugins/composite/src/backbuffertracking/tests/CMakeLists.txt (+24/-0)
plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp (+450/-0)
plugins/composite/src/privates.h (+18/-2)
plugins/composite/src/screen.cpp (+137/-12)
plugins/kdecompat/src/kdecompat.cpp (+2/-2)
plugins/opengl/include/opengl/opengl.h (+18/-3)
plugins/opengl/src/doublebuffer/src/double-buffer.cpp (+1/-2)
plugins/opengl/src/framebufferobject.cpp (+1/-1)
plugins/opengl/src/paint.cpp (+11/-3)
plugins/opengl/src/privates.h (+30/-1)
plugins/opengl/src/screen.cpp (+290/-30)
plugins/resize/src/resize.cpp (+1/-1)
plugins/ring/src/ring.cpp (+1/-1)
plugins/scale/src/scale.cpp (+3/-1)
plugins/staticswitcher/src/staticswitcher.cpp (+1/-1)
plugins/switcher/src/switcher.cpp (+1/-1)
plugins/td/src/3d.cpp (+1/-1)
plugins/water/src/water.cpp (+7/-0)
plugins/water/src/water.h (+1/-0)
src/event.cpp (+3/-29)
src/option/tests/CMakeLists.txt (+0/-1)
src/option/tests/option.cpp (+0/-4)
src/outputdevices.h (+0/-5)
src/privatewindow.h (+25/-22)
src/tests/CMakeLists.txt (+0/-1)
src/window.cpp (+1/-0)
tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp (+0/-80)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1024304
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Esokrates (community) testing, benchmarking Approve
Compiz Maintainers Pending
Review via email: mp+147832@code.launchpad.net

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

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

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 :
review: Approve (continuous-integration)
Revision history for this message
Esokrates (esokrarkose) wrote :

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 :

The change to debian/changelog seems to be unintended and should probably be removed.

3561. By Sam Spilsbury

Fix typo

3562. By Sam Spilsbury

Merge lp:compiz

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

Fix broken merge

3564. By Sam Spilsbury

Merge lp:compiz

3565. By Sam Spilsbury

Revert more changes which should not have happened

3566. By Sam Spilsbury

Merge lp:compiz

3567. By Sam Spilsbury

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

3568. By Sam Spilsbury

Merge lp:compiz

Unmerged revisions

3568. By Sam Spilsbury

Merge lp:compiz

3567. By Sam Spilsbury

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

3566. By Sam Spilsbury

Merge lp:compiz

3565. By Sam Spilsbury

Revert more changes which should not have happened

3564. By Sam Spilsbury

Merge lp:compiz

3563. By Sam Spilsbury

Fix broken merge

3562. By Sam Spilsbury

Merge lp:compiz

3561. By Sam Spilsbury

Fix typo

3560. By Sam Spilsbury

Unrevert changes which should not have been reverted

3559. By Sam Spilsbury

Merge lp:compiz

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/core/window.h'
--- include/core/window.h 2013-01-03 16:06:41 +0000
+++ include/core/window.h 2013-02-13 11:42:25 +0000
@@ -43,12 +43,12 @@
43#include <core/region.h>43#include <core/region.h>
44#include <core/windowgeometry.h>44#include <core/windowgeometry.h>
45#include <core/windowextents.h>45#include <core/windowextents.h>
46#include <core/servergrab.h>
4746
48#include <core/wrapsystem.h>47#include <core/wrapsystem.h>
4948
50#include <map>49#include <map>
5150
51class ServerLock;
52class CompWindow;52class CompWindow;
53class CompIcon;53class CompIcon;
54class PrivateWindow;54class PrivateWindow;
@@ -434,7 +434,7 @@
434 void moveInputFocusToOtherWindow ();434 void moveInputFocusToOtherWindow ();
435435
436 /* wraps XConfigureWindow and updates serverGeometry */436 /* wraps XConfigureWindow and updates serverGeometry */
437 void configureXWindow (unsigned int valueMask,437 void configureXWindow (unsigned int valueMask,
438 XWindowChanges *xwc);438 XWindowChanges *xwc);
439439
440 void restackAndConfigureXWindow (unsigned int valueMask,440 void restackAndConfigureXWindow (unsigned int valueMask,
441441
=== modified file 'plugins/animation/src/animation.cpp'
--- plugins/animation/src/animation.cpp 2013-01-11 08:28:51 +0000
+++ plugins/animation/src/animation.cpp 2013-02-13 11:42:25 +0000
@@ -1617,7 +1617,7 @@
1617 // Is this the first glPaint call this round1617 // Is this the first glPaint call this round
1618 // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK?1618 // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK?
1619 if (mPAScreen->mStartingNewPaintRound &&1619 if (mPAScreen->mStartingNewPaintRound &&
1620 !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))1620 !(mask & PAINT_WINDOW_NO_DRAW_MASKS))
1621 {1621 {
1622 mPAScreen->mStartingNewPaintRound = false;1622 mPAScreen->mStartingNewPaintRound = false;
16231623
16241624
=== modified file 'plugins/composite/CMakeLists.txt'
--- plugins/composite/CMakeLists.txt 2012-09-25 01:15:36 +0000
+++ plugins/composite/CMakeLists.txt 2013-02-13 11:42:25 +0000
@@ -2,9 +2,14 @@
22
3include (CompizPlugin)3include (CompizPlugin)
44
5include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
5include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/pixmapbinding/include)6include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/pixmapbinding/include)
7include_directories (${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking/include)
8
6link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/pixmapbinding)9link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/pixmapbinding)
10link_directories (${CMAKE_CURRENT_BINARY_DIR}/src/backbuffertracking)
711
8compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding)12compiz_plugin (composite LIBRARIES compiz_composite_pixmapbinding compiz_composite_backbuffertracking)
913
10add_subdirectory (src/pixmapbinding)14add_subdirectory (src/pixmapbinding)
15add_subdirectory (src/backbuffertracking)
1116
=== added file 'plugins/composite/include/composite/agedamagequery.h'
--- plugins/composite/include/composite/agedamagequery.h 1970-01-01 00:00:00 +0000
+++ plugins/composite/include/composite/agedamagequery.h 2013-02-13 11:42:25 +0000
@@ -0,0 +1,53 @@
1/*
2 * Compiz, composite plugin, GLX_EXT_buffer_age logic
3 *
4 * Copyright (c) 2012 Sam Spilsbury
5 * Authors: Sam Spilsbury <smspillaz@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#ifndef _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H
26#define _COMPIZ_COMPOSITE_AGEDAMAGEQUERY_H
27
28#include <boost/shared_ptr.hpp>
29#include <core/region.h>
30
31namespace compiz
32{
33namespace composite
34{
35namespace buffertracking
36{
37class AgeDamageQuery
38{
39 public:
40
41 typedef boost::shared_ptr <AgeDamageQuery> Ptr;
42 typedef boost::function <bool (const CompRegion &)> AreaShouldBeMarkedDirty;
43
44 virtual ~AgeDamageQuery () {}
45 virtual CompRegion damageForFrameAge (unsigned int) = 0;
46 virtual const CompRegion & currentFrameDamage () = 0;
47};
48}
49}
50}
51
52#endif
53
054
=== modified file 'plugins/composite/include/composite/composite.h'
--- plugins/composite/include/composite/composite.h 2012-10-16 05:11:10 +0000
+++ plugins/composite/include/composite/composite.h 2013-02-13 11:42:25 +0000
@@ -30,7 +30,7 @@
3030
31#include <X11/extensions/Xcomposite.h>31#include <X11/extensions/Xcomposite.h>
3232
33#define COMPIZ_COMPOSITE_ABI 533#define COMPIZ_COMPOSITE_ABI 6
3434
35#include "core/pluginclasshandler.h"35#include "core/pluginclasshandler.h"
36#include "core/timer.h"36#include "core/timer.h"
@@ -38,6 +38,8 @@
38#include "core/screen.h"38#include "core/screen.h"
39#include "core/wrapsystem.h"39#include "core/wrapsystem.h"
4040
41#include "composite/agedamagequery.h"
42
41#define COMPOSITE_SCREEN_DAMAGE_PENDING_MASK (1 << 0)43#define COMPOSITE_SCREEN_DAMAGE_PENDING_MASK (1 << 0)
42#define COMPOSITE_SCREEN_DAMAGE_REGION_MASK (1 << 1)44#define COMPOSITE_SCREEN_DAMAGE_REGION_MASK (1 << 1)
43#define COMPOSITE_SCREEN_DAMAGE_ALL_MASK (1 << 2)45#define COMPOSITE_SCREEN_DAMAGE_ALL_MASK (1 << 2)
@@ -98,18 +100,19 @@
98namespace composite100namespace composite
99{101{
100class PaintHandler {102class PaintHandler {
101public:103 public:
102 virtual ~PaintHandler () {};104 virtual ~PaintHandler () {};
103105
104 virtual void paintOutputs (CompOutput::ptrList &outputs,106 virtual void paintOutputs (CompOutput::ptrList &outputs,
105 unsigned int mask,107 unsigned int mask,
106 const CompRegion &region) = 0;108 const CompRegion &region) = 0;
107109
108 virtual bool hasVSync () { return false; };110 virtual bool hasVSync () { return false; };
109 virtual bool requiredForcedRefreshRate () { return false; };111 virtual bool requiredForcedRefreshRate () { return false; };
110112
111 virtual void prepareDrawing () {};113 virtual void prepareDrawing () {};
112 virtual bool compositingActive () { return false; };114 virtual bool compositingActive () { return false; };
115 virtual unsigned int getFrameAge () { return 1; }
113};116};
114}117}
115}118}
@@ -173,12 +176,19 @@
173 * Hookable function to damage regions directly176 * Hookable function to damage regions directly
174 */177 */
175 virtual void damageRegion (const CompRegion &r);178 virtual void damageRegion (const CompRegion &r);
179
180 /**
181 * Hookable function to notify plugins that the last damage
182 * event for this frame has been received, and all further damage
183 * events will be for the next frame
184 */
185 virtual void damageCutoff ();
176};186};
177187
178extern template class PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>;188extern template class PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>;
179189
180class CompositeScreen :190class CompositeScreen :
181 public WrapableHandler<CompositeScreenInterface, 7>,191 public WrapableHandler<CompositeScreenInterface, 8>,
182 public PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>,192 public PluginClassHandler<CompositeScreen, CompScreen, COMPIZ_COMPOSITE_ABI>,
183 public CompOption::Class193 public CompOption::Class
184{194{
@@ -203,6 +213,24 @@
203 void damageScreen ();213 void damageScreen ();
204214
205 void damagePending ();215 void damagePending ();
216
217 /**
218 * Causes the damage that was recorded on N - 1 number of
219 * frames ago to be added to the current frame, applied
220 * culmulatively. An age of "zero" means that the entire frame
221 * is considered undefined and must be completely repaired,
222 * wheras an age of 1 means that this frame is the same as the
223 * last frame, so no damage is required.
224 */
225 void applyDamageForFrameAge (unsigned int);
226 unsigned int getFrameAge ();
227 void addOverdrawDamageRegion (const CompRegion &);
228
229 typedef compiz::composite::buffertracking::AgeDamageQuery DamageQuery;
230 typedef DamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty;
231
232 DamageQuery::Ptr
233 getDamageQuery (const AreaShouldBeMarkedDirty &callback);
206 234
207235
208 unsigned int damageMask ();236 unsigned int damageMask ();
@@ -248,6 +276,7 @@
248 * event loop276 * event loop
249 */277 */
250 WRAPABLE_HND (6, CompositeScreenInterface, void, damageRegion, const CompRegion &);278 WRAPABLE_HND (6, CompositeScreenInterface, void, damageRegion, const CompRegion &);
279 WRAPABLE_HND (7, CompositeScreenInterface, void, damageCutoff);
251280
252 friend class PrivateCompositeDisplay;281 friend class PrivateCompositeDisplay;
253282
@@ -310,6 +339,12 @@
310 */339 */
311#define PAINT_WINDOW_BLEND_MASK (1 << 19)340#define PAINT_WINDOW_BLEND_MASK (1 << 19)
312341
342/**
343 * flags that would indicate the window is never actually drawn
344 */
345#define PAINT_WINDOW_NO_DRAW_MASKS (PAINT_WINDOW_OCCLUSION_DETECTION_MASK | \
346 PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
347
313class CompositeWindowInterface;348class CompositeWindowInterface;
314extern template class WrapableInterface<CompositeWindow, CompositeWindowInterface>;349extern template class WrapableInterface<CompositeWindow, CompositeWindowInterface>;
315350
316351
=== added directory 'plugins/composite/src/backbuffertracking'
=== added file 'plugins/composite/src/backbuffertracking/CMakeLists.txt'
--- plugins/composite/src/backbuffertracking/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/composite/src/backbuffertracking/CMakeLists.txt 2013-02-13 11:42:25 +0000
@@ -0,0 +1,31 @@
1INCLUDE_DIRECTORIES (
2 ${CMAKE_CURRENT_SOURCE_DIR}/../../include
3 ${CMAKE_CURRENT_SOURCE_DIR}/include
4 ${CMAKE_CURRENT_SOURCE_DIR}/src
5
6 ${Boost_INCLUDE_DIRS}
7)
8
9LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
10
11SET(
12 SRCS
13 ${CMAKE_CURRENT_SOURCE_DIR}/src/backbuffertracking.cpp
14)
15
16ADD_LIBRARY(
17 compiz_composite_backbuffertracking STATIC
18
19 ${SRCS}
20)
21
22if (COMPIZ_BUILD_TESTING)
23ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
24endif (COMPIZ_BUILD_TESTING)
25
26TARGET_LINK_LIBRARIES(
27 compiz_composite_backbuffertracking
28
29 compiz_size
30 compiz_core
31)
032
=== added directory 'plugins/composite/src/backbuffertracking/include'
=== added file 'plugins/composite/src/backbuffertracking/include/backbuffertracking.h'
--- plugins/composite/src/backbuffertracking/include/backbuffertracking.h 1970-01-01 00:00:00 +0000
+++ plugins/composite/src/backbuffertracking/include/backbuffertracking.h 2013-02-13 11:42:25 +0000
@@ -0,0 +1,125 @@
1/*
2 * Compiz, composite plugin, GLX_EXT_buffer_age logic
3 *
4 * Copyright (c) 2012 Sam Spilsbury
5 * Authors: Sam Spilsbury <smspillaz@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#ifndef _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H
26#define _COMPIZ_COMPOSITE_BACKBUFFERTRACKING_H
27
28#include <memory>
29#include <boost/noncopyable.hpp>
30#include <boost/shared_ptr.hpp>
31#include <boost/weak_ptr.hpp>
32#include <boost/function.hpp>
33
34#include <composite/agedamagequery.h>
35
36class CompSize;
37class CompRegion;
38
39namespace compiz
40{
41namespace composite
42{
43namespace buffertracking
44{
45class DamageAgeTracking
46{
47 public:
48
49 virtual ~DamageAgeTracking () {};
50 virtual void dirtyAreaOnCurrentFrame (const CompRegion &) = 0;
51 virtual void overdrawRegionOnPaintingFrame (const CompRegion &) = 0;
52 virtual void subtractObscuredArea (const CompRegion &) = 0;
53 virtual void incrementFrameAges () = 0;
54};
55
56class AgeingDamageBufferObserver
57{
58 public:
59
60 virtual ~AgeingDamageBufferObserver () {};
61 virtual void observe (DamageAgeTracking &damageAgeTracker) = 0;
62 virtual void unobserve (DamageAgeTracking &damageAgeTracker) = 0;
63};
64
65class AgeingDamageBuffers :
66 public AgeingDamageBufferObserver,
67 boost::noncopyable
68{
69 public:
70
71 AgeingDamageBuffers ();
72
73 void observe (DamageAgeTracking &damageAgeTracker);
74 void unobserve (DamageAgeTracking &damageAgeTracker);
75 void incrementAges ();
76 void markAreaDirty (const CompRegion &reg);
77 void markAreaDirtyOnLastFrame (const CompRegion &reg);
78 void subtractObscuredArea (const CompRegion &reg);
79
80 private:
81
82 class Private;
83 std::auto_ptr <Private> priv;
84};
85
86class FrameRoster :
87 public DamageAgeTracking,
88 public AgeDamageQuery,
89 boost::noncopyable
90{
91 public:
92
93 typedef AgeDamageQuery::AreaShouldBeMarkedDirty AreaShouldBeMarkedDirty;
94 typedef boost::shared_ptr <FrameRoster> Ptr;
95
96 FrameRoster (const CompSize &size,
97 AgeingDamageBufferObserver &tracker,
98 const AreaShouldBeMarkedDirty &shouldMarkDirty);
99
100 ~FrameRoster ();
101
102 void dirtyAreaOnCurrentFrame (const CompRegion &);
103 void overdrawRegionOnPaintingFrame (const CompRegion &);
104 void subtractObscuredArea (const CompRegion &);
105 void incrementFrameAges ();
106 CompRegion damageForFrameAge (unsigned int);
107 const CompRegion & currentFrameDamage ();
108
109 class Private;
110 std::auto_ptr <Private> priv;
111
112 static const unsigned int NUM_TRACKED_FRAMES = 10;
113
114 static
115 FrameRoster::Ptr create (const CompSize &size,
116
117 const AreaShouldBeMarkedDirty &shouldMarkDirty);
118
119 private:
120
121};
122} // namespace buffertracking
123} // namespace composite
124} // namespace compiz
125#endif
0126
=== added directory 'plugins/composite/src/backbuffertracking/src'
=== added file 'plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp'
--- plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 1970-01-01 00:00:00 +0000
+++ plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp 2013-02-13 11:42:25 +0000
@@ -0,0 +1,214 @@
1/*
2 * Compiz, composite plugin, GLX_EXT_buffer_age logic
3 *
4 * Copyright (c) 2012 Sam Spilsbury
5 * Authors: Sam Spilsbury <smspillaz@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#include <deque>
26#include <core/size.h>
27#include <core/region.h>
28#include "backbuffertracking.h"
29#include <cstdio>
30
31namespace bt = compiz::composite::buffertracking;
32
33class bt::FrameRoster::Private
34{
35 public:
36
37 Private (const CompSize &size,
38 bt::AgeingDamageBufferObserver &observer,
39 const bt::FrameRoster::AreaShouldBeMarkedDirty &shouldBeMarkedDirty) :
40 screenSize (size),
41 observer (observer),
42 shouldBeMarkedDirty (shouldBeMarkedDirty),
43 oldFrames (1)
44 {
45 }
46
47 CompSize screenSize;
48 bt::AgeingDamageBufferObserver &observer;
49 bt::FrameRoster::AreaShouldBeMarkedDirty shouldBeMarkedDirty;
50 std::deque <CompRegion> oldFrames;
51};
52
53bt::FrameRoster::FrameRoster (const CompSize &size,
54 bt::AgeingDamageBufferObserver &tracker,
55 const AreaShouldBeMarkedDirty &shouldBeMarkedDirty) :
56 priv (new bt::FrameRoster::Private (size,
57 tracker,
58 shouldBeMarkedDirty))
59{
60 priv->observer.observe (*this);
61}
62
63bt::FrameRoster::~FrameRoster ()
64{
65 priv->observer.unobserve (*this);
66}
67
68CompRegion
69bt::FrameRoster::damageForFrameAge (unsigned int age)
70{
71 if (!age)
72 return CompRegion (0, 0,
73 priv->screenSize.width (),
74 priv->screenSize.height ());
75
76 if (age >= priv->oldFrames.size ())
77 return CompRegion (0, 0,
78 priv->screenSize.width (),
79 priv->screenSize.height ());
80
81 CompRegion accumulatedDamage;
82
83 while (age--)
84 {
85 unsigned int frameNum = (priv->oldFrames.size () - age) - 1;
86 accumulatedDamage += priv->oldFrames[frameNum];
87 }
88
89 return accumulatedDamage;
90}
91
92void
93bt::FrameRoster::dirtyAreaOnCurrentFrame (const CompRegion &r)
94{
95 if (priv->shouldBeMarkedDirty (r))
96 (*priv->oldFrames.rbegin ()) += r;
97}
98
99void
100bt::FrameRoster::subtractObscuredArea (const CompRegion &r)
101{
102 (*priv->oldFrames.rbegin ()) -= r;
103}
104
105void
106bt::FrameRoster::overdrawRegionOnPaintingFrame (const CompRegion &r)
107{
108 assert (priv->oldFrames.size () > 1);
109 std::deque <CompRegion>::reverse_iterator it = priv->oldFrames.rbegin ();
110 ++it;
111 (*it) += r;
112}
113
114void
115bt::FrameRoster::incrementFrameAges ()
116{
117 priv->oldFrames.push_back (CompRegion ());
118
119 /* Get rid of old frames */
120 if (priv->oldFrames.size () > NUM_TRACKED_FRAMES)
121 priv->oldFrames.pop_front ();
122}
123
124const CompRegion &
125bt::FrameRoster::currentFrameDamage ()
126{
127 return *priv->oldFrames.rbegin ();
128}
129
130class bt::AgeingDamageBuffers::Private
131{
132 public:
133
134 std::vector <bt::DamageAgeTracking *> damageAgeTrackers;
135};
136
137bt::AgeingDamageBuffers::AgeingDamageBuffers () :
138 priv (new bt::AgeingDamageBuffers::Private ())
139{
140}
141
142void
143bt::AgeingDamageBuffers::observe (bt::DamageAgeTracking &damageAgeTracker)
144{
145 priv->damageAgeTrackers.push_back (&damageAgeTracker);
146}
147
148void
149bt::AgeingDamageBuffers::unobserve (bt::DamageAgeTracking &damageAgeTracker)
150{
151 std::vector <bt::DamageAgeTracking *>::iterator it =
152 std::find (priv->damageAgeTrackers.begin (),
153 priv->damageAgeTrackers.end (),
154 &damageAgeTracker);
155
156 if (it != priv->damageAgeTrackers.end ())
157 priv->damageAgeTrackers.erase (it);
158}
159
160void
161bt::AgeingDamageBuffers::incrementAges ()
162{
163 for (std::vector <bt::DamageAgeTracking *>::iterator it =
164 priv->damageAgeTrackers.begin ();
165 it != priv->damageAgeTrackers.end ();
166 ++it)
167 {
168 bt::DamageAgeTracking *tracker = *it;
169
170 tracker->incrementFrameAges ();
171 }
172}
173
174void
175bt::AgeingDamageBuffers::markAreaDirty (const CompRegion &reg)
176{
177 for (std::vector <bt::DamageAgeTracking *>::iterator it =
178 priv->damageAgeTrackers.begin ();
179 it != priv->damageAgeTrackers.end ();
180 ++it)
181 {
182 bt::DamageAgeTracking *tracker = *it;
183
184 tracker->dirtyAreaOnCurrentFrame (reg);
185 }
186}
187
188void
189bt::AgeingDamageBuffers::subtractObscuredArea (const CompRegion &reg)
190{
191 for (std::vector <bt::DamageAgeTracking *>::iterator it =
192 priv->damageAgeTrackers.begin ();
193 it != priv->damageAgeTrackers.end ();
194 ++it)
195 {
196 bt::DamageAgeTracking *tracker = *it;
197
198 tracker->subtractObscuredArea (reg);
199 }
200}
201
202void
203bt::AgeingDamageBuffers::markAreaDirtyOnLastFrame (const CompRegion &reg)
204{
205 for (std::vector <bt::DamageAgeTracking *>::iterator it =
206 priv->damageAgeTrackers.begin ();
207 it != priv->damageAgeTrackers.end ();
208 ++it)
209 {
210 bt::DamageAgeTracking *tracker = *it;
211
212 tracker->overdrawRegionOnPaintingFrame (reg);
213 }
214}
0215
=== added directory 'plugins/composite/src/backbuffertracking/tests'
=== added file 'plugins/composite/src/backbuffertracking/tests/CMakeLists.txt'
--- plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/composite/src/backbuffertracking/tests/CMakeLists.txt 2013-02-13 11:42:25 +0000
@@ -0,0 +1,24 @@
1find_library (GMOCK_LIBRARY gmock)
2find_library (GMOCK_MAIN_LIBRARY gmock_main)
3
4if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
5 message ("Google Mock and Google Test not found - cannot build tests!")
6 set (COMPIZ_BUILD_TESTING OFF)
7endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
8
9include_directories (${GTEST_INCLUDE_DIRS})
10
11link_directories (${COMPIZ_LIBRARY_DIRS})
12
13add_executable (compiz_test_composite_backbuffertracking
14 ${CMAKE_CURRENT_SOURCE_DIR}/test-composite-backbuffertracking.cpp)
15
16target_link_libraries (compiz_test_composite_backbuffertracking
17 compiz_composite_backbuffertracking
18 ${GTEST_BOTH_LIBRARIES}
19 ${GMOCK_LIBRARY}
20 ${GMOCK_MAIN_LIBRARY}
21 ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
22 )
23
24compiz_discover_tests (compiz_test_composite_backbuffertracking COVERAGE compiz_composite_backbuffertracking)
025
=== added file 'plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp'
--- plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 1970-01-01 00:00:00 +0000
+++ plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp 2013-02-13 11:42:25 +0000
@@ -0,0 +1,450 @@
1/*
2 * Compiz, composite plugin, GLX_EXT_buffer_age logic
3 *
4 * Copyright (c) 2012 Sam Spilsbury
5 * Authors: Sam Spilsbury <smspillaz@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#include <boost/bind.hpp>
26
27#include <gtest/gtest.h>
28#include <gmock/gmock.h>
29
30#include <core/region.h>
31#include <core/size.h>
32
33#include "backbuffertracking.h"
34
35using ::testing::NiceMock;
36using ::testing::_;
37using ::testing::AtLeast;
38
39namespace bt = compiz::composite::buffertracking;
40
41namespace
42{
43class MockAgeingDamageBufferObserver :
44 public bt::AgeingDamageBufferObserver
45{
46 public:
47
48 MOCK_METHOD1 (observe, void (bt::DamageAgeTracking &));
49 MOCK_METHOD1 (unobserve, void (bt::DamageAgeTracking &));
50};
51
52bool alwaysTrackDamage (const CompRegion &)
53{
54 return true;
55}
56
57
58class BackbufferTracking :
59 public ::testing::Test
60{
61 public:
62
63 BackbufferTracking () :
64 screen (1000, 1000),
65 roster ()
66 {
67 }
68
69 virtual void SetUp ()
70 {
71 SetupRoster ();
72 }
73
74 virtual void SetupRoster ()
75 {
76 roster.reset (new bt::FrameRoster (screen,
77 niceTracker,
78 boost::bind (alwaysTrackDamage,
79 _1)));
80 }
81
82 protected:
83
84 CompSize screen;
85 NiceMock <MockAgeingDamageBufferObserver> niceTracker;
86 bt::FrameRoster::Ptr roster;
87};
88
89class BackbufferTrackingCallbacks :
90 public BackbufferTracking
91{
92 public:
93
94 BackbufferTrackingCallbacks () :
95 shouldDamage (false)
96 {
97 }
98
99 protected:
100
101 void allowDamage (bool allow)
102 {
103 shouldDamage = allow;
104 }
105
106 private:
107
108 virtual void SetupRoster ()
109 {
110 roster.reset (new bt::FrameRoster (screen,
111 niceTracker,
112 boost::bind (&BackbufferTrackingCallbacks::shouldDamageCallback,
113 this, _1)));
114 }
115
116 bool shouldDamageCallback (const CompRegion &)
117 {
118 return shouldDamage;
119 }
120
121 bool shouldDamage;
122};
123}
124
125std::ostream &
126operator<< (std::ostream &os, const CompRegion &reg)
127{
128 os << "Region with Bounding Rectangle : " <<
129 reg.boundingRect ().x () << " " <<
130 reg.boundingRect ().y () << " " <<
131 reg.boundingRect ().width () << " " <<
132 reg.boundingRect ().height () << std::endl;
133 CompRect::vector rects (reg.rects ());
134 for (CompRect::vector::iterator it = rects.begin ();
135 it != rects.end ();
136 it++)
137 os << " - subrectangle: " <<
138 (*it).x () << " " <<
139 (*it).y () << " " <<
140 (*it).width () << " " <<
141 (*it).height () << " " << std::endl;
142
143 return os;
144}
145
146TEST (BackbufferTrackingConstruction, CreateAddsToObserverList)
147{
148 MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver;
149
150 /* We can't verify the argument here,
151 * but we can verify the function call */
152 EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_));
153 EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_)).Times (AtLeast (0));
154 bt::FrameRoster roster (CompSize (),
155 mockAgeingDamageBufferObserver,
156 boost::bind (alwaysTrackDamage, _1));
157}
158
159TEST (BackbufferTrackingConstruction, DestroyRemovesFromObserverList)
160{
161 MockAgeingDamageBufferObserver mockAgeingDamageBufferObserver;
162
163 /* We can't verify the argument here,
164 * but we can verify the function call */
165 EXPECT_CALL (mockAgeingDamageBufferObserver, observe (_)).Times (AtLeast (0));
166 EXPECT_CALL (mockAgeingDamageBufferObserver, unobserve (_));
167 bt::FrameRoster roster (CompSize (),
168 mockAgeingDamageBufferObserver,
169 boost::bind (alwaysTrackDamage, _1));
170}
171
172TEST_F (BackbufferTrackingCallbacks, TrackIntoCurrentIfCallbackTrue)
173{
174 allowDamage (true);
175 CompRegion damage (100, 100, 100, 100);
176 roster->dirtyAreaOnCurrentFrame (damage);
177 EXPECT_EQ (damage, roster->currentFrameDamage ());
178}
179
180TEST_F (BackbufferTrackingCallbacks, NoTrackIntoCurrentIfCallbackFalse)
181{
182 allowDamage (false);
183 CompRegion damage (100, 100, 100, 100);
184 roster->dirtyAreaOnCurrentFrame (damage);
185 EXPECT_EQ (emptyRegion, roster->currentFrameDamage ());
186}
187
188TEST_F (BackbufferTracking, DirtyAreaSubtraction)
189{
190 CompRegion dirty (100, 100, 100, 100);
191 CompRegion obscured (150, 150, 50, 50);
192 roster->dirtyAreaOnCurrentFrame (dirty);
193 roster->subtractObscuredArea (obscured);
194 EXPECT_EQ (dirty - obscured, roster->currentFrameDamage ());
195}
196
197TEST_F (BackbufferTracking, DirtyAreaForAgeZeroAll)
198{
199 EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()),
200 roster->damageForFrameAge (0));
201}
202
203TEST_F (BackbufferTracking, DirtyAreaAllForOlderThanTrackedAge)
204{
205 EXPECT_EQ (CompRegion (0, 0, screen.width (), screen.height ()),
206 roster->damageForFrameAge (1));
207}
208
209TEST_F (BackbufferTracking, NoDirtyAreaForLastFrame)
210{
211 CompRegion all (0, 0, screen.width (), screen.height ());
212 roster->dirtyAreaOnCurrentFrame (all);
213 roster->incrementFrameAges ();
214 EXPECT_EQ (emptyRegion, roster->damageForFrameAge (1));
215}
216
217TEST_F (BackbufferTracking, DirtyAreaIfMoreSinceLastFrame)
218{
219 CompRegion all (0, 0, screen.width (), screen.height ());
220 roster->dirtyAreaOnCurrentFrame (all);
221 roster->incrementFrameAges ();
222 roster->dirtyAreaOnCurrentFrame(all);
223 EXPECT_EQ (all, roster->damageForFrameAge (1));
224}
225
226TEST_F (BackbufferTracking, AddOverdrawRegionForLastFrame)
227{
228 CompRegion all (0, 0, screen.width (), screen.height ());
229 roster->dirtyAreaOnCurrentFrame (all);
230 roster->incrementFrameAges ();
231 roster->incrementFrameAges ();
232 roster->overdrawRegionOnPaintingFrame (all);
233 EXPECT_EQ (all, roster->damageForFrameAge (2));
234}
235
236TEST_F (BackbufferTracking, TwoFramesAgo)
237{
238 CompRegion all (0, 0, screen.width (), screen.height ());
239 CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
240
241 roster->dirtyAreaOnCurrentFrame (all);
242 roster->incrementFrameAges ();
243 roster->dirtyAreaOnCurrentFrame (topleft);
244 roster->incrementFrameAges ();
245 EXPECT_EQ (topleft, roster->damageForFrameAge (2));
246}
247
248TEST_F (BackbufferTracking, TwoFramesAgoCulmulative)
249{
250 CompRegion all (0, 0, screen.width (), screen.height ());
251 CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
252 CompRegion topright (0, screen.width () / 2,
253 screen.width () / 2,
254 screen.height () / 2);
255
256 roster->dirtyAreaOnCurrentFrame (all);
257 roster->incrementFrameAges ();
258 roster->dirtyAreaOnCurrentFrame (topleft);
259 roster->dirtyAreaOnCurrentFrame (topright);
260 roster->incrementFrameAges ();
261 EXPECT_EQ (topleft + topright, roster->damageForFrameAge (2));
262}
263
264TEST_F (BackbufferTracking, ThreeFramesAgo)
265{
266 CompRegion all (0, 0, screen.width (), screen.height ());
267 CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
268 CompRegion bottomright (screen.width () / 2,
269 screen.height () / 2,
270 screen.width () / 2,
271 screen.height () / 2);
272
273 roster->dirtyAreaOnCurrentFrame (all);
274 roster->incrementFrameAges ();
275 roster->dirtyAreaOnCurrentFrame (topleft);
276 roster->incrementFrameAges ();
277 roster->dirtyAreaOnCurrentFrame (bottomright);
278 roster->incrementFrameAges ();
279
280 EXPECT_EQ (topleft + bottomright, roster->damageForFrameAge (3));
281}
282
283/* These are more or less functional tests from this point forward
284 * just checking a number of different situations */
285
286TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFrames)
287{
288 CompRegion all (0, 0, screen.width (), screen.height ());
289 CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
290 CompRegion bottomright (screen.width () / 2,
291 screen.height () / 2,
292 screen.width () / 2,
293 screen.height () / 2);
294 CompRegion topright (screen.width () / 2,
295 0,
296 screen.width () / 2,
297 screen.height () / 2);
298
299 roster->dirtyAreaOnCurrentFrame (all);
300 roster->incrementFrameAges ();
301 roster->dirtyAreaOnCurrentFrame (topleft);
302 roster->incrementFrameAges ();
303 roster->dirtyAreaOnCurrentFrame (bottomright);
304 roster->incrementFrameAges ();
305 roster->dirtyAreaOnCurrentFrame (topright);
306 roster->incrementFrameAges ();
307
308 EXPECT_EQ (topright + bottomright, roster->damageForFrameAge (3));
309}
310
311TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFramesAndOverlap)
312{
313 CompRegion all (0, 0, screen.width (), screen.height ());
314 CompRegion topleft (0, 0, screen.width () / 2, screen.height () / 2);
315 CompRegion bottomright (screen.width () / 2,
316 screen.height () / 2,
317 screen.width () / 2,
318 screen.height () / 2);
319 CompRegion topright (screen.width () / 2,
320 0,
321 screen.width () / 2,
322 screen.height () / 2);
323
324 roster->dirtyAreaOnCurrentFrame (all);
325 roster->incrementFrameAges ();
326 roster->dirtyAreaOnCurrentFrame (topleft);
327 roster->incrementFrameAges ();
328 roster->dirtyAreaOnCurrentFrame (bottomright);
329 roster->incrementFrameAges ();
330 roster->dirtyAreaOnCurrentFrame (bottomright);
331 roster->incrementFrameAges ();
332
333 EXPECT_EQ (bottomright, roster->damageForFrameAge (3));
334}
335
336TEST_F (BackbufferTracking, AllDamageForExceedingMaxTrackedFrames)
337{
338 CompRegion all (0, 0, screen.width (), screen.height ());
339 CompRegion damage (0, 0, 1, 1);
340
341 roster->dirtyAreaOnCurrentFrame (all);
342
343 for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES - 1; ++i)
344 {
345 roster->incrementFrameAges ();
346 roster->dirtyAreaOnCurrentFrame (damage);
347 }
348
349 EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES + 1));
350}
351
352TEST_F (BackbufferTracking, DamageForMaxTrackedFrame)
353{
354 CompRegion all (0, 0, screen.width (), screen.height ());
355 CompRegion damage (0, 0, 1, 1);
356
357 roster->dirtyAreaOnCurrentFrame (all);
358
359 for (unsigned int i = 0; i < bt::FrameRoster::NUM_TRACKED_FRAMES + 1; ++i)
360 {
361 roster->incrementFrameAges ();
362 roster->dirtyAreaOnCurrentFrame (damage);
363 }
364
365 EXPECT_EQ (all, roster->damageForFrameAge (bt::FrameRoster::NUM_TRACKED_FRAMES));
366}
367
368class MockDamageAgeTracking :
369 public bt::DamageAgeTracking
370{
371 public:
372
373 typedef boost::shared_ptr <MockDamageAgeTracking> Ptr;
374
375 MOCK_METHOD0 (incrementFrameAges, void ());
376 MOCK_METHOD1 (dirtyAreaOnCurrentFrame, void (const CompRegion &));
377 MOCK_METHOD1 (subtractObscuredArea, void (const CompRegion &));
378 MOCK_METHOD1 (overdrawRegionOnPaintingFrame, void (const CompRegion &));
379};
380
381class AgeingDamageBuffers :
382 public ::testing::Test
383{
384 public:
385
386 AgeingDamageBuffers ()
387 {
388 ageing.observe (mockDamageAgeTracker);
389 }
390
391 MockDamageAgeTracking mockDamageAgeTracker;
392 bt::AgeingDamageBuffers ageing;
393};
394
395TEST_F (AgeingDamageBuffers, IncrementAgesOnValidRosters)
396{
397 EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ());
398 ageing.incrementAges ();
399}
400
401TEST_F (AgeingDamageBuffers, DirtyAreaOnValidRosters)
402{
403 CompRegion dirtyArea (100, 100, 100, 100);
404 EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (dirtyArea));
405 ageing.markAreaDirty (dirtyArea);
406}
407
408TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnValidRosters)
409{
410 CompRegion obscuredArea (100, 100, 100, 100);
411 EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (obscuredArea));
412 ageing.subtractObscuredArea (obscuredArea);
413}
414
415TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnValidRosters)
416{
417 CompRegion overdrawArea (100, 100, 100, 100);
418 EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (overdrawArea));
419 ageing.markAreaDirtyOnLastFrame (overdrawArea);
420}
421
422TEST_F (AgeingDamageBuffers, IncrementAgesOnInvalidRosters)
423{
424 EXPECT_CALL (mockDamageAgeTracker, incrementFrameAges ()).Times (0);
425 ageing.unobserve (mockDamageAgeTracker);
426 ageing.incrementAges ();
427}
428
429TEST_F (AgeingDamageBuffers, DirtyAreaOnInvalidRosters)
430{
431 EXPECT_CALL (mockDamageAgeTracker, dirtyAreaOnCurrentFrame (_)).Times (0);
432 ageing.unobserve (mockDamageAgeTracker);
433 ageing.markAreaDirty (emptyRegion);
434}
435
436TEST_F (AgeingDamageBuffers, SubtractObscuredAreaOnInvalidRosters)
437{
438 EXPECT_CALL (mockDamageAgeTracker, subtractObscuredArea (_)).Times (0);
439 ageing.unobserve (mockDamageAgeTracker);
440 ageing.subtractObscuredArea (emptyRegion);
441}
442
443TEST_F (AgeingDamageBuffers, AddOverdrawAreaOnInvalidRosters)
444{
445 EXPECT_CALL (mockDamageAgeTracker, overdrawRegionOnPaintingFrame (_)).Times (0);
446 ageing.unobserve (mockDamageAgeTracker);
447 ageing.markAreaDirtyOnLastFrame (emptyRegion);
448}
449
450
0451
=== modified file 'plugins/composite/src/privates.h'
--- plugins/composite/src/privates.h 2012-09-20 09:35:40 +0000
+++ plugins/composite/src/privates.h 2013-02-13 11:42:25 +0000
@@ -36,12 +36,20 @@
36#include <map>36#include <map>
3737
38#include "pixmapbinding.h"38#include "pixmapbinding.h"
39#include "backbuffertracking.h"
39#include "composite_options.h"40#include "composite_options.h"
4041
41extern CompPlugin::VTable *compositeVTable;42extern CompPlugin::VTable *compositeVTable;
4243
43extern CompWindow *lastDamagedWindow;44extern CompWindow *lastDamagedWindow;
4445
46enum DamageTracking
47{
48 DamageForCurrentFrame = 0,
49 DamageForLastFrame = 1,
50 DamageFinalPaintRegion
51};
52
45class PrivateCompositeScreen :53class PrivateCompositeScreen :
46 ScreenInterface,54 ScreenInterface,
47 public CompositeOptions55 public CompositeOptions
@@ -66,6 +74,8 @@
6674
67 void scheduleRepaint ();75 void scheduleRepaint ();
6876
77 const CompRegion * damageTrackedBuffer (const CompRegion &);
78
69 public:79 public:
7080
71 CompositeScreen *cScreen;81 CompositeScreen *cScreen;
@@ -80,10 +90,12 @@
80 bool randrExtension;90 bool randrExtension;
81 int randrEvent, randrError;91 int randrEvent, randrError;
8292
83 CompRegion damage;93 CompRegion lastFrameDamage;
84 unsigned long damageMask;94 unsigned long damageMask;
8595
86 CompRegion tmpRegion;96 CompRegion tmpRegion;
97
98 DamageTracking currentlyTrackingDamage;
8799
88 Window overlay;100 Window overlay;
89 Window output;101 Window output;
@@ -99,6 +111,7 @@
99 int redrawTime;111 int redrawTime;
100 int optimalRedrawTime;112 int optimalRedrawTime;
101 bool scheduled, painting, reschedule;113 bool scheduled, painting, reschedule;
114 bool damageRequiresRepaintReschedule;
102115
103 bool slowAnimations;116 bool slowAnimations;
104117
@@ -115,6 +128,9 @@
115128
116 /* Map Damage handle to its bounding box */129 /* Map Damage handle to its bounding box */
117 std::map<Damage, XRectangle> damages;130 std::map<Damage, XRectangle> damages;
131
132 compiz::composite::buffertracking::AgeingDamageBuffers ageingBuffers;
133 compiz::composite::buffertracking::FrameRoster roster;
118};134};
119135
120class PrivateCompositeWindow :136class PrivateCompositeWindow :
121137
=== modified file 'plugins/composite/src/screen.cpp'
--- plugins/composite/src/screen.cpp 2013-01-28 19:22:29 +0000
+++ plugins/composite/src/screen.cpp 2013-02-13 11:42:25 +0000
@@ -47,6 +47,8 @@
4747
48template class WrapableInterface<CompositeScreen, CompositeScreenInterface>;48template class WrapableInterface<CompositeScreen, CompositeScreenInterface>;
4949
50namespace bt = compiz::composite::buffertracking;
51
50static const int FALLBACK_REFRESH_RATE = 60; /* if all else fails */52static const int FALLBACK_REFRESH_RATE = 60; /* if all else fails */
5153
52CompWindow *lastDamagedWindow = 0;54CompWindow *lastDamagedWindow = 0;
@@ -276,6 +278,14 @@
276 delete priv;278 delete priv;
277}279}
278280
281namespace
282{
283bool alwaysMarkDirty ()
284{
285 return true;
286}
287}
288
279289
280PrivateCompositeScreen::PrivateCompositeScreen (CompositeScreen *cs) :290PrivateCompositeScreen::PrivateCompositeScreen (CompositeScreen *cs) :
281 cScreen (cs),291 cScreen (cs),
@@ -294,6 +304,7 @@
294 randrEvent (0),304 randrEvent (0),
295 randrError (0),305 randrError (0),
296 damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK),306 damageMask (COMPOSITE_SCREEN_DAMAGE_ALL_MASK),
307 currentlyTrackingDamage (DamageForCurrentFrame),
297 overlay (None),308 overlay (None),
298 output (None),309 output (None),
299 exposeRects (),310 exposeRects (),
@@ -305,12 +316,16 @@
305 scheduled (false),316 scheduled (false),
306 painting (false),317 painting (false),
307 reschedule (false),318 reschedule (false),
319 damageRequiresRepaintReschedule (true),
308 slowAnimations (false),320 slowAnimations (false),
309 pHnd (NULL),321 pHnd (NULL),
310 FPSLimiterMode (CompositeFPSLimiterModeDefault),322 FPSLimiterMode (CompositeFPSLimiterModeDefault),
311 withDestroyedWindows (),323 withDestroyedWindows (),
312 cmSnAtom (0),324 cmSnAtom (0),
313 newCmSnOwner (None)325 newCmSnOwner (None),
326 roster (*screen,
327 ageingBuffers,
328 boost::bind (alwaysMarkDirty))
314{329{
315 gettimeofday (&lastRedraw, 0);330 gettimeofday (&lastRedraw, 0);
316 // wrap outputChangeNotify331 // wrap outputChangeNotify
@@ -491,15 +506,47 @@
491 return false;506 return false;
492}507}
493508
509const CompRegion *
510PrivateCompositeScreen::damageTrackedBuffer (const CompRegion &region)
511{
512 const CompRegion *currentDamage = NULL;
513
514 switch (currentlyTrackingDamage)
515 {
516 case DamageForCurrentFrame:
517 currentDamage = &(roster.currentFrameDamage ());
518 ageingBuffers.markAreaDirty (region);
519 break;
520 case DamageForLastFrame:
521 currentDamage = &(lastFrameDamage);
522 lastFrameDamage += region;
523 break;
524 case DamageFinalPaintRegion:
525 currentDamage = &(tmpRegion);
526 tmpRegion += region;
527 break;
528 default:
529 compLogMessage ("composite", CompLogLevelFatal, "unreachable section");
530 assert (false);
531 abort ();
532 }
533
534 assert (currentDamage);
535 return currentDamage;
536}
537
494void538void
495CompositeScreen::damageScreen ()539CompositeScreen::damageScreen ()
496{540{
541 /* Don't tell plugins about damage events when the damage buffer is already full */
497 bool alreadyDamaged = priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK;542 bool alreadyDamaged = priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
543 alreadyDamaged |= ((currentDamage () & screen->region ()) == screen->region ());
498544
499 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;545 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
500 priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;546 priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
501547
502 priv->scheduleRepaint ();548 if (priv->damageRequiresRepaintReschedule)
549 priv->scheduleRepaint ();
503550
504 /*551 /*
505 * Call through damageRegion since plugins listening for incoming damage552 * Call through damageRegion since plugins listening for incoming damage
@@ -507,7 +554,15 @@
507 */554 */
508555
509 if (!alreadyDamaged)556 if (!alreadyDamaged)
557 {
510 damageRegion (CompRegion (0, 0, screen->width (), screen->height ()));558 damageRegion (CompRegion (0, 0, screen->width (), screen->height ()));
559
560 /* Set the damage region as the fullscreen region, because if
561 * windows are unredirected we need to correctly subtract from
562 * it later
563 */
564 priv->damageTrackedBuffer (screen->region ());
565 }
511}566}
512567
513void568void
@@ -518,7 +573,12 @@
518 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)573 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
519 return;574 return;
520575
521 priv->damage += region;576 /* Don't cause repaints to be scheduled for empty damage
577 * regions */
578 if (region.isEmpty ())
579 return;
580
581 const CompRegion *currentDamage = priv->damageTrackedBuffer (region);
522 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;582 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
523583
524 /* if the number of damage rectangles grows two much between repaints,584 /* if the number of damage rectangles grows two much between repaints,
@@ -526,16 +586,61 @@
526 in order to make sure we're not having too much overhead, damage586 in order to make sure we're not having too much overhead, damage
527 the whole screen if we have a lot of damage rects */587 the whole screen if we have a lot of damage rects */
528588
529 if (priv->damage.numRects () > 100)589 if (currentDamage->numRects () > 100)
530 damageScreen ();590 damageScreen ();
531 priv->scheduleRepaint ();591
592 if (priv->damageRequiresRepaintReschedule)
593 priv->scheduleRepaint ();
594}
595
596void
597CompositeScreen::damageCutoff ()
598{
599 WRAPABLE_HND_FUNCTN (damageCutoff);
532}600}
533601
534void602void
535CompositeScreen::damagePending ()603CompositeScreen::damagePending ()
536{604{
537 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;605 priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;
538 priv->scheduleRepaint ();606
607 if (priv->damageRequiresRepaintReschedule)
608 priv->scheduleRepaint ();
609}
610
611void
612CompositeScreen::applyDamageForFrameAge (unsigned int age)
613{
614 /* Track into "last frame damage" */
615 priv->currentlyTrackingDamage = DamageForLastFrame;
616 damageRegion (priv->roster.damageForFrameAge (age));
617 priv->currentlyTrackingDamage = DamageForCurrentFrame;
618}
619
620unsigned int
621CompositeScreen::getFrameAge ()
622{
623 if (priv->pHnd)
624 return priv->pHnd->getFrameAge ();
625
626 return 1;
627}
628
629void
630CompositeScreen::addOverdrawDamageRegion (const CompRegion &r)
631{
632 priv->ageingBuffers.markAreaDirtyOnLastFrame (r);
633}
634
635typedef CompositeScreen::AreaShouldBeMarkedDirty ShouldMarkDirty;
636
637CompositeScreen::DamageQuery::Ptr
638CompositeScreen::getDamageQuery (const ShouldMarkDirty &callback)
639{
640 /* No initial damage */
641 return bt::FrameRoster::Ptr (new bt::FrameRoster (CompSize (),
642 priv->ageingBuffers,
643 callback));
539}644}
540645
541unsigned int646unsigned int
@@ -780,6 +885,10 @@
780 {885 {
781 int timeDiff;886 int timeDiff;
782887
888 /* Damage that accumulates here does not require a repaint reschedule
889 * as it will end up on this frame */
890 priv->damageRequiresRepaintReschedule = false;
891
783 if (priv->pHnd)892 if (priv->pHnd)
784 priv->pHnd->prepareDrawing ();893 priv->pHnd->prepareDrawing ();
785894
@@ -814,7 +923,7 @@
814 continue;923 continue;
815924
816 if (!CompositeWindow::get (w)->redirected ())925 if (!CompositeWindow::get (w)->redirected ())
817 priv->damage -= w->region ();926 priv->ageingBuffers.subtractObscuredArea (w->region ());
818927
819 break;928 break;
820 }929 }
@@ -826,7 +935,13 @@
826 }935 }
827 }936 }
828937
829 priv->tmpRegion = priv->damage & screen->region ();938 /* All further damage is for the next frame now, as
939 * priv->tmpRegion will be assigned. Notify plugins that do
940 * damage tracking of this */
941 damageCutoff ();
942
943 priv->tmpRegion = (priv->roster.currentFrameDamage () + priv->lastFrameDamage) & screen->region ();
944 priv->currentlyTrackingDamage = DamageFinalPaintRegion;
830945
831 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)946 if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
832 {947 {
@@ -848,7 +963,9 @@
848 XSync (dpy, False);963 XSync (dpy, False);
849 priv->damages.clear ();964 priv->damages.clear ();
850965
851 priv->damage = CompRegion ();966 /* Any more damage requires a repaint reschedule */
967 priv->damageRequiresRepaintReschedule = true;
968 priv->lastFrameDamage = CompRegion ();
852969
853 int mask = priv->damageMask;970 int mask = priv->damageMask;
854 priv->damageMask = 0;971 priv->damageMask = 0;
@@ -864,9 +981,13 @@
864 else981 else
865 outputs.push_back (&screen->fullscreenOutput ());982 outputs.push_back (&screen->fullscreenOutput ());
866983
984 priv->currentlyTrackingDamage = DamageForCurrentFrame;
985
986 /* All new damage goes on the next frame */
987 priv->ageingBuffers.incrementAges ();
988
867 paint (outputs, mask);989 paint (outputs, mask);
868990
869
870 donePaint ();991 donePaint ();
871992
872 priv->outputShapeChanged = false;993 priv->outputShapeChanged = false;
@@ -1023,8 +1144,12 @@
1023CompositeScreenInterface::damageRegion (const CompRegion &r)1144CompositeScreenInterface::damageRegion (const CompRegion &r)
1024 WRAPABLE_DEF (damageRegion, r);1145 WRAPABLE_DEF (damageRegion, r);
10251146
1147void
1148CompositeScreenInterface::damageCutoff ()
1149 WRAPABLE_DEF (damageCutoff);
1150
1026const CompRegion &1151const CompRegion &
1027CompositeScreen::currentDamage () const1152CompositeScreen::currentDamage () const
1028{1153{
1029 return priv->damage;1154 return priv->roster.currentFrameDamage ();
1030}1155}
10311156
=== modified file 'plugins/kdecompat/src/kdecompat.cpp'
--- plugins/kdecompat/src/kdecompat.cpp 2012-08-14 06:33:22 +0000
+++ plugins/kdecompat/src/kdecompat.cpp 2013-02-13 11:42:25 +0000
@@ -196,7 +196,7 @@
196 if ((!(ks->optionGetPlasmaThumbnails () || mPreviews.empty ()) &&196 if ((!(ks->optionGetPlasmaThumbnails () || mPreviews.empty ()) &&
197 !(mSlideData || mSlideData->remaining)) ||197 !(mSlideData || mSlideData->remaining)) ||
198 !window->mapNum () ||198 !window->mapNum () ||
199 (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))199 (mask & PAINT_WINDOW_NO_DRAW_MASKS))
200 {200 {
201 status = gWindow->glPaint (attrib, transform, region, mask);201 status = gWindow->glPaint (attrib, transform, region, mask);
202 return status;202 return status;
@@ -210,7 +210,7 @@
210 CompRect clipBox (window->x (), window->y (),210 CompRect clipBox (window->x (), window->y (),
211 window->width (), window->height ());211 window->width (), window->height ());
212212
213 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)213 if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
214 return false;214 return false;
215215
216 remainder = (float) data->remaining / data->duration;216 remainder = (float) data->remaining / data->duration;
217217
=== modified file 'plugins/opengl/include/opengl/opengl.h'
--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
+++ plugins/opengl/include/opengl/opengl.h 2013-02-13 11:42:25 +0000
@@ -37,6 +37,13 @@
37#else37#else
38#include <GL/gl.h>38#include <GL/gl.h>
39#include <GL/glx.h>39#include <GL/glx.h>
40
41/* Some implementations have not yet given a definition
42 * to GLX_BACK_BUFFER_AGE_EXT but this is the token as defined
43 * in the spec (https://www.opengl.org/registry/specs/EXT/glx_buffer_age.txt)
44 */
45#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
46
40#endif47#endif
4148
42#include <core/size.h>49#include <core/size.h>
@@ -50,7 +57,7 @@
50#include <opengl/programcache.h>57#include <opengl/programcache.h>
51#include <opengl/shadercache.h>58#include <opengl/shadercache.h>
5259
53#define COMPIZ_OPENGL_ABI 660#define COMPIZ_OPENGL_ABI 8
5461
55/*62/*
56 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but63 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
@@ -525,6 +532,7 @@
525 extern bool shaders;532 extern bool shaders;
526 extern bool stencilBuffer;533 extern bool stencilBuffer;
527 extern GLint maxTextureUnits;534 extern GLint maxTextureUnits;
535 extern bool bufferAge;
528536
529 extern bool canDoSaturated;537 extern bool canDoSaturated;
530 extern bool canDoSlightlySaturated;538 extern bool canDoSlightlySaturated;
@@ -663,6 +671,11 @@
663 unsigned int mask);671 unsigned int mask);
664672
665 /**673 /**
674 * Return true if glPaintCompositedOutput is required for this frame
675 */
676 virtual bool glPaintCompositedOutputRequired ();
677
678 /**
666 * Hookable function used by plugins to determine stenciling mask679 * Hookable function used by plugins to determine stenciling mask
667 */680 */
668 virtual void glBufferStencil (const GLMatrix &matrix,681 virtual void glBufferStencil (const GLMatrix &matrix,
@@ -674,7 +687,7 @@
674extern template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>;687extern template class PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>;
675688
676class GLScreen :689class GLScreen :
677 public WrapableHandler<GLScreenInterface, 8>,690 public WrapableHandler<GLScreenInterface, 9>,
678 public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>,691 public PluginClassHandler<GLScreen, CompScreen, COMPIZ_OPENGL_ABI>,
679 public CompOption::Class692 public CompOption::Class
680{693{
@@ -788,7 +801,9 @@
788 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,801 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
789 const CompRegion &, GLFramebufferObject *, unsigned int);802 const CompRegion &, GLFramebufferObject *, unsigned int);
790803
791 WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,804 WRAPABLE_HND (7, GLScreenInterface, bool, glPaintCompositedOutputRequired);
805
806 WRAPABLE_HND (8, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
792 GLVertexBuffer &,807 GLVertexBuffer &,
793 CompOutput *);808 CompOutput *);
794809
795810
=== modified file 'plugins/opengl/src/doublebuffer/src/double-buffer.cpp'
--- plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-11-09 06:13:00 +0000
+++ plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2013-02-13 11:42:25 +0000
@@ -26,6 +26,7 @@
2626
27#include <cstdlib>27#include <cstdlib>
28#include <cassert>28#include <cassert>
29#include <cstdio>
29#include "opengl/doublebuffer.h"30#include "opengl/doublebuffer.h"
3031
31using namespace compiz::opengl;32using namespace compiz::opengl;
@@ -77,9 +78,7 @@
7778
78 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&79 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&
79 !setting[HAVE_PERSISTENT_BACK_BUFFER])80 !setting[HAVE_PERSISTENT_BACK_BUFFER])
80 {
81 copyFrontToBack ();81 copyFrontToBack ();
82 }
83 }82 }
84 else83 else
85 {84 {
8685
=== modified file 'plugins/opengl/src/framebufferobject.cpp'
--- plugins/opengl/src/framebufferobject.cpp 2012-08-06 09:44:49 +0000
+++ plugins/opengl/src/framebufferobject.cpp 2013-02-13 11:42:25 +0000
@@ -131,7 +131,7 @@
131131
132 (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,132 (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,
133 priv->glTex->target (),133 priv->glTex->target (),
134 priv->glTex->name (), 0);134 priv->glTex->name (), 0);
135135
136 priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);136 priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);
137137
138138
=== modified file 'plugins/opengl/src/paint.cpp'
--- plugins/opengl/src/paint.cpp 2013-01-01 10:04:50 +0000
+++ plugins/opengl/src/paint.cpp 2013-02-13 11:42:25 +0000
@@ -626,8 +626,8 @@
626 if (mask & PAINT_SCREEN_FULL_MASK)626 if (mask & PAINT_SCREEN_FULL_MASK)
627 {627 {
628 glPaintTransformedOutput (sAttrib, sTransform,628 glPaintTransformedOutput (sAttrib, sTransform,
629 CompRegion (*output), output, mask);629 CompRegionRef (output->region ()), output, mask);
630630 priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
631 return true;631 return true;
632 }632 }
633633
@@ -657,8 +657,9 @@
657 }657 }
658 else if (mask & PAINT_SCREEN_FULL_MASK)658 else if (mask & PAINT_SCREEN_FULL_MASK)
659 {659 {
660 glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output),660 glPaintTransformedOutput (sAttrib, sTransform, CompRegionRef (output->region ()),
661 output, mask);661 output, mask);
662 priv->cScreen->addOverdrawDamageRegion (CompRegionRef (output->region ()));
662663
663 return true;664 return true;
664 }665 }
@@ -668,6 +669,13 @@
668 }669 }
669}670}
670671
672bool
673GLScreen::glPaintCompositedOutputRequired ()
674{
675 WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintCompositedOutputRequired);
676 return false;
677}
678
671void679void
672GLScreen::glPaintCompositedOutput (const CompRegion &region,680GLScreen::glPaintCompositedOutput (const CompRegion &region,
673 GLFramebufferObject *fbo,681 GLFramebufferObject *fbo,
674682
=== modified file 'plugins/opengl/src/privates.h'
--- plugins/opengl/src/privates.h 2013-01-01 09:41:41 +0000
+++ plugins/opengl/src/privates.h 2013-02-13 11:42:25 +0000
@@ -29,6 +29,9 @@
29#define _OPENGL_PRIVATES_H29#define _OPENGL_PRIVATES_H
3030
31#include <memory>31#include <memory>
32#include <vector>
33#include <tr1/tuple>
34#include <boost/shared_ptr.hpp>
3235
33#include <composite/composite.h>36#include <composite/composite.h>
34#include <opengl/opengl.h>37#include <opengl/opengl.h>
@@ -119,8 +122,26 @@
119 GLTexture::List textures;122 GLTexture::List textures;
120};123};
121124
125class FrameProvider
126{
127 public:
128
129 typedef boost::shared_ptr <FrameProvider> Ptr;
130 typedef std::tr1::tuple <GLFramebufferObject *, int> Frame;
131
132 virtual ~FrameProvider () {}
133
134 virtual GLuint getCurrentFrame () = 0;
135 virtual void endFrame () = 0;
136
137 virtual bool providesPersistence () = 0;
138 virtual bool alwaysPostprocess () = 0;
139 virtual void invalidateAll () = 0;
140};
141
122class PrivateGLScreen :142class PrivateGLScreen :
123 public ScreenInterface,143 public ScreenInterface,
144 public CompositeScreenInterface,
124 public compiz::composite::PaintHandler,145 public compiz::composite::PaintHandler,
125 public OpenglOptions146 public OpenglOptions
126{147{
@@ -141,12 +162,16 @@
141 bool hasVSync ();162 bool hasVSync ();
142 bool requiredForcedRefreshRate ();163 bool requiredForcedRefreshRate ();
143164
165 unsigned int getFrameAge ();
166
144 void updateRenderMode ();167 void updateRenderMode ();
145168
146 void prepareDrawing ();169 void prepareDrawing ();
147170
148 bool compositingActive ();171 bool compositingActive ();
149172
173 void damageCutoff ();
174
150 void paintBackground (const GLMatrix &transform,175 void paintBackground (const GLMatrix &transform,
151 const CompRegion &region,176 const CompRegion &region,
152 bool transformed);177 bool transformed);
@@ -162,6 +187,8 @@
162187
163 bool driverIsBlacklisted (const char *regex) const;188 bool driverIsBlacklisted (const char *regex) const;
164189
190 bool postprocessRequiredForCurrentFrame ();
191
165 public:192 public:
166193
167 GLScreen *gScreen;194 GLScreen *gScreen;
@@ -196,7 +223,7 @@
196 GLXDoubleBuffer doubleBuffer;223 GLXDoubleBuffer doubleBuffer;
197 #endif224 #endif
198225
199 GLFramebufferObject *scratchFbo;226 boost::shared_ptr <GLFramebufferObject> scratchFbo;
200 CompRegion outputRegion;227 CompRegion outputRegion;
201228
202 XRectangle lastViewport;229 XRectangle lastViewport;
@@ -221,8 +248,10 @@
221 Pixmap rootPixmapCopy;248 Pixmap rootPixmapCopy;
222 CompSize rootPixmapSize;249 CompSize rootPixmapSize;
223250
251 FrameProvider::Ptr frameProvider;
224 const char *glVendor, *glRenderer, *glVersion;252 const char *glVendor, *glRenderer, *glVersion;
225253
254 bool postprocessingRequired;
226 mutable CompString prevRegex;255 mutable CompString prevRegex;
227 mutable bool prevBlacklisted;256 mutable bool prevBlacklisted;
228};257};
229258
=== modified file 'plugins/opengl/src/screen.cpp'
--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
+++ plugins/opengl/src/screen.cpp 2013-02-13 11:42:25 +0000
@@ -186,6 +186,7 @@
186 bool vboEnabled = false;186 bool vboEnabled = false;
187 bool shaders = false;187 bool shaders = false;
188 GLint maxTextureUnits = 1;188 GLint maxTextureUnits = 1;
189 bool bufferAge = false;
189190
190 bool canDoSaturated = false;191 bool canDoSaturated = false;
191 bool canDoSlightlySaturated = false;192 bool canDoSlightlySaturated = false;
@@ -301,6 +302,52 @@
301302
302#ifndef USE_GLES303#ifndef USE_GLES
303304
305class BufferAgeFrameProvider :
306 public FrameProvider
307{
308 public:
309
310 BufferAgeFrameProvider (Display *disp,
311 GLXDrawable drawable) :
312 mDisplay (disp),
313 mDrawable (drawable)
314 {
315 }
316
317 unsigned int getCurrentFrame ()
318 {
319 unsigned int age = 0;
320 (*GL::queryDrawable) (mDisplay,
321 mDrawable,
322 GLX_BACK_BUFFER_AGE_EXT,
323 &age);
324 return age;
325 }
326
327 void endFrame ()
328 {
329 }
330
331 void invalidateAll ()
332 {
333 }
334
335 bool providesPersistence ()
336 {
337 return true;
338 }
339
340 bool alwaysPostprocess ()
341 {
342 return false;
343 }
344
345 private:
346
347 Display *mDisplay;
348 GLXDrawable mDrawable;
349};
350
304namespace compiz351namespace compiz
305{352{
306namespace opengl353namespace opengl
@@ -358,6 +405,137 @@
358405
359#endif406#endif
360407
408class UndefinedFrameProvider :
409 public FrameProvider
410{
411 public:
412
413 unsigned int getCurrentFrame ()
414 {
415 return 0;
416 }
417
418 void endFrame ()
419 {
420 }
421
422 void invalidateAll ()
423 {
424 }
425
426 bool providesPersistence ()
427 {
428 return false;
429 }
430
431 bool alwaysPostprocess ()
432 {
433 return false;
434 }
435};
436
437class PostprocessFrameProvider :
438 public FrameProvider
439{
440 public:
441
442 PostprocessFrameProvider (GLFramebufferObject *object) :
443 mObject (object),
444 mAge (0)
445 {
446 }
447
448 unsigned int getCurrentFrame ()
449 {
450 /* We are now using this buffer, reset
451 * age back to zero */
452 unsigned int lastAge = mAge;
453 mAge = 0;
454
455 return lastAge;
456 }
457
458 void endFrame ()
459 {
460 ++mAge;
461 }
462
463 void invalidateAll ()
464 {
465 mAge = 0;
466 }
467
468 bool providesPersistence ()
469 {
470 return true;
471 }
472
473 bool alwaysPostprocess ()
474 {
475 return true;
476 }
477
478 private:
479
480 GLFramebufferObject *mObject;
481 unsigned int mAge;
482};
483
484class OptionalPostprocessFrameProvider :
485 public FrameProvider
486{
487 public:
488
489 typedef boost::function <bool ()> PostprocessRequired;
490
491 OptionalPostprocessFrameProvider (const FrameProvider::Ptr &backbuffer,
492 const FrameProvider::Ptr &scratchbuffer,
493 const PostprocessRequired &ppRequired) :
494 mBackbuffer (backbuffer),
495 mScratchbuffer (scratchbuffer),
496 mPPRequired (ppRequired)
497 {
498 }
499
500 unsigned int getCurrentFrame ()
501 {
502 if (mPPRequired ())
503 return mScratchbuffer->getCurrentFrame ();
504 else
505 return mBackbuffer->getCurrentFrame ();
506 }
507
508 void endFrame ()
509 {
510 mScratchbuffer->endFrame ();
511 }
512
513 void invalidateAll ()
514 {
515 mScratchbuffer->invalidateAll ();
516 }
517
518 bool providesPersistence ()
519 {
520 /* We are only as good as the backbuffer is */
521 return mBackbuffer->providesPersistence ();
522 }
523
524 bool alwaysPostprocess ()
525 {
526 if (mPPRequired ())
527 return mScratchbuffer->alwaysPostprocess ();
528 else
529 return mBackbuffer->alwaysPostprocess ();
530 }
531
532 private:
533
534 FrameProvider::Ptr mBackbuffer;
535 FrameProvider::Ptr mScratchbuffer;
536 PostprocessRequired mPPRequired;
537};
538
361bool539bool
362GLScreen::glInitContext (XVisualInfo *visinfo)540GLScreen::glInitContext (XVisualInfo *visinfo)
363{541{
@@ -593,6 +771,8 @@
593771
594 priv->incorrectRefreshRate = false;772 priv->incorrectRefreshRate = false;
595773
774 priv->frameProvider.reset (new PostprocessFrameProvider ());
775
596 #else776 #else
597777
598 Display *dpy = screen->dpy ();778 Display *dpy = screen->dpy ();
@@ -899,12 +1079,48 @@
8991079
900 if (GL::fboSupported)1080 if (GL::fboSupported)
901 {1081 {
902 priv->scratchFbo = new GLFramebufferObject;1082 priv->scratchFbo.reset (new GLFramebufferObject ());
903 priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);1083 priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
904 }1084 }
9051085
906 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);1086 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
9071087
1088 /* We need scratchFbo to be set before doing this, and it is common
1089 * to both the GLES and non-GLES codepaths, so using another #ifdef
1090 */
1091#ifndef USE_GLES
1092 const Window outputWindow = CompositeScreen::get (screen)->output ();
1093
1094 if (GL::fboEnabled)
1095 {
1096 if (GL::bufferAge)
1097 {
1098 FrameProvider::Ptr back (new BufferAgeFrameProvider (screen->dpy (),
1099 outputWindow));
1100 FrameProvider::Ptr scratch (new PostprocessFrameProvider (priv->scratchFbo.get ()));
1101 OptionalPostprocessFrameProvider::PostprocessRequired ppReq
1102 (boost::bind (&PrivateGLScreen::postprocessRequiredForCurrentFrame,
1103 priv));
1104 priv->frameProvider.reset (new OptionalPostprocessFrameProvider (back,
1105 scratch,
1106 ppReq));
1107 }
1108 else
1109 {
1110 /* Prefer using FBO's instead of switching between a defined/undefined backbuffer */
1111 priv->frameProvider.reset (new PostprocessFrameProvider (priv->scratchFbo.get ()));
1112 }
1113 }
1114 else
1115 {
1116 if (GL::bufferAge)
1117 priv->frameProvider.reset (new BufferAgeFrameProvider (screen->dpy (),
1118 outputWindow));
1119 else
1120 priv->frameProvider.reset (new UndefinedFrameProvider ());
1121 }
1122#endif
1123
908 return true;1124 return true;
909}1125}
9101126
@@ -993,6 +1209,13 @@
993 return;1209 return;
994 }1210 }
9951211
1212 if (strstr (glxExtensions, "GLX_EXT_buffer_age"))
1213 {
1214 compLogMessage ("opengl", CompLogLevelInfo,
1215 "GLX_EXT_buffer_age is supported");
1216 GL::bufferAge = true;
1217 }
1218
996 priv->getProcAddress = (GL::GLXGetProcAddressProc)1219 priv->getProcAddress = (GL::GLXGetProcAddressProc)
997 getProcAddress ("glXGetProcAddressARB");1220 getProcAddress ("glXGetProcAddressARB");
998 GL::bindTexImage = (GL::GLXBindTexImageProc)1221 GL::bindTexImage = (GL::GLXBindTexImageProc)
@@ -1209,9 +1432,6 @@
1209 glXDestroyContext (screen->dpy (), priv->ctx);1432 glXDestroyContext (screen->dpy (), priv->ctx);
1210 #endif1433 #endif
12111434
1212 if (priv->scratchFbo)
1213 delete priv->scratchFbo;
1214
1215 delete priv;1435 delete priv;
1216}1436}
12171437
@@ -1233,7 +1453,7 @@
1233 ctx (EGL_NO_CONTEXT),1453 ctx (EGL_NO_CONTEXT),
1234 doubleBuffer (screen->dpy (), *screen, surface),1454 doubleBuffer (screen->dpy (), *screen, surface),
1235 #endif1455 #endif
1236 scratchFbo (NULL),1456 scratchFbo (),
1237 outputRegion (),1457 outputRegion (),
1238 refreshSubBuffer (false),1458 refreshSubBuffer (false),
1239 lastMask (0),1459 lastMask (0),
@@ -1246,13 +1466,16 @@
1246 autoProgram (new GLScreenAutoProgram(gs)),1466 autoProgram (new GLScreenAutoProgram(gs)),
1247 rootPixmapCopy (None),1467 rootPixmapCopy (None),
1248 rootPixmapSize (),1468 rootPixmapSize (),
1469 frameProvider (),
1249 glVendor (NULL),1470 glVendor (NULL),
1250 glRenderer (NULL),1471 glRenderer (NULL),
1251 glVersion (NULL),1472 glVersion (NULL),
1473 postprocessingRequired (false),
1252 prevRegex (),1474 prevRegex (),
1253 prevBlacklisted (false)1475 prevBlacklisted (false)
1254{1476{
1255 ScreenInterface::setHandler (screen);1477 ScreenInterface::setHandler (screen);
1478 CompositeScreenInterface::setHandler (cScreen);
1256}1479}
12571480
1258PrivateGLScreen::~PrivateGLScreen ()1481PrivateGLScreen::~PrivateGLScreen ()
@@ -1443,8 +1666,11 @@
1443{1666{
1444 screen->outputChangeNotify ();1667 screen->outputChangeNotify ();
14451668
1669 frameProvider->invalidateAll ();
1670
1446 if (scratchFbo)1671 if (scratchFbo)
1447 scratchFbo->allocate (*screen, NULL, GL_BGRA);1672 scratchFbo->allocate (*screen, NULL, GL_BGRA);
1673
1448 updateView ();1674 updateView ();
1449}1675}
14501676
@@ -1669,6 +1895,10 @@
1669GLScreenInterface::projectionMatrix ()1895GLScreenInterface::projectionMatrix ()
1670 WRAPABLE_DEF (projectionMatrix)1896 WRAPABLE_DEF (projectionMatrix)
16711897
1898bool
1899GLScreenInterface::glPaintCompositedOutputRequired ()
1900 WRAPABLE_DEF (glPaintCompositedOutputRequired)
1901
1672void1902void
1673GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,1903GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
1674 GLFramebufferObject *fbo,1904 GLFramebufferObject *fbo,
@@ -1977,18 +2207,6 @@
1977 glDepthMask (GL_FALSE);2207 glDepthMask (GL_FALSE);
1978 glStencilMask (0);2208 glStencilMask (0);
19792209
1980 GLFramebufferObject *oldFbo = NULL;
1981 bool useFbo = false;
1982
1983 /* Clear the color buffer where appropriate */
1984 if (GL::fboEnabled && scratchFbo)
1985 {
1986 oldFbo = scratchFbo->bind ();
1987 useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
1988 if (!useFbo)
1989 GLFramebufferObject::rebind (oldFbo);
1990 }
1991
1992#ifdef UNSAFE_ARM_SGX_FIXME2210#ifdef UNSAFE_ARM_SGX_FIXME
1993 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&2211 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
1994 !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&2212 !(mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
@@ -2006,8 +2224,21 @@
2006 }2224 }
2007#endif2225#endif
20082226
2009 CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?2227 CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
2010 screen->region () : region;2228 screen->region () : region);
2229 bool useFbo = false;
2230 GLFramebufferObject *oldFbo = NULL;
2231
2232 postprocessingRequired = gScreen->glPaintCompositedOutputRequired ();
2233 postprocessingRequired |= frameProvider->alwaysPostprocess ();
2234
2235 /* Clear the color buffer where appropriate */
2236 if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ()))
2237 {
2238 oldFbo = scratchFbo->bind ();
2239 if (scratchFbo->checkStatus ())
2240 useFbo = true;
2241 }
20112242
2012 foreach (CompOutput *output, outputs)2243 foreach (CompOutput *output, outputs)
2013 {2244 {
@@ -2034,7 +2265,8 @@
20342265
2035 gScreen->glPaintOutput (defaultScreenPaintAttrib,2266 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2036 identity,2267 identity,
2037 CompRegion (*output), output,2268 CompRegion (*output),
2269 output,
2038 PAINT_SCREEN_REGION_MASK |2270 PAINT_SCREEN_REGION_MASK |
2039 PAINT_SCREEN_FULL_MASK);2271 PAINT_SCREEN_FULL_MASK);
2040 }2272 }
@@ -2057,7 +2289,9 @@
2057 tmpRegion = CompRegion (*output);2289 tmpRegion = CompRegion (*output);
2058#endif2290#endif
20592291
2060 outputRegion = tmpRegion & CompRegion (*output);2292 /* Clip current paint region to output extents */
2293 CompRegionRef wholeOutput (output->region ());
2294 outputRegion = (paintRegion & wholeOutput);
20612295
2062 if (!gScreen->glPaintOutput (defaultScreenPaintAttrib,2296 if (!gScreen->glPaintOutput (defaultScreenPaintAttrib,
2063 identity,2297 identity,
@@ -2068,10 +2302,11 @@
20682302
2069 gScreen->glPaintOutput (defaultScreenPaintAttrib,2303 gScreen->glPaintOutput (defaultScreenPaintAttrib,
2070 identity,2304 identity,
2071 CompRegion (*output), output,2305 wholeOutput, output,
2072 PAINT_SCREEN_FULL_MASK);2306 PAINT_SCREEN_FULL_MASK);
20732307
2074 tmpRegion += *output;2308 paintRegion += wholeOutput;
2309 cScreen->addOverdrawDamageRegion (wholeOutput);
2075 }2310 }
2076 }2311 }
2077 }2312 }
@@ -2082,13 +2317,18 @@
20822317
2083 if (useFbo)2318 if (useFbo)
2084 {2319 {
2085 GLFramebufferObject::rebind (oldFbo);
2086
2087 // FIXME: does not work if screen dimensions exceed max texture size2320 // FIXME: does not work if screen dimensions exceed max texture size
2088 // We should try to use glBlitFramebuffer instead.2321 // We should try to use glBlitFramebuffer instead.
2089 gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);2322 GLFramebufferObject::rebind (oldFbo);
2323 /* If we must always postprocess, then we don't have any
2324 * "real" backbuffer persistence, redraw the whole thing */
2325 gScreen->glPaintCompositedOutput (frameProvider->alwaysPostprocess () ?
2326 screen->region () :
2327 paintRegion, scratchFbo.get (), mask);
2090 }2328 }
20912329
2330 frameProvider->endFrame ();
2331
2092 if (cScreen->outputWindowChanged ())2332 if (cScreen->outputWindowChanged ())
2093 {2333 {
2094 /*2334 /*
@@ -2100,20 +2340,27 @@
2100 return;2340 return;
2101 }2341 }
21022342
2343 bool persistence = frameProvider->providesPersistence ();
2103 bool alwaysSwap = optionGetAlwaysSwapBuffers ();2344 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2104 bool fullscreen = useFbo ||2345 bool fullscreen = persistence ||
2105 alwaysSwap ||2346 alwaysSwap ||
2106 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&2347 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2107 commonFrontbuffer);2348 commonFrontbuffer);
21082349
2109 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());2350 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2110 doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);2351 doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, persistence);
2111 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);2352 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2112 doubleBuffer.render (tmpRegion, fullscreen);2353 doubleBuffer.render (paintRegion, fullscreen);
21132354
2114 lastMask = mask;2355 lastMask = mask;
2115}2356}
21162357
2358unsigned int
2359PrivateGLScreen::getFrameAge ()
2360{
2361 return frameProvider->getCurrentFrame ();
2362}
2363
2117bool2364bool
2118PrivateGLScreen::hasVSync ()2365PrivateGLScreen::hasVSync ()
2119{2366{
@@ -2138,6 +2385,13 @@
2138}2385}
21392386
2140void2387void
2388PrivateGLScreen::damageCutoff ()
2389{
2390 cScreen->applyDamageForFrameAge (frameProvider->getCurrentFrame ());
2391 cScreen->damageCutoff ();
2392}
2393
2394void
2141PrivateGLScreen::updateRenderMode ()2395PrivateGLScreen::updateRenderMode ()
2142{2396{
2143#ifndef USE_GLES2397#ifndef USE_GLES
@@ -2170,6 +2424,12 @@
2170 return prevBlacklisted;2424 return prevBlacklisted;
2171}2425}
21722426
2427bool
2428PrivateGLScreen::postprocessRequiredForCurrentFrame ()
2429{
2430 return postprocessingRequired;
2431}
2432
2173GLTexture::BindPixmapHandle2433GLTexture::BindPixmapHandle
2174GLScreen::registerBindPixmap (GLTexture::BindPixmapProc proc)2434GLScreen::registerBindPixmap (GLTexture::BindPixmapProc proc)
2175{2435{
@@ -2198,7 +2458,7 @@
2198GLFramebufferObject *2458GLFramebufferObject *
2199GLScreen::fbo ()2459GLScreen::fbo ()
2200{2460{
2201 return priv->scratchFbo;2461 return priv->scratchFbo.get ();
2202}2462}
22032463
2204GLTexture *2464GLTexture *
22052465
=== modified file 'plugins/resize/src/resize.cpp'
--- plugins/resize/src/resize.cpp 2012-10-19 09:23:11 +0000
+++ plugins/resize/src/resize.cpp 2013-02-13 11:42:25 +0000
@@ -257,7 +257,7 @@
257 float xScale, yScale;257 float xScale, yScale;
258 int x, y;258 int x, y;
259259
260 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)260 if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
261 return false;261 return false;
262262
263 status = gWindow->glPaint (attrib, transform, region,263 status = gWindow->glPaint (attrib, transform, region,
264264
=== modified file 'plugins/ring/src/ring.cpp'
--- plugins/ring/src/ring.cpp 2013-01-19 11:47:22 +0000
+++ plugins/ring/src/ring.cpp 2013-02-13 11:42:25 +0000
@@ -264,7 +264,7 @@
264 GLWindowPaintAttrib wAttrib (gWindow->lastPaintAttrib ());264 GLWindowPaintAttrib wAttrib (gWindow->lastPaintAttrib ());
265 GLMatrix wTransform = transform;265 GLMatrix wTransform = transform;
266266
267 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)267 if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
268 return false;268 return false;
269269
270 if (mSlot)270 if (mSlot)
271271
=== modified file 'plugins/scale/src/scale.cpp'
--- plugins/scale/src/scale.cpp 2013-01-29 23:16:32 +0000
+++ plugins/scale/src/scale.cpp 2013-02-13 11:42:25 +0000
@@ -384,12 +384,14 @@
384384
385 status = gWindow->glPaint (sAttrib, transform, region, mask);385 status = gWindow->glPaint (sAttrib, transform, region, mask);
386386
387 mask &= ~(PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
388
387 if (scaled)389 if (scaled)
388 {390 {
389 GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());391 GLWindowPaintAttrib lastAttrib (gWindow->lastPaintAttrib ());
390 GLMatrix wTransform (transform);392 GLMatrix wTransform (transform);
391393
392 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)394 if (mask & PAINT_WINDOW_NO_DRAW_MASKS)
393 return false;395 return false;
394396
395 if (window->alpha () || lastAttrib.opacity != OPAQUE)397 if (window->alpha () || lastAttrib.opacity != OPAQUE)
396398
=== modified file 'plugins/staticswitcher/src/staticswitcher.cpp'
--- plugins/staticswitcher/src/staticswitcher.cpp 2012-12-10 03:28:47 +0000
+++ plugins/staticswitcher/src/staticswitcher.cpp 2013-02-13 11:42:25 +0000
@@ -1246,7 +1246,7 @@
12461246
1247 const CompWindow::Geometry &g = window->geometry ();1247 const CompWindow::Geometry &g = window->geometry ();
12481248
1249 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||1249 if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
1250 sScreen->ignoreSwitcher)1250 sScreen->ignoreSwitcher)
1251 return false;1251 return false;
12521252
12531253
=== modified file 'plugins/switcher/src/switcher.cpp'
--- plugins/switcher/src/switcher.cpp 2012-12-10 03:28:47 +0000
+++ plugins/switcher/src/switcher.cpp 2013-02-13 11:42:25 +0000
@@ -971,7 +971,7 @@
971971
972 const CompWindow::Geometry &g = window->geometry ();972 const CompWindow::Geometry &g = window->geometry ();
973973
974 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK ||974 if (mask & PAINT_WINDOW_NO_DRAW_MASKS ||
975 sScreen->ignoreSwitcher)975 sScreen->ignoreSwitcher)
976 return false;976 return false;
977977
978978
=== modified file 'plugins/td/src/3d.cpp'
--- plugins/td/src/3d.cpp 2013-02-03 17:50:59 +0000
+++ plugins/td/src/3d.cpp 2013-02-13 11:42:25 +0000
@@ -163,7 +163,7 @@
163 glGetIntegerv (GL_CULL_FACE_MODE, &cull);163 glGetIntegerv (GL_CULL_FACE_MODE, &cull);
164 cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;164 cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;
165165
166 if (ww && wh && !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) &&166 if (ww && wh && !(mask & PAINT_WINDOW_NO_DRAW_MASKS) &&
167 ((cs->paintOrder () == FTB && mFtb) ||167 ((cs->paintOrder () == FTB && mFtb) ||
168 (cs->paintOrder () == BTF && !mFtb)))168 (cs->paintOrder () == BTF && !mFtb)))
169 {169 {
170170
=== modified file 'plugins/water/src/water.cpp'
--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
+++ plugins/water/src/water.cpp 2013-02-13 11:42:25 +0000
@@ -317,6 +317,12 @@
317 }317 }
318}318}
319319
320bool
321WaterScreen::glPaintCompositedOutputRequired ()
322{
323 return true;
324}
325
320void326void
321WaterScreen::glPaintCompositedOutput (const CompRegion &region,327WaterScreen::glPaintCompositedOutput (const CompRegion &region,
322 GLFramebufferObject *fbo,328 GLFramebufferObject *fbo,
@@ -467,6 +473,7 @@
467 cScreen->preparePaintSetEnabled (this, false);473 cScreen->preparePaintSetEnabled (this, false);
468 gScreen->glPaintOutputSetEnabled (this, false);474 gScreen->glPaintOutputSetEnabled (this, false);
469 gScreen->glPaintCompositedOutputSetEnabled (this, false);475 gScreen->glPaintCompositedOutputSetEnabled (this, false);
476 gScreen->glPaintCompositedOutputRequiredSetEnabled (this, false);
470 cScreen->donePaintSetEnabled (this, false);477 cScreen->donePaintSetEnabled (this, false);
471 }478 }
472479
473480
=== modified file 'plugins/water/src/water.h'
--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
+++ plugins/water/src/water.h 2013-02-13 11:42:25 +0000
@@ -64,6 +64,7 @@
6464
65 void handleEvent (XEvent *);65 void handleEvent (XEvent *);
6666
67 bool glPaintCompositedOutputRequired ();
67 void glPaintCompositedOutput (const CompRegion &region,68 void glPaintCompositedOutput (const CompRegion &region,
68 GLFramebufferObject *fbo,69 GLFramebufferObject *fbo,
69 unsigned int mask);70 unsigned int mask);
7071
=== modified file 'src/event.cpp'
--- src/event.cpp 2013-01-03 16:06:41 +0000
+++ src/event.cpp 2013-02-13 11:42:25 +0000
@@ -1288,17 +1288,6 @@
1288 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))1288 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))
1289 privateScreen.setDefaultWindowAttributes (&wa);1289 privateScreen.setDefaultWindowAttributes (&wa);
12901290
1291 /* That being said, we should store as much information as possible
1292 * about it. There may be requests relative to this window that could
1293 * use the data in the XCreateWindowEvent structure, especially the
1294 * override redirect state */
1295 wa.x = event->xcreatewindow.x;
1296 wa.y = event->xcreatewindow.y;
1297 wa.width = event->xcreatewindow.width;
1298 wa.height = event->xcreatewindow.height;
1299 wa.border_width = event->xcreatewindow.border_width;
1300 wa.override_redirect = event->xcreatewindow.override_redirect;
1301
1302 foreach (CompWindow *w, screen->windows ())1291 foreach (CompWindow *w, screen->windows ())
1303 {1292 {
1304 if (w->priv->serverFrame == event->xcreatewindow.window)1293 if (w->priv->serverFrame == event->xcreatewindow.window)
@@ -1478,15 +1467,7 @@
1478 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))1467 if (!XGetWindowAttributes (privateScreen.dpy, event->xcreatewindow.window, &wa))
1479 privateScreen.setDefaultWindowAttributes (&wa);1468 privateScreen.setDefaultWindowAttributes (&wa);
14801469
1481 /* That being said, we should store as much information as possible1470 PrivateWindow::createCompWindow (getTopWindow ()->id (), getTopServerWindow ()->id (), wa, event->xcreatewindow.window);
1482 * about it. There may be requests relative to this window that could
1483 * use the data in the XCreateWindowEvent structure, especially the
1484 * override redirect state */
1485 wa.x = event->xreparent.x;
1486 wa.y = event->xreparent.y;
1487 wa.override_redirect = event->xreparent.override_redirect;
1488
1489 PrivateWindow::createCompWindow (getTopWindow ()->id (), getTopServerWindow ()->id (), wa, event->xreparent.window);
1490 break;1471 break;
1491 }1472 }
1492 else1473 else
@@ -2118,10 +2099,7 @@
2118 ServerLock lock (screen->serverGrabInterface ());2099 ServerLock lock (screen->serverGrabInterface ());
21192100
2120 /* This will be the window that we must lower relative to */2101 /* This will be the window that we must lower relative to */
2121 CompWindow *sibling =2102 CompWindow *sibling = PrivateWindow::findValidStackSiblingBelow (active, fsw, lock);
2122 PrivateWindow::findValidStackSiblingBelow (active,
2123 fsw,
2124 lock);
21252103
2126 if (sibling)2104 if (sibling)
2127 {2105 {
@@ -2199,11 +2177,7 @@
2199 if (w)2177 if (w)
2200 {2178 {
2201 ServerLock lock (screen->serverGrabInterface ());2179 ServerLock lock (screen->serverGrabInterface ());
2202 if (PrivateWindow::stackDocks (w,2180 if (PrivateWindow::stackDocks (w, dockWindows, &xwc, &mask, lock))
2203 dockWindows,
2204 &xwc,
2205 &mask,
2206 lock))
2207 {2181 {
2208 Window sibling = xwc.sibling;2182 Window sibling = xwc.sibling;
2209 xwc.stack_mode = Above;2183 xwc.stack_mode = Above;
22102184
=== modified file 'src/option/tests/CMakeLists.txt'
--- src/option/tests/CMakeLists.txt 2012-12-10 13:01:00 +0000
+++ src/option/tests/CMakeLists.txt 2013-02-13 11:42:25 +0000
@@ -10,7 +10,6 @@
10 ${compiz_SOURCE_DIR}/src/point/include10 ${compiz_SOURCE_DIR}/src/point/include
11 ${compiz_SOURCE_DIR}/src/window/geometry/include11 ${compiz_SOURCE_DIR}/src/window/geometry/include
12 ${compiz_SOURCE_DIR}/src/window/extents/include12 ${compiz_SOURCE_DIR}/src/window/extents/include
13 ${compiz_SOURCE_DIR}/src/servergrab/include
14 ${COMPIZ_INCLUDE_DIRS}13 ${COMPIZ_INCLUDE_DIRS}
15)14)
1615
1716
=== modified file 'src/option/tests/option.cpp'
--- src/option/tests/option.cpp 2012-12-10 13:01:00 +0000
+++ src/option/tests/option.cpp 2013-02-13 11:42:25 +0000
@@ -1,9 +1,5 @@
1#include <gtest/gtest.h>1#include <gtest/gtest.h>
22
3/* XXX: including core.h means that we pull in
4 * both window.h and screen.h which are cascading
5 * includes. We should eliminate this dependency
6 */
7#include "core/core.h"3#include "core/core.h"
8#include "core/action.h"4#include "core/action.h"
9#include "core/match.h"5#include "core/match.h"
106
=== modified file 'src/outputdevices.h'
--- src/outputdevices.h 2012-12-10 13:01:00 +0000
+++ src/outputdevices.h 2013-02-13 11:42:25 +0000
@@ -25,11 +25,6 @@
25#include <core/output.h>25#include <core/output.h>
26#include <core/rect.h>26#include <core/rect.h>
27#include <core/region.h>27#include <core/region.h>
28
29/* XXX: Including screen.h includes window.h and other unnecessary
30 * headers which cause cascading header dependencies. We should seek to
31 * eliminate this dependency
32 */
33#include <core/screen.h>28#include <core/screen.h>
3429
35namespace compiz30namespace compiz
3631
=== modified file 'src/privatewindow.h'
--- src/privatewindow.h 2013-01-03 16:06:41 +0000
+++ src/privatewindow.h 2013-02-13 11:42:25 +0000
@@ -33,6 +33,8 @@
33#include <core/point.h>33#include <core/point.h>
34#include <core/timer.h>34#include <core/timer.h>
3535
36class ServerLock;
37
36#include <boost/shared_ptr.hpp>38#include <boost/shared_ptr.hpp>
3739
38#define XWINDOWCHANGES_INIT {0, 0, 0, 0, 0, None, 0}40#define XWINDOWCHANGES_INIT {0, 0, 0, 0, 0, None, 0}
@@ -127,22 +129,23 @@
127129
128 bool isInvisible() const;130 bool isInvisible() const;
129131
130 static bool stackLayerCheck (CompWindow *w,132 static bool stackLayerCheck (CompWindow *w,
131 Window clientLeader,133 Window clientLeader,
132 CompWindow *below,134 CompWindow *below,
133 const ServerLock &lock);135 const ServerLock &lock);
134136
135 static bool avoidStackingRelativeTo (CompWindow *w, const ServerLock &lock);137 static bool avoidStackingRelativeTo (CompWindow *w,
138 const ServerLock &lock);
136139
137 static CompWindow * findSiblingBelow (CompWindow *w,140 static CompWindow * findSiblingBelow (CompWindow *w,
138 bool aboveFs,141 bool aboveFs,
139 const ServerLock &lock);142 const ServerLock &lock);
140143
141 static CompWindow * findLowestSiblingBelow (CompWindow *w,144 static CompWindow * findLowestSiblingBelow (CompWindow *w,
142 const ServerLock &lock);145 const ServerLock &lock);
143146
144 static bool validSiblingBelow (CompWindow *w,147 static bool validSiblingBelow (CompWindow *w,
145 CompWindow *sibling,148 CompWindow *sibling,
146 const ServerLock &lock);149 const ServerLock &lock);
147150
148 void saveGeometry (int mask);151 void saveGeometry (int mask);
@@ -152,21 +155,21 @@
152 void reconfigureXWindow (unsigned int valueMask,155 void reconfigureXWindow (unsigned int valueMask,
153 XWindowChanges *xwc);156 XWindowChanges *xwc);
154157
155 static bool stackDocks (CompWindow *w,158 static bool stackDocks (CompWindow *w,
156 CompWindowList &updateList,159 CompWindowList &updateList,
157 XWindowChanges *xwc,160 XWindowChanges *xwc,
158 unsigned int *mask,161 unsigned int *mask,
159 const ServerLock &lock);162 const ServerLock &lock);
160163
161 static bool stackTransients (CompWindow *w,164 static bool stackTransients (CompWindow *w,
162 CompWindow *avoid,165 CompWindow *avoid,
163 XWindowChanges *xwc,166 XWindowChanges *xwc,
164 CompWindowList &updateList,167 CompWindowList &updateList,
165 const ServerLock &lock);168 const ServerLock &lock);
166169
167 static void stackAncestors (CompWindow *w,170 static void stackAncestors (CompWindow *w,
168 XWindowChanges *xwc,171 XWindowChanges *xwc,
169 CompWindowList &updateList,172 CompWindowList &updateList,
170 const ServerLock &lock);173 const ServerLock &lock);
171174
172 static bool isAncestorTo (CompWindow *transient,175 static bool isAncestorTo (CompWindow *transient,
@@ -179,8 +182,8 @@
179 int addWindowSizeChanges (XWindowChanges *xwc,182 int addWindowSizeChanges (XWindowChanges *xwc,
180 CompWindow::Geometry old);183 CompWindow::Geometry old);
181184
182 int addWindowStackChanges (XWindowChanges *xwc,185 int addWindowStackChanges (XWindowChanges *xwc,
183 CompWindow *sibling,186 CompWindow *sibling,
184 const ServerLock &lock);187 const ServerLock &lock);
185188
186 static CompWindow * findValidStackSiblingBelow (CompWindow *w,189 static CompWindow * findValidStackSiblingBelow (CompWindow *w,
187190
=== modified file 'src/tests/CMakeLists.txt'
--- src/tests/CMakeLists.txt 2013-01-03 16:06:41 +0000
+++ src/tests/CMakeLists.txt 2013-02-13 11:42:25 +0000
@@ -10,7 +10,6 @@
10 ${COMPIZ_MAIN_SOURCE_DIR}/pluginclasshandler/include10 ${COMPIZ_MAIN_SOURCE_DIR}/pluginclasshandler/include
11 ${COMPIZ_MAIN_SOURCE_DIR}/window/geometry/include11 ${COMPIZ_MAIN_SOURCE_DIR}/window/geometry/include
12 ${COMPIZ_MAIN_SOURCE_DIR}/window/extents/include12 ${COMPIZ_MAIN_SOURCE_DIR}/window/extents/include
13 ${COMPIZ_MAIN_SOURCE_DIR}/servergrab/include
14 ${COMPIZ_INCLUDE_DIRS}13 ${COMPIZ_INCLUDE_DIRS}
15)14)
1615
1716
=== modified file 'src/window.cpp'
--- src/window.cpp 2013-02-12 22:02:10 +0000
+++ src/window.cpp 2013-02-13 11:42:25 +0000
@@ -41,6 +41,7 @@
41#include <core/icon.h>41#include <core/icon.h>
42#include <core/atoms.h>42#include <core/atoms.h>
43#include "core/windowconstrainment.h"43#include "core/windowconstrainment.h"
44#include <core/servergrab.h>
44#include "privatewindow.h"45#include "privatewindow.h"
45#include "privatescreen.h"46#include "privatescreen.h"
46#include "privatestackdebugger.h"47#include "privatestackdebugger.h"
4748
=== modified file 'tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp'
--- tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2012-12-10 12:38:48 +0000
+++ tests/system/xorg-gtest/tests/compiz_xorg_gtest_test_window_stacking.cpp 2013-02-13 11:42:25 +0000
@@ -293,83 +293,3 @@
293 EXPECT_EQ (*it++, w3);293 EXPECT_EQ (*it++, w3);
294 EXPECT_EQ (*it++, w2);294 EXPECT_EQ (*it++, w2);
295}295}
296
297TEST_F (CompizXorgSystemStackingTest, TestCreateRelativeToDestroyedWindowFindsAnotherAppropriatePosition)
298{
299 ::Display *dpy = Display ();
300 ct::PropertyNotifyXEventMatcher matcher (dpy, "_NET_CLIENT_LIST_STACKING");
301
302 Window dock = ct::CreateNormalWindow (dpy);
303
304 /* Make it a dock */
305 MakeDock (dpy, dock);
306
307 /* Immediately map the dock window and clear the event queue for it */
308 XMapRaised (dpy, dock);
309
310 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, dock, ReparentNotify, -1, -1)));
311 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, dock, MapNotify, -1, -1)));
312
313 /* Dock window needs to be in the client list */
314 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
315 DefaultRootWindow (dpy),
316 PropertyNotify,
317 -1,
318 -1,
319 matcher)));
320 std::list <Window> clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
321 ASSERT_EQ (clientList.size (), 1);
322
323 Window w1 = ct::CreateNormalWindow (dpy);
324 Window w2 = ct::CreateNormalWindow (dpy);
325
326 XMapRaised (dpy, w1);
327
328 /* All reparented and mapped */
329 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy,w1, ReparentNotify, -1, -1)));
330 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w1, MapNotify, -1, -1)));
331
332 /* Grab the server so that we can guaruntee that all of these requests
333 * happen before compiz gets them */
334 XGrabServer (dpy);
335 XSync (dpy, false);
336
337 /* Map the second window, so it ideally goes above w1. Compiz will
338 * receive the MapRequest for this first */
339 XMapRaised (dpy, w2);
340
341 /* Create window that has w2 as its ideal above-candidate
342 * (compiz will receive the CreateNotify for this window
343 * after the MapRequest but before the subsequent MapNotify) */
344 Window w3 = ct::CreateNormalWindow (dpy);
345
346 XMapRaised (dpy, w3);
347
348 /* Destroy w2 */
349 XDestroyWindow (dpy, w2);
350
351 XUngrabServer (dpy);
352 XSync (dpy, false);
353
354 /* Reparented and mapped */
355 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w3, ReparentNotify, -1, -1)));
356 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindow (dpy, w3, MapNotify, -1, -1)));
357
358 /* Update _NET_CLIENT_LIST_STACKING twice */
359 ASSERT_TRUE (Advance (dpy, ct::WaitForEventOfTypeOnWindowMatching (dpy,
360 DefaultRootWindow (dpy),
361 PropertyNotify,
362 -1,
363 -1,
364 matcher)));
365
366 /* Check the client list to see that dock > w3 > w1 */
367 clientList = ct::NET_CLIENT_LIST_STACKING (dpy);
368
369 std::list <Window>::iterator it = clientList.begin ();
370
371 EXPECT_EQ (3, clientList.size ());
372 EXPECT_EQ (w1, (*it++));
373 EXPECT_EQ (w3, (*it++));
374 EXPECT_EQ (dock, (*it++));
375}

Subscribers

People subscribed via source and target branches