Merge lp:~compiz-team/compiz/compiz.fix_1024304.1.1 into lp:compiz/0.9.11

Proposed by Sam Spilsbury
Status: Merged
Approved by: Christopher Townsend
Approved revision: 3729
Merged at revision: 3799
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1024304.1.1
Merge into: lp:compiz/0.9.11
Diff against target: 2221 lines (+1500/-72)
17 files modified
plugins/composite/CMakeLists.txt (+6/-1)
plugins/composite/include/composite/agedamagequery.h (+53/-0)
plugins/composite/include/composite/composite.h (+53/-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 (+449/-0)
plugins/composite/src/privates.h (+18/-2)
plugins/composite/src/screen.cpp (+149/-11)
plugins/opengl/include/opengl/opengl.h (+18/-3)
plugins/opengl/src/paint.cpp (+25/-6)
plugins/opengl/src/privates.h (+31/-4)
plugins/opengl/src/screen.cpp (+297/-30)
plugins/opengl/src/window.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.1
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Christopher Townsend (community) Approve
Marco Trevisan (TreviƱo) Approve
Esokrates testing, benchmarking Pending
Andrea Azzarone Pending
Timo Jyrinki build&run Pending
MC Return Pending
Daniel van Vugt Pending
Sam Spilsbury Pending
Review via email: mp+176798@code.launchpad.net

This proposal supersedes a proposal from 2013-05-26.

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.

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 : 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: 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
MC Return (mc-return) wrote : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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

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

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 : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

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

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
MC Return (mc-return) wrote : Posted in a previous version of this proposal

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) : Posted in a previous version of this proposal
review: Abstain
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

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

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

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
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
MC Return (mc-return) wrote : Posted in a previous version of this proposal

Let us land this. :)

I am running trunk here on modern ATI gfx with prop. fglrx, but in the long run I could test 2 Intel chipsets, one mobile ATI chipset and a modern Nvidia powered system as well.

Should there be regressions I will report those.

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

Awaiting review of
https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589/+merge/147543
and https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947.2/+merge/163474

On Mon, May 13, 2013 at 2:50 PM, MC Return <email address hidden> wrote:
> Review: Approve
>
> Let us land this. :)
>
> I am running trunk here on modern ATI gfx with prop. fglrx, but in the long run I could test 2 Intel chipsets, one mobile ATI chipset and a modern Nvidia powered system as well.
>
> Should there be regressions I will report those.
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1/+merge/163416
> You proposed lp:~compiz-team/compiz/compiz.fix_1024304.1 for merging.

--
Sam Spilsbury

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: 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
MC Return (mc-return) wrote : Posted in a previous version of this proposal

News:
http://support.amd.com/us/kbarticles/Pages/amdcatalyst13-6linbetadriver.aspx

AMD's fglrx 13.6 Beta driver now also supports GLX_EXT_buffer_age extension !!! \o/

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

Nux branch seems approved now https://code.launchpad.net/~smspillaz/nux/nux.fix_1091589.1/+merge/165772 but needs to go in together with Unity which still needs some work https://code.launchpad.net/~smspillaz/unity/unity.fix_1080947.2.1/+merge/165774 - after that, this one!

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
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Please re-target to lp:compiz

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

FAILED: Continuous integration, rev:3729
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1024304.1.1/+merge/176798/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/compiz-ci/284/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-saucy-amd64-ci/97
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-saucy-armhf-ci/97
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-saucy-i386-ci/97

Click here to trigger a rebuild:
http://s-jenkins:8080/job/compiz-ci/284/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote :

(added commit message to keep jenkins happy about that part)

Revision history for this message
Marco Trevisan (TreviƱo) (3v1n0) wrote :

I think we're finally ready for merging this.

review: Approve
Revision history for this message
Christopher Townsend (townsend) wrote :

Yeah, I approve as well, so here we go...

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

Cool to see that this finally went in.

Remember that you'll need lp:~smspillaz/unity/unity.fix_1080947.2 and lp:~unity-team/nux/nux.fix_1091589.1, otherwise unity won't be able to cope with inconsistent backbuffers.

Revision history for this message
Christopher Townsend (townsend) wrote :

Hey Sam,

Yeah, we're working on those branches as we speak. We made ~unity-team branches to do this and superseded the MP's, but look for those to get in soon:)

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: