Merge lp:~vanvugt/compiz/XDamageReport2 into lp:compiz/0.9.8

Proposed by Daniel van Vugt
Status: Merged
Merged at revision: 3265
Proposed branch: lp:~vanvugt/compiz/XDamageReport2
Merge into: lp:compiz/0.9.8
Diff against target: 132 lines (+29/-6)
7 files modified
plugins/annotate/src/annotate.cpp (+1/-1)
plugins/composite/src/privates.h (+4/-0)
plugins/composite/src/screen.cpp (+19/-0)
plugins/composite/src/window.cpp (+1/-1)
plugins/copytex/src/copytex.cpp (+1/-1)
plugins/decor/src/decor.cpp (+2/-2)
plugins/opengl/src/texture.cpp (+1/-1)
To merge this branch: bzr merge lp:~vanvugt/compiz/XDamageReport2
Reviewer Review Type Date Requested Status
Sam Spilsbury Approve
Compiz Maintainers Pending
Review via email: mp+111739@code.launchpad.net

Commit message

Use the XDamage extension more efficiently (the way it was designed to be
used). This dramatically reduces CPU usage, reduces wakeups, and increases
frame rates. It also solves at least one observed performance bug
(LP: #1007299) and probably several more.

Description of the change

Second attempt...

This time I've been careful to avoid races with the X server that could result in damage artefacts.

The original proposal is here:
https://code.launchpad.net/~vanvugt/compiz/XDamageReport/+merge/108307

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Hmm, I think I can see more potential for races unless some server grabbing is added. Work in progress again.

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

BTW, I would suggest using the ServerLock class to do server grabs safely.

ServerLock serverLock (screen->serverGrabInterface ());

It's testable and ensures that you don't get stale grabs caused by missed output buffer flushes.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

No I think my hunch was wrong and the code is right. There is no need for a server grab because each XDamageSubtract is completely independent (different drawables). And in fact XDamageSubtract is synchronous, so the XSync() probably is not required.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Though, we could probably make the code much safer by using de->geometry (the whole drawable) instead of de->area (the damaged region) and XDamageReportNonEmpty instead of XDamageReportBoundingBox.

Then we'd be guaranteed a maximum of one damage per drawable per frame, and the damage would always be the whole drawable. It would be safer in theory, even if potentially less efficient.

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

> Though, we could probably make the code much safer by using de->geometry (the
> whole drawable) instead of de->area (the damaged region) and
> XDamageReportNonEmpty instead of XDamageReportBoundingBox.
>
> Then we'd be guaranteed a maximum of one damage per drawable per frame, and
> the damage would always be the whole drawable. It would be safer in theory,
> even if potentially less efficient.

I think the problem then is that for maximized or fullscreen windows you don't get the optimization of being able to clip painting. Its worth looking into how important this optimization is IMO.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Ignore the above hypotheses for now. Please review and test the actual code below :)

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

Works great, nouveau. Code fine.

I feel as though this code may be easy to break because of the coupling between this:

43 + else if (event->type == damageEvent + XDamageNotify)
44 + {
45 + XDamageNotifyEvent *de = (XDamageNotifyEvent*)event;
46 + damages[de->damage] = de->area;
47 + }

And this:

55 + Display *dpy = screen->dpy ();
56 + std::map<Damage, XRectangle>::iterator d = priv->damages.begin ();
57 + for (; d != priv->damages.end (); d++)
58 + {
59 + XserverRegion sub = XFixesCreateRegion (dpy, &d->second, 1);
60 + if (sub != None)
61 + {
62 + XDamageSubtract (dpy, d->first, sub, None);
63 + XFixesDestroyRegion (dpy, sub);
64 + }
65 + }
66 + XSync (dpy, False);
67 + priv->damages.clear ();

Since if the latter is not done for the former, then things will stop updating. As such, I would strongly recommend adding some unit tests to ensure that this code doesn't break accidentally. So abstaining for now, someone else can approve if they think tests aren't appropriate.

review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The risk, and what needs testing here, is for races between XFunctions and the X server. Testing for such races should be done as part of a system test suite that runs a real compiz instance on a real X server. Unit tests in this case are not relevant.

The next best thing to an automated system test suite, until one exists, is manual testing.

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

The reason i say unit tests is because the code itself is tightly coupled and looks easy to subtly break if someone doesnt know what they are doing.

Sent from Samsung Mobile

 Daniel van Vugt <email address hidden> wrote:

The risk, and what needs testing here, is for races between XFunctions and the X server. Testing for such races should be done as part of a system test suite that runs a real compiz instance on a real X server. Unit tests in this case are not relevant.

The next best thing to an automated system test suite, until one exists, is manual testing.
--
https://code.launchpad.net/~vanvugt/compiz/XDamageReport2/+merge/111739
You are reviewing the proposed merge of lp:~vanvugt/compiz/XDamageReport2 into lp:compiz.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

In that case, the maintenance risk is actually between:
   XDamageCreate(..., XDamageReportBoundingBox);
and
   XDamageSubtract().

So to mitigate that risk, we need to ensure:
   1. All plugins that use XDamageCreate with BoundingBox need to depend on composite. Already done.
   2. Maybe add a comment to composite saying "Don't delete this code!". But the same could be said for lots of critical code.

If you happen to delete the XDamageSubtract code by accident, then I can tell you from experience that you'll know about it because the screen won't update at all. :)

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

> In that case, the maintenance risk is actually between:
> XDamageCreate(..., XDamageReportBoundingBox);
> and
> XDamageSubtract().
>
> So to mitigate that risk, we need to ensure:
> 1. All plugins that use XDamageCreate with BoundingBox need to depend on
> composite. Already done.
> 2. Maybe add a comment to composite saying "Don't delete this code!". But
> the same could be said for lots of critical code.

