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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1024304.1
Merge into: lp:compiz/0.9.10
Diff against target: 2314 lines (+1484/-81)
25 files modified
plugins/animation/src/animation.cpp (+1/-1)
plugins/composite/CMakeLists.txt (+6/-1)
plugins/composite/include/composite/agedamagequery.h (+53/-0)
plugins/composite/include/composite/composite.h (+49/-14)
plugins/composite/src/backbuffertracking/CMakeLists.txt (+31/-0)
plugins/composite/src/backbuffertracking/include/backbuffertracking.h (+125/-0)
plugins/composite/src/backbuffertracking/src/backbuffertracking.cpp (+214/-0)
plugins/composite/src/backbuffertracking/tests/CMakeLists.txt (+22/-0)
plugins/composite/src/backbuffertracking/tests/test-composite-backbuffertracking.cpp (+450/-0)
plugins/composite/src/privates.h (+18/-2)
plugins/composite/src/screen.cpp (+136/-11)
plugins/kdecompat/src/kdecompat.cpp (+2/-2)
plugins/opengl/include/opengl/opengl.h (+18/-3)
plugins/opengl/src/paint.cpp (+14/-6)
plugins/opengl/src/privates.h (+31/-4)
plugins/opengl/src/screen.cpp (+297/-30)
plugins/opengl/src/window.cpp (+1/-1)
plugins/resize/src/resize.cpp (+1/-1)
plugins/ring/src/ring.cpp (+1/-1)
plugins/scale/src/scale.cpp (+3/-1)
plugins/staticswitcher/src/staticswitcher.cpp (+1/-1)
plugins/switcher/src/switcher.cpp (+1/-1)
plugins/td/src/3d.cpp (+1/-1)
plugins/water/src/water.cpp (+7/-0)
plugins/water/src/water.h (+1/-0)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1024304.1
Reviewer Review Type Date Requested Status
Sam Spilsbury Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
MC Return Abstain
Daniel van Vugt Pending
Esokrates testing, benchmarking Pending
Timo Jyrinki build&run Pending
Andrea Azzarone Pending
Review via email: mp+160687@code.launchpad.net

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

This proposal has been superseded by a proposal from 2013-05-12.

Commit message

Add support for the GLX_EXT_buffer_age extension on hardware that supports it, which should result in a nice speed-boost due to the fact that we no longer have to abuse fillrate by retaining old frame contents, and instead asking the driver how defined the current frame is.

Added external API for plugins to register their own damage tracking objects - with a callback as to whether or not to track the specified damage. This allows plugins that rely on both the retrospective and new damage to the framebuffer to ignore feedback caused by their old damage events.

