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