Either that or add an abstraction such that the implementation detail is not exposed by default, and the tests expect that XDamageSubtract is called for all damage added to the map. A failing test is possibly a lot more effective in providing feedback than a comment that just says "don't do dis!!" on code a future maintainer might not understand.

>
> If you happen to delete the XDamageSubtract code by accident, then I can tell
> you from experience that you'll know about it because the screen won't update
> at all. :)

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

In any case, I'd prefer to have this in than out, even without tests.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/annotate/src/annotate.cpp'
2--- plugins/annotate/src/annotate.cpp 2012-01-30 05:12:24 +0000
3+++ plugins/annotate/src/annotate.cpp 2012-06-24 10:15:24 +0000
4@@ -73,7 +73,7 @@
5 }
6
7 damage = XDamageCreate (screen->dpy (), pixmap,
8- XDamageReportRawRectangles);
9+ XDamageReportBoundingBox);
10
11 surface =
12 cairo_xlib_surface_create_with_xrender_format (screen->dpy (),
13
14=== modified file 'plugins/composite/src/privates.h'
15--- plugins/composite/src/privates.h 2012-06-06 05:12:28 +0000
16+++ plugins/composite/src/privates.h 2012-06-24 10:15:24 +0000
17@@ -33,6 +33,7 @@
18
19 #include <composite/composite.h>
20 #include <core/atoms.h>
21+#include <map>
22
23 #include "pixmapbinding.h"
24 #include "composite_options.h"
25@@ -110,6 +111,9 @@
26
27 Atom cmSnAtom;
28 Window newCmSnOwner;
29+
30+ /* Map Damage handle to its bounding box */
31+ std::map<Damage, XRectangle> damages;
32 };
33
34 class PrivateCompositeWindow :
35
36=== modified file 'plugins/composite/src/screen.cpp'
37--- plugins/composite/src/screen.cpp 2012-06-06 07:31:59 +0000
38+++ plugins/composite/src/screen.cpp 2012-06-24 10:15:24 +0000
39@@ -100,6 +100,11 @@
40 }
41 }
42 }
43+ else if (event->type == damageEvent + XDamageNotify)
44+ {
45+ XDamageNotifyEvent *de = (XDamageNotifyEvent*)event;
46+ damages[de->damage] = de->area;
47+ }
48 break;
49 }
50
51@@ -793,6 +798,20 @@
52 damageScreen ();
53 }
54
55+ Display *dpy = screen->dpy ();
56+ std::map<Damage, XRectangle>::iterator d = priv->damages.begin ();
57+ for (; d != priv->damages.end (); d++)
58+ {
59+ XserverRegion sub = XFixesCreateRegion (dpy, &d->second, 1);
60+ if (sub != None)
61+ {
62+ XDamageSubtract (dpy, d->first, sub, None);
63+ XFixesDestroyRegion (dpy, sub);
64+ }
65+ }
66+ XSync (dpy, False);
67+ priv->damages.clear ();
68+
69 priv->damage = CompRegion ();
70
71 int mask = priv->damageMask;
72
73=== modified file 'plugins/composite/src/window.cpp'
74--- plugins/composite/src/window.cpp 2012-06-06 05:12:28 +0000
75+++ plugins/composite/src/window.cpp 2012-06-24 10:15:24 +0000
76@@ -36,7 +36,7 @@
77 if (w->windowClass () != InputOnly)
78 {
79 priv->damage = XDamageCreate (s->dpy (), w->id (),
80- XDamageReportRawRectangles);
81+ XDamageReportBoundingBox);
82 }
83 else
84 {
85
86=== modified file 'plugins/copytex/src/copytex.cpp'
87--- plugins/copytex/src/copytex.cpp 2012-05-27 04:32:55 +0000
88+++ plugins/copytex/src/copytex.cpp 2012-06-24 10:15:24 +0000
89@@ -80,7 +80,7 @@
90 MIN (h, maxTS)));
91
92
93- cp->damage = XDamageCreate (screen->dpy (), cp->pixmap, XDamageReportRawRectangles);
94+ cp->damage = XDamageCreate (screen->dpy (), cp->pixmap, XDamageReportBoundingBox);
95 CopytexScreen::get (screen)->pixmaps[cp->damage] = cp;
96
97 return cp;
98
99=== modified file 'plugins/decor/src/decor.cpp'
100--- plugins/decor/src/decor.cpp 2012-06-19 06:03:04 +0000
101+++ plugins/decor/src/decor.cpp 2012-06-24 10:15:24 +0000
102@@ -347,7 +347,7 @@
103 textures[0]->setMipmap (false);
104
105 damage = XDamageCreate (screen->dpy (), pixmap->getPixmap (),
106- XDamageReportRawRectangles);
107+ XDamageReportBoundingBox);
108 }
109
110 /*
111@@ -1986,7 +1986,7 @@
112 oldHeight = 0;
113
114 frameDamage = XDamageCreate (screen->dpy (), outputFrame,
115- XDamageReportRawRectangles);
116+ XDamageReportBoundingBox);
117
118 dScreen->frames[outputFrame] = this;
119 }
120
121=== modified file 'plugins/opengl/src/texture.cpp'
122--- plugins/opengl/src/texture.cpp 2012-06-05 09:31:34 +0000
123+++ plugins/opengl/src/texture.cpp 2012-06-24 10:15:24 +0000
124@@ -581,7 +581,7 @@
125 glBindTexture (texTarget, 0);
126
127 tex->damage = XDamageCreate (screen->dpy (), pixmap,
128- XDamageReportRawRectangles);
129+ XDamageReportBoundingBox);
130 boundPixmapTex[tex->damage] = tex;
131
132 return rv;

Subscribers

People subscribed via source and target branches