(LP: #1024304)

Description of the change

Add support for the GLX_EXT_buffer_age extension on hardware that supports it, which should result in a nice speed-boost due to the fact that we no longer have to abuse fillrate by retaining old frame contents, and instead asking the driver how defined the current frame is.

Note: I've marked this needs review for now, but it shouldn't be merged because it confuses unity a fair bit. I've got some branches on unity which will make it work with this code (albeit, the launcher and panel will be re-presented on every frame, but that is what was happening anyways and is harmless for performance).

1. https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589/+merge/147543 (WindowThread::PresentWindowsIntersectingGeometryOnThisFrame, WindowThread::ForeignFrameCutoff, WindowThread::ForeignFrameEnded)
2. https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544 (make unity use the new APIs)

Note 2: I don't have any solid numbers on this yet. Daniel reported a 10% difference with redirect-to-fbo-on-each-frame in bug 1024304, so I think that is a good start, because with this branch we are effectively not doing that (on NVIDIA). I've got some testers to gather some more concrete numbers in a few days.

Update: test results here: http://www.ucc.asn.au/~smspillaz/phoronix-test-suite/composite.xml

I was careful to modify phoronix-test-suite to run tests in windowed mode only, and those were the only three tests I was able to get to run in windowed mode. Of particular interest was the fact that the unigine demos had a 5x performance improvement, probably because the driver was spending less time filling redundant pixels from the compositor. In other areas we had a roughly 5FPS boost.

Compiz framerate graph:

http://www.ucc.asn.au/~smspillaz/compiz-perf-graph.png

You'll see that especially on the last test, it drops off quite a bit on the non buffer_age case, and is generally speaking lower across the board.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Esokrates (esokrarkose) wrote : Posted in a previous version of this proposal

I have used the ppa containing these changes since the beginning and could confirm the performance improvements using Phoronix Test Suite (and of course my subjective feeling). Comparing benchmarks of compiz 0.9.9.0 and the branch containing the improvements (both disabled "unredirect fullscreen windows") clearly shows that there is an substantial performance improvement.
Part of my benchmark results can be downloaded here:
http://ubuntuone.com/2JNLvWQiYiQmOCAca0bIEn

review: Approve (testing, benchmarking)
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal

I'm getting a crash on Intel SandyBridge with this branch. At least machine information at bug #1153482 - that was after canceling the first apport dialog. Apport refuses to file the actual compiz .crash file since it notices the version numbers are out of date, but I can send the CoreDump.gz and/or .crash via e-mail.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Don't worry it doesn't matter. I've been told that all
non-insignificant changes to compiz are automatically vetoed at this
point.

On Mon, Mar 11, 2013 at 3:52 PM, Timo Jyrinki
<email address hidden> wrote:
> Review: Needs Fixing
>
> I'm getting a crash on Intel SandyBridge with this branch. At least machine information at bug #1153482 - that was after canceling the first apport dialog. Apport refuses to file the actual compiz .crash file since it notices the version numbers are out of date, but I can send the CoreDump.gz and/or .crash via e-mail.
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Stacktrace would be nice though. Can you get one manually?

On Mon, Mar 11, 2013 at 4:01 PM, Sam Spilsbury <email address hidden> wrote:
> Don't worry it doesn't matter. I've been told that all
> non-insignificant changes to compiz are automatically vetoed at this
> point.
>
> On Mon, Mar 11, 2013 at 3:52 PM, Timo Jyrinki
> <email address hidden> wrote:
>> Review: Needs Fixing
>>
>> I'm getting a crash on Intel SandyBridge with this branch. At least machine information at bug #1153482 - that was after canceling the first apport dialog. Apport refuses to file the actual compiz .crash file since it notices the version numbers are out of date, but I can send the CoreDump.gz and/or .crash via e-mail.
>> --
>> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
>> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>
>
>
> --
> Sam Spilsbury

--
Sam Spilsbury

Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal

Sorry, PEBKAC, recompiled Unity against it and now it works. I don't have a raring machine where I could test the actual functionality, but seems to work on Intel identically to before.

So approved with regards to build / run on Intel without GLX_EXT_buffer_age.

review: Approve (build&run)
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Ah, cool that you got it working on intel hw.

Unfortunately my understanding is that this won't go in for raring. It requires both a Unity and Nux change in order to ensure that there isn't a performance /regression/ (because of Unity's brain-dead damageScreen-on-any-damage hook), and those changes are quite substantial.

Sadly, the ps-team had three months to review these changes and I kept them up-to-date during that entire time, but the feet-dragging has effectively meant its come to a point where they won't be merged :(

Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal
review: Needs Information
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote : Posted in a previous version of this proposal

Andrea: I don't think so (I might be wrong), but these are surely required to go in together with this:
https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544
https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589/+merge/147543

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

@Timo: at the moment, it kinda pulls in https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1040478/+merge/150949 because I wrote https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544 with the former in mind. If we're still interested in getting this is (I'd be happy if we were) I can do a quick refactor to try and remove the dependency.

Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal

> @Timo: at the moment, it kinda pulls in https://code.launchpad.net/~compiz-
> team/compiz/compiz.fix_1040478/+merge/150949 because I wrote
> https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544
> with the former in mind. If we're still interested in getting this is (I'd be
> happy if we were) I can do a quick refactor to try and remove the dependency.

Yes, please. If we can get this into a mergeable state in the next week there's a good chance we can get it in by final beta freeze (March 28). Otherwise, it's still worth getting in post-13.04

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

On Thu, Mar 21, 2013 at 9:14 PM, Andrea Azzarone <email address hidden> wrote:
>> @Timo: at the moment, it kinda pulls in https://code.launchpad.net/~compiz-
>> team/compiz/compiz.fix_1040478/+merge/150949 because I wrote
>> https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947/+merge/147544
>> with the former in mind. If we're still interested in getting this is (I'd be
>> happy if we were) I can do a quick refactor to try and remove the dependency.
>
> Yes, please. If we can get this into a mergeable state in the next week there's a good chance we can get it in by final beta freeze (March 28). Otherwise, it's still worth getting in post-13.04

:) Alrighty, glad to see this resolved. Is it cleared with distro?
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote : Posted in a previous version of this proposal

Hey Sam, do you mind talking to duflu and see if he gets time to review this branch? If he's happy with it, we can get it in.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

I think Daniel is busy on other projects. Subscribe him if you want, but I
think this should be left to the main legacy stack maintainers.
On 21/03/2013 11:39 PM, "Didier Roche" <email address hidden> wrote:

> Hey Sam, do you mind talking to duflu and see if he gets time to review
> this branch? If he's happy with it, we can get it in.
> --
>
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/150951
> Your team Compiz Maintainers is subscribed to branch lp:compiz.
>

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Okay, so the unity branch should only depend on this one now.

Though the other one is certainly a nice to have - it means we don't have to read out the bindings from opengl in unity.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Please re-target this for lp:compiz/0.9.10

review: Needs Resubmitting
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
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Okay, so I've talked to Didier about this and we've come up with a small plan of action. We'll need to give this a week solid of QA at the beginning of the S cycle and then make sure that we don't have any AP regressions. That'll happen in about two weeks.

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

Fix typo

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

We reset the frame provider at the end of glXInitContext, no need to do
it before that in the GLES case

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote :

I do not understand this part:

1891 + /* We need scratchFbo to be set before doing this, and it is common
1892 + * to both the GLES and non-GLES codepaths, so using another #ifdef
1893 + */
1894 + priv->updateFrameProvider ();
1895 +

Is configureLock not needed here anymore ?:

2202 - icons (),
2203 - configureLock (w->obtainLockOnConfigureRequests ())
2204 + icons ()

There is no #ifdef here ?

These changes seem to be unrelated, but okay:

2216 - case PlaceOptions::ModeCascade:
2217 + case PlaceOptions::ModeCascade:

2225 -

2359 - if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
2360 + if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2

Was this wrong ?:

2368 - /* Gravity here is assumed to be SouthEast, clients can update
2369 + /* Gravity here is assumed to be NorthWest, clients can update

What is the water change about ? Water needs FBOs to work AFAIK.

Here brackets could be removed:

1995 - CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
1996 - screen->region () : region;
1997 + CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) ?
1998 + screen->region () : region);

Here also:

2006 + if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ()))

Why not 7 ?:

1469 -#define COMPIZ_OPENGL_ABI 6
1470 +#define COMPIZ_OPENGL_ABI 8

Is this intended, it looks strange ?:

626 + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
627 + )

The rest LGTM AFAICT.

Revision history for this message
MC Return (mc-return) wrote :

Note: The "There is no #ifdef here ?" sentence above belongs after "1895 +".

3637. By Sam Spilsbury

Revert unrelated changes, unrevert some unintentional changes to
window.cpp

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Thanks for the review :)

> I do not understand this part:
>
> 1891 + /* We need scratchFbo to be set before doing this, and it is
> common
> 1892 + * to both the GLES and non-GLES codepaths, so using another
> #ifdef
> 1893 + */
> 1894 + priv->updateFrameProvider ();
> 1895 +
>
> Is configureLock not needed here anymore ?:
>

Yep, that was an error, possibly caused by the tons-of-re-merging I've had to do here. Fixed now.

> 2202 - icons (),
> 2203 - configureLock (w->obtainLockOnConfigureRequests ())
> 2204 + icons ()
>
> There is no #ifdef here ?

The comment itself was outdated, fixed.
>
> These changes seem to be unrelated, but okay:
>
> 2216 - case PlaceOptions::ModeCascade:
> 2217 + case PlaceOptions::ModeCascade:
>
> 2225 -
>
> 2359 - if (serverFrameGeometry.width () == xwc->width +
> serverGeometry.border () * 2
> 2360 + if (serverFrameGeometry.width () == xwc->width +
> serverGeometry.border () * 2
>

Reverted.

> Was this wrong ?:
>
> 2368 - /* Gravity here is assumed to be SouthEast, clients can update
> 2369 + /* Gravity here is assumed to be NorthWest, clients can update
>

Also reverted. I'll propose it separately, looks like it probably got in there by accident.

> What is the water change about ? Water needs FBOs to work AFAIK.
>

Painting the whole scene to an framebuffer object was turned off by default unless some plugin or opengl indicates that it is necessary on this frame. The water change basically hooks glPaintCompositedOutputRequired when water is active and always returns true.

> Here brackets could be removed:
>
> 1995 - CompRegion tmpRegion = (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
> ?
> 1996 - screen->region () : region;
> 1997 + CompRegion paintRegion ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
> ?
> 1998 + screen->region () : region);
>

Bracketing bitwise operations is usually a good idea when they are mixed with other parts of if statements.

> Here also:
>
> 2006 + if ((GL::fboEnabled && postprocessRequiredForCurrentFrame ()))
>

Fixed, thanks.

> Why not 7 ?:
>
> 1469 -#define COMPIZ_OPENGL_ABI 6
> 1470 +#define COMPIZ_OPENGL_ABI 8
>

Fixed.

> Is this intended, it looks strange ?:
>
> 626 + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
> 627 + )
>

Fixed. Its left over from when I removed all of the references but wasn't able to do so here yet.

> The rest LGTM AFAICT.

I might self-review this a little later, so for now.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote :

> Thanks for the review :)
>
No problem, thanks 4 your reviews as well ;)

3638. By Sam Spilsbury

Merge lp:compiz

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

This was tested. This was reviewed. This compiles and passes tests.

There is time until the next version (0.9.10) of Compiz gets released and there is time until the next version of *buntu gets released.

I say -> let us land this now and fix eventually remaining regressions later...

Sam, I have one additional idea and suggestion for this though:
We should ideally make this configurable via CCSM, so even users, who own hardware that supports GLX_EXT_buffer_age are not forced to use this OpenGL extension, should problems occur for them.

Could you implement such an option ?

Enable GLX_EXT_buffer_age Support (X)

I am just choosing "Abstain" here, because Sam mentioned he would like to self-review this once again, but this is
effectively an "Approve" from me... :)

review: Approve
Revision history for this message
MC Return (mc-return) :
review: Abstain
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

On Sun, Apr 28, 2013 at 12:18 AM, MC Return <email address hidden> wrote:
> Review: Approve
>
> Sam, I have one additional idea and suggestion for this though:
> We should ideally make this configurable via CCSM, so even users, who own hardware that supports GLX_EXT_buffer_age are not forced to use this OpenGL extension, should problems occur for them.
>
> Could you implement such an option ?
>
> Enable GLX_EXT_buffer_age Support (X)

I don't like the idea of options affecting the rendering system
generally. The system should pick the most optimal rendering path and
if it doesn't work then we fix it rather than having people disable
it.

EXT_b_a is straightforward to implement in a driver, any problems are
likely to be on the client implementation and not the driver.

>
> I am just choosing "Abstain" here, because Sam mentioned he would like to self-review this once again, but this is
> effectively an "Approve" from me... :)
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/160687
> You proposed lp:~compiz-team/compiz/compiz.fix_1024304.1 for merging.

--
Sam Spilsbury

3639. By Sam Spilsbury

Merge lp:compiz

3640. By Sam Spilsbury

Merge lp:compiz

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

Self-review:

1. This PAINT_WINDOW_NO_DRAW_MASKS was really necessary for the blur plugin and can probably be moved out into a separate branch:

1 === modified file 'plugins/animation/src/animation.cpp'
2 --- plugins/animation/src/animation.cpp 2013-04-25 11:07:54 +0000
3 +++ plugins/animation/src/animation.cpp 2013-05-03 22:53:26 +0000
4 @@ -1618,7 +1618,7 @@
5 // Is this the first glPaint call this round
6 // without the mask PAINT_WINDOW_OCCLUSION_DETECTION_MASK?
7 if (mPAScreen->mStartingNewPaintRound &&
8 - !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
9 + !(mask & PAINT_WINDOW_NO_DRAW_MASKS))
10 {
11 mPAScreen->mStartingNewPaintRound = false;

(see also lines 206, 2202, 2215, 2227. 2235, 2261, 2274)

2.

181 + void addOverdrawDamageRegion (const CompRegion &);

This can probably be renamed to addOverdrawDamageRegionForCurrentlyPaintingFrame

3.

340 +class FrameRoster :

Perhaps rename to PreviousDamageBuffers

4.

468 + while (age--)

do
{
} while (--age)

5.

717 + NiceMock <MockAgeingDamageBufferObserver> niceTracker;

Possibly better to explicitly set unused expectations as opposed to using NiceMock. Or perhaps not because we want to shortcut it in the constructor.

6.

915 +/* These are more or less functional tests from this point forward
916 + * just checking a number of different situations */
917 +
918 +TEST_F (BackbufferTracking, ThreeFramesAgoWithFourFrames)
919 +{

Better rename the test fixture.

7.

1167 +namespace
1168 +{
1169 +bool alwaysMarkDirty ()
1170 +{
1171 + return true;
1172 +}
1173 +}

1199 + roster (*screen,
1200 + ageingBuffers,
1201 + boost::bind (alwaysMarkDirty))

1338 +CompositeScreen::DamageQuery::Ptr
1339 +CompositeScreen::getDamageQuery (const ShouldMarkDirty &callback)

This feels clunky. Perhaps the default could be an empty boost function which, upon being empty would always mark the area dirty.

9.

1536 + CompRegionRef (output->region ()), output, mask);

Needs to be 80 columns

10.

1546 + glPaintTransformedOutput (sAttrib, sTransform, CompRegionRef (output->region ()),

Conversion of tabs to spaces

11.

1583 -#ifdef USE_GLES
1584 #include <opengl/framebufferobject.h>
1585 -#endif
1586 -

Probably not necessary any longer?

review: Needs Fixing
3641. By Sam Spilsbury

Revert introduction of PAINT_WINDOW_NO_DRAW_MASKS. It isn't entirely
relevant here.

3642. By Sam Spilsbury

Merge lp:compiz

3643. By Sam Spilsbury

Rename addOverdrawDamageRegion to recordDamageOnCurrentFrame and tidy
up some formatting

3644. By Sam Spilsbury

Allow an empty callback argument to getDamageQuery. Makes the plugin API
simpler

3645. By Sam Spilsbury

Merge lp:compiz

3646. By Sam Spilsbury

Merge lp:compiz

3647. By Sam Spilsbury

Merge lp:compiz

Unmerged revisions

3647. By Sam Spilsbury

Merge lp:compiz

3646. By Sam Spilsbury

Merge lp:compiz

3645. By Sam Spilsbury

Merge lp:compiz

3644. By Sam Spilsbury

Allow an empty callback argument to getDamageQuery. Makes the plugin API
simpler

3643. By Sam Spilsbury

Rename addOverdrawDamageRegion to recordDamageOnCurrentFrame and tidy
up some formatting

3642. By Sam Spilsbury

Merge lp:compiz

3641. By Sam Spilsbury

Revert introduction of PAINT_WINDOW_NO_DRAW_MASKS. It isn't entirely
relevant here.

3640. By Sam Spilsbury

Merge lp:compiz

3639. By Sam Spilsbury

Merge lp:compiz

3638. By Sam Spilsbury

Merge lp:compiz

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: