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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.performance_1040478
Merge into: lp:compiz/0.9.9
Diff against target: 4940 lines (+1336/-1650)
21 files modified
include/core/configurerequestbuffer.h (+0/-73)
plugins/opengl/CMakeLists.txt (+6/-0)
plugins/opengl/include/opengl/framebufferobject.h (+182/-41)
plugins/opengl/include/opengl/opengl-api.h (+42/-0)
plugins/opengl/include/opengl/opengl.h (+82/-22)
plugins/opengl/src/fbdirectdraw/CMakeLists.txt (+32/-0)
plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h (+111/-0)
plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp (+177/-0)
plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt (+24/-0)
plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp (+237/-0)
plugins/opengl/src/framebufferobject.cpp (+112/-104)
plugins/opengl/src/paint.cpp (+10/-80)
plugins/opengl/src/privates.h (+49/-7)
plugins/opengl/src/screen.cpp (+251/-34)
plugins/water/src/water.cpp (+17/-9)
plugins/water/src/water.h (+4/-4)
src/asyncserverwindow.h (+0/-52)
src/configurerequestbuffer-impl.h (+0/-145)
src/configurerequestbuffer.cpp (+0/-363)
src/syncserverwindow.h (+0/-49)
src/tests/test_configurerequestbuffer.cpp (+0/-667)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.performance_1040478
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Sam Spilsbury Pending
jenkins continuous-integration Pending
Review via email: mp+150738@code.launchpad.net

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

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

Commit message

Implement support for glBlitFramebuffer. On some platforms this may speed up the final composite operation as we skip the fragment processor entirely.

The logic around this code is basically that if glBlitFramebuffer fails, then we don't use it again (the failure case is it not being available), and use the fallback textured draw code.

Tests added for the new module FramebufferDirectDraw.

(LP: #1040478) (LP: #1051287)

Description of the change

Proposing this now so I can get some early feedback.

Implement support for glBlitFramebuffer. On some platforms this may speed up the final composite operation as we skip the fragment processor entirely.

The logic around this code is basically that if glBlitFramebuffer fails, then we don't use it again (the failure case is it not being available), and use the fallback textured draw code.

Tests added for the new module FramebufferDirectDraw.

The API and ABI of GLFramebufferObject were broken too so that we could specify which buffer we actually wanted to bind.

Also added new concepts of framebuffer binding points. These are now responsible for binding framebuffers to the GL_DRAW_FRAMEBUFFER or GL_READ_FRAMEBUFFER rather than the object itself. This effectively means that we can optimize out multiple binds of the same object, or leave objects bound until they /actually/ need to change.

To post a comment you must log in.
Revision history for this message
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
jenkins (martin-mrazik+qa) 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

I have not seen any improvement yet myself. It would have to be quite significant to risk large changes to the 0.9.8 tree right now.

As far as I can tell, this is not required for quantal. So please repropose it after we've branched for 0.9.9.

review: Needs Resubmitting
Revision history for this message
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Don't we want to fix bug 1051287 before merging this?

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

Probably a good idea. Lets do that.

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

Though, I'm not entirely certain. In order to fix it properly I'll need to add a concept of framebuffer bindings points to opengl, that could inflate this change a little more (or at least introduce a dependency)

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

OK, then. Bug 1051287 needs fixing here.

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

Lets look into this again post 0.9.9.0

review: Needs Resubmitting
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

165 + * This since this code only draws a rectangular region from one
should probably be:
165 + * Since this code only draws a rectangular region from one

The copyright in plugins/opengl/include/opengl/opengl-api.h seems to be incorrect.

Is the fallthrough in plugins/opengl/src/framebufferobject.cpp intentional ?
1323 switch (status)
1324 {
1325 - case GL::FRAMEBUFFER_COMPLETE:
1326 + case GL::FRAMEBUFFER_COMPLETE:
1327 return "GL::FRAMEBUFFER_COMPLETE";
1328 - case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1329 + case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1330 return "GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
1331 - case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1332 + case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1333 return "GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
1334 - case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1335 + case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1336 return "GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
1337 - case GL::FRAMEBUFFER_UNSUPPORTED:
1338 + case GL::FRAMEBUFFER_UNSUPPORTED:
1339 return "GL::FRAMEBUFFER_UNSUPPORTED";
1340 default:
1341 return "unexpected status";
1342 }

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

On Sun, Feb 10, 2013 at 8:28 PM, MC Return <email address hidden> wrote:
> 165 + * This since this code only draws a rectangular region from one
> should probably be:
> 165 + * Since this code only draws a rectangular region from one
>
> The copyright in plugins/opengl/include/opengl/opengl-api.h seems to be incorrect.

Thanks, I'll update it.

>
> Is the fallthrough in plugins/opengl/src/framebufferobject.cpp intentional ?
> 1323 switch (status)
> 1324 {
> 1325 - case GL::FRAMEBUFFER_COMPLETE:
> 1326 + case GL::FRAMEBUFFER_COMPLETE:
> 1327 return "GL::FRAMEBUFFER_COMPLETE";
> 1328 - case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
> 1329 + case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
> 1330 return "GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
> 1331 - case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
> 1332 + case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
> 1333 return "GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
> 1334 - case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
> 1335 + case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
> 1336 return "GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
> 1337 - case GL::FRAMEBUFFER_UNSUPPORTED:
> 1338 + case GL::FRAMEBUFFER_UNSUPPORTED:
> 1339 return "GL::FRAMEBUFFER_UNSUPPORTED";
> 1340 default:
> 1341 return "unexpected status";
> 1342 }
>

No fall-through is possible, since we return directly.

> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.performance_1040478/+merge/147541
> You proposed lp:~compiz-team/compiz/compiz.performance_1040478 for merging.

--
Sam Spilsbury

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

>
> No fall-through is possible, since we return directly.
>
Ah, yeah - you are right ofc. - sorry 'bout that.

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

Checking the copyright again on opengl-api.h, I don't think there is any problem there. All I did for that code was cut-and-paste part of private.h, no actual modification on my part.

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
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 here as well.

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

Thanks. I fixed that yesterday but seemed to forget to push it here.

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

Merge lp:compiz

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

Unrevert changes reverted by a merge

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

Unmerged revisions

3419. By Sam Spilsbury

Unrevert changes reverted by a merge

3418. By Sam Spilsbury

Merge lp:compiz

3417. By Sam Spilsbury

Merge lp:compiz

3416. By Sam Spilsbury

Make the currently bound drawbuffer available to plugins (as they might want
to do a read/draw swap)

3415. By Sam Spilsbury

Revert more changes which should not have happened

3414. By Sam Spilsbury

Merge lp:compiz

3413. By Sam Spilsbury

Fix merge errors

3412. By Sam Spilsbury

Merge lp:compiz

3411. By Sam Spilsbury

Another botched merge

3410. By Sam Spilsbury

Unrevert changes which shouldn't have been reverted

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'include/core/configurerequestbuffer.h'
2--- include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000
3+++ include/core/configurerequestbuffer.h 2013-02-28 02:29:22 +0000
4@@ -0,0 +1,73 @@
5+/*
6+ * Copyright © 2012 Sam Spilsbury
7+ *
8+ * Permission to use, copy, modify, distribute, and sell this software
9+ * and its documentation for any purpose is hereby granted without
10+ * fee, provided that the above copyright notice appear in all copies
11+ * and that both that copyright notice and this permission notice
12+ * appear in supporting documentation, and that the name of
13+ * Canonical Ltd. not be used in advertising or publicity pertaining to
14+ * distribution of the software without specific, written prior permission.
15+ * Canonical Ltd. makes no representations about the suitability of this
16+ * software for any purpose. It is provided "as is" without express or
17+ * implied warranty.
18+ *
19+ * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
21+ * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
23+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26+ *
27+ * Authored by: Sam Spilsbury <smspillaz@gmail.com>
28+ */
29+#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
30+#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
31+
32+#include <boost/shared_ptr.hpp>
33+#include <X11/Xlib.h>
34+#include <syncserverwindow.h>
35+
36+namespace compiz
37+{
38+namespace window
39+{
40+namespace configure_buffers
41+{
42+class Releasable
43+{
44+ public:
45+
46+ typedef boost::shared_ptr <Releasable> Ptr;
47+
48+ virtual void release () = 0;
49+};
50+
51+class Buffer :
52+ public SyncServerWindow
53+{
54+ public:
55+
56+ typedef boost::shared_ptr <Buffer> Ptr;
57+
58+ virtual ~Buffer () {}
59+
60+ virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
61+ virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
62+ virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
63+
64+ virtual void pushSyntheticConfigureNotify () = 0;
65+
66+ virtual Releasable::Ptr obtainLock () = 0;
67+
68+ /* This API will all configure requests to be
69+ * released. It should only be used in situations
70+ * where you have a server grab and need
71+ * to have complete sync with the server */
72+ virtual void forceRelease () = 0;
73+};
74+}
75+}
76+}
77+#endif
78
79=== removed file 'include/core/configurerequestbuffer.h'
80--- include/core/configurerequestbuffer.h 2012-12-13 11:12:32 +0000
81+++ include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000
82@@ -1,73 +0,0 @@
83-/*
84- * Copyright © 2012 Sam Spilsbury
85- *
86- * Permission to use, copy, modify, distribute, and sell this software
87- * and its documentation for any purpose is hereby granted without
88- * fee, provided that the above copyright notice appear in all copies
89- * and that both that copyright notice and this permission notice
90- * appear in supporting documentation, and that the name of
91- * Canonical Ltd. not be used in advertising or publicity pertaining to
92- * distribution of the software without specific, written prior permission.
93- * Canonical Ltd. makes no representations about the suitability of this
94- * software for any purpose. It is provided "as is" without express or
95- * implied warranty.
96- *
97- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
98- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
99- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
100- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
101- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
102- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
103- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
104- *
105- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
106- */
107-#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
108-#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
109-
110-#include <boost/shared_ptr.hpp>
111-#include <X11/Xlib.h>
112-#include <syncserverwindow.h>
113-
114-namespace compiz
115-{
116-namespace window
117-{
118-namespace configure_buffers
119-{
120-class Releasable
121-{
122- public:
123-
124- typedef boost::shared_ptr <Releasable> Ptr;
125-
126- virtual void release () = 0;
127-};
128-
129-class Buffer :
130- public SyncServerWindow
131-{
132- public:
133-
134- typedef boost::shared_ptr <Buffer> Ptr;
135-
136- virtual ~Buffer () {}
137-
138- virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
139- virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
140- virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
141-
142- virtual void pushSyntheticConfigureNotify () = 0;
143-
144- virtual Releasable::Ptr obtainLock () = 0;
145-
146- /* This API will all configure requests to be
147- * released. It should only be used in situations
148- * where you have a server grab and need
149- * to have complete sync with the server */
150- virtual void forceRelease () = 0;
151-};
152-}
153-}
154-}
155-#endif
156
157=== modified file 'plugins/opengl/CMakeLists.txt'
158--- plugins/opengl/CMakeLists.txt 2012-12-12 07:33:12 +0000
159+++ plugins/opengl/CMakeLists.txt 2013-02-28 02:29:22 +0000
160@@ -5,15 +5,21 @@
161 set (INTERNAL_LIBRARIES
162 compiz_opengl_double_buffer
163 compiz_opengl_fsregion
164+ compiz_opengl_framebuffer_direct_draw
165 compiz_opengl_blacklist
166 compiz_opengl_glx_tfp_bind
167 )
168
169+set (COMPIZ_OPENGL_PLUGIN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
170+set (COMPIZ_OPENGL_PLUGIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
171+
172 add_subdirectory (src/doublebuffer)
173 add_subdirectory (src/fsregion)
174+add_subdirectory (src/fbdirectdraw)
175 add_subdirectory (src/blacklist)
176 add_subdirectory (src/glxtfpbind)
177
178+include_directories (src/fbdirectdraw/include)
179 include_directories (src/glxtfpbind/include)
180
181 if (USE_GLES)
182
183=== modified file 'plugins/opengl/include/opengl/framebufferobject.h'
184--- plugins/opengl/include/opengl/framebufferobject.h 2012-08-09 02:19:26 +0000
185+++ plugins/opengl/include/opengl/framebufferobject.h 2013-02-28 02:29:22 +0000
186@@ -26,29 +26,177 @@
187 #ifndef _COMPIZ_GLFRAMEBUFFEROBJECT_H
188 #define _COMPIZ_GLFRAMEBUFFEROBJECT_H
189
190-#include <opengl/opengl.h>
191+#include <list>
192+#include <boost/function.hpp>
193+#include <opengl/opengl-api.h>
194+#include <core/size.h>
195+#include <core/rect.h>
196+
197+class GLVertexBuffer;
198+class GLTexture;
199+
200+namespace compiz
201+{
202+namespace opengl
203+{
204+typedef enum _BlitMask
205+{
206+ ColorData = (1 << 0),
207+ StencilData = (1 << 1)
208+} BlitMask;
209+
210+typedef enum _Filter
211+{
212+ Fast = 0,
213+ Good = 1,
214+} Filter;
215+
216+typedef enum _BindPoint
217+{
218+ Read = 0,
219+ Draw = 1
220+} BindPoint;
221+
222+class BindableFramebuffer
223+{
224+ public:
225+
226+ virtual ~BindableFramebuffer () {}
227+
228+ virtual GLuint getResourceId () const = 0;
229+ virtual bool setBindStatus (GLenum) = 0;
230+ virtual void updateAllocation (GLenum) = 0;
231+};
232+
233+class BindLocation
234+{
235+ public:
236+
237+ virtual ~BindLocation () {}
238+
239+ /**
240+ * Bind the specified BindableFramebuffer to this bind location
241+ * usually either as the read target or the draw target
242+ *
243+ * The previous FBO is no longer bound. If it was bound to the
244+ * draw target, it will be safe to use its texture.
245+ *
246+ * This returns the last-bound BindableFramebuffer object on
247+ * success and NULL on failure (no change). Call this again
248+ * in order to restore that framebuffer
249+ */
250+ virtual BindableFramebuffer * bind (BindableFramebuffer *) = 0;
251+ virtual BindableFramebuffer * getCurrentlyBound () = 0;
252+};
253+
254+typedef boost::function <bool (const CompRect &src,
255+ const CompRect &dst,
256+ GLbitfield mask,
257+ GLenum filter)> RectangularDraw;
258+typedef std::list <RectangularDraw> RectangularDrawList;
259+
260+class DirectDrawStrategies
261+{
262+ public:
263+
264+ typedef boost::shared_ptr <DirectDrawStrategies> Ptr;
265+
266+ virtual ~DirectDrawStrategies () {}
267+ virtual void draw (const CompRect &src,
268+ const CompRect &dst,
269+ BlitMask mask,
270+ Filter filter) = 0;
271+};
272+
273+class FramebufferObject
274+{
275+ public:
276+
277+ virtual ~FramebufferObject () {}
278+
279+ /**
280+ * Ensure the texture is of the given size, recreating it if needed,
281+ * and replace the FBO color attachment with it. The texture contents
282+ * become undefined, unless specified in the 'image' argument.
283+ * When specifying 'image', it's also possible to pass-in the
284+ * desired image's 'format' and 'type'.
285+ *
286+ * Returns true on success, and false on texture allocation failure.
287+ */
288+ virtual bool allocate (const CompSize &size,
289+ const char *image = NULL,
290+ GLenum format = GL_RGBA,
291+ GLenum type = GL_UNSIGNED_BYTE) = 0;
292+
293+ /**
294+ * Check the FBO completeness. Returns true on complete.
295+ * Otherwise returns false and reports the error to log.
296+ */
297+ virtual bool checkStatus () = 0;
298+
299+ /**
300+ * Return a pointer to the texture that is the color attachment.
301+ * This will return NULL, if allocate () has not been called, or
302+ * the last allocate () call failed.
303+ */
304+ virtual GLTexture * tex () = 0;
305+};
306+
307+class DirectDrawObject :
308+ virtual public compiz::opengl::FramebufferObject,
309+ virtual public compiz::opengl::BindableFramebuffer
310+{
311+ public:
312+
313+ virtual ~DirectDrawObject () {};
314+
315+ /**
316+ * Draws a region of the framebuffer object as specified in
317+ * framebuffer-specified co-ordinates as @src co-ordinates in
318+ * the buffer currently bound co-ordinates @dst . @mask indicates
319+ * what kind of data should be propogated downwards. @filter indicates
320+ * what kind of filter should be used when drawing this buffer
321+ *
322+ * This since this code only draws a rectangular region from one
323+ * framebuffer to another, it will try and use the fastest codepath
324+ * possible, falling back to a simple textured draw if
325+ * glBlitFramebuffer is not available
326+ *
327+ */
328+ virtual void directDraw (const CompRect &src,
329+ const CompRect &dst,
330+ compiz::opengl::BlitMask mask,
331+ compiz::opengl::Filter filter) = 0;
332+};
333+
334+namespace impl
335+{
336+namespace cgl = compiz::opengl;
337
338 struct PrivateGLFramebufferObject;
339
340-/**
341- * Class representing a framebuffer object in GL, supporting only one
342- * color attachment as per GLES 2 spec. The color attachment is referred
343- * to as the texture (of the FBO).
344- *
345- * Usage:
346- * 1. create a GLFramebufferObject (requires a GL context)
347- * 2. call allocate (size), and check status ()
348- * 3. old = bind ()
349- * 4. do your rendering
350- * 5. rebind (old)
351- * 6. use the rendered texture via tex ()
352- * 7. go to 2 or 3, or delete to quit (requires a GL context)
353- */
354-class GLFramebufferObject
355-{
356- public:
357- GLFramebufferObject ();
358- ~GLFramebufferObject ();
359+class FBOBindLocation :
360+ public cgl::BindLocation
361+{
362+ public:
363+
364+ FBOBindLocation (GLenum binding, BindableFramebuffer *back);
365+ BindableFramebuffer * bind (BindableFramebuffer *);
366+ BindableFramebuffer * getCurrentlyBound ();
367+
368+ private:
369+
370+ class Private;
371+ std::auto_ptr <Private> priv;
372+};
373+
374+class FramebufferObject :
375+ public cgl::FramebufferObject,
376+ public cgl::BindableFramebuffer
377+{
378+ public:
379+ FramebufferObject ();
380+ ~FramebufferObject ();
381
382 /**
383 * Ensure the texture is of the given size, recreating it if needed,
384@@ -65,26 +213,6 @@
385 GLenum type = GL_UNSIGNED_BYTE);
386
387 /**
388- * Bind this as the current FBO, previous binding in GL context is
389- * undone. GL rendering is now targeted to this FBO.
390- * Returns a pointer to the previously bound FBO, or NULL if
391- * the previous binding was zero (the window system provided
392- * framebuffer).
393- *
394- * The previous FBO is no longer bound, so you can use its
395- * texture. To restore the previous FBO, call rebind (FBO) with
396- * the returned pointer as the argument.
397- */
398- GLFramebufferObject *bind ();
399-
400- /**
401- * Bind the given FBO as the current FBO, without looking up the
402- * previous binding. The argument can be NULL, in which case the
403- * window system provided framebuffer gets bound (FBO is unbound).
404- */
405- static void rebind (GLFramebufferObject *fbo);
406-
407- /**
408 * Check the FBO completeness. Returns true on complete.
409 * Otherwise returns false and reports the error to log.
410 */
411@@ -95,10 +223,23 @@
412 * This will return NULL, if allocate () has not been called, or
413 * the last allocate () call failed.
414 */
415- GLTexture *tex ();
416+ GLTexture * tex ();
417
418 private:
419+
420+ /**
421+ * Returns the framebuffer identifier
422+ */
423+ GLuint getResourceId () const;
424+ bool setBindStatus (GLenum);
425+ void updateAllocation (GLenum bindingLocation);
426+
427 PrivateGLFramebufferObject *priv;
428 };
429+}
430+}
431+}
432+
433+typedef compiz::opengl::impl::FramebufferObject GLFramebufferObject;
434
435 #endif // _COMPIZ_GLFRAMEBUFFEROBJECT_H
436
437=== added file 'plugins/opengl/include/opengl/opengl-api.h'
438--- plugins/opengl/include/opengl/opengl-api.h 1970-01-01 00:00:00 +0000
439+++ plugins/opengl/include/opengl/opengl-api.h 2013-02-28 02:29:22 +0000
440@@ -0,0 +1,42 @@
441+/*
442+ * Copyright © 2008 Dennis Kasprzyk
443+ * Copyright © 2007 Novell, Inc.
444+ *
445+ * Permission to use, copy, modify, distribute, and sell this software
446+ * and its documentation for any purpose is hereby granted without
447+ * fee, provided that the above copyright notice appear in all copies
448+ * and that both that copyright notice and this permission notice
449+ * appear in supporting documentation, and that the name of
450+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
451+ * distribution of the software without specific, written prior permission.
452+ * Dennis Kasprzyk makes no representations about the suitability of this
453+ * software for any purpose. It is provided "as is" without express or
454+ * implied warranty.
455+ *
456+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
457+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
458+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
459+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
460+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
461+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
462+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
463+ *
464+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
465+ * David Reveman <davidr@novell.com>
466+ */
467+
468+#ifndef _COMPIZ_OPENGL_API_H
469+#define _COMPIZ_OPENGL_API_H
470+
471+#ifdef USE_GLES
472+#define SUPPORT_X11
473+#include <GLES2/gl2.h>
474+#include <GLES2/gl2ext.h>
475+#include <EGL/egl.h>
476+#include <EGL/eglext.h>
477+#else
478+#include <GL/gl.h>
479+#include <GL/glx.h>
480+#endif
481+
482+#endif
483
484=== modified file 'plugins/opengl/include/opengl/opengl.h'
485--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
486+++ plugins/opengl/include/opengl/opengl.h 2013-02-28 02:29:22 +0000
487@@ -28,29 +28,19 @@
488 #ifndef _COMPIZ_OPENGL_H
489 #define _COMPIZ_OPENGL_H
490
491-#ifdef USE_GLES
492-#define SUPPORT_X11
493-#include <GLES2/gl2.h>
494-#include <GLES2/gl2ext.h>
495-#include <EGL/egl.h>
496-#include <EGL/eglext.h>
497-#else
498-#include <GL/gl.h>
499-#include <GL/glx.h>
500-#endif
501+#include <opengl/opengl-api.h>
502
503 #include <core/size.h>
504 #include <core/pluginclasshandler.h>
505
506 #include <opengl/matrix.h>
507 #include <opengl/texture.h>
508-#include <opengl/framebufferobject.h>
509 #include <opengl/vertexbuffer.h>
510 #include <opengl/program.h>
511 #include <opengl/programcache.h>
512 #include <opengl/shadercache.h>
513
514-#define COMPIZ_OPENGL_ABI 6
515+#define COMPIZ_OPENGL_ABI 7
516
517 /*
518 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
519@@ -84,9 +74,38 @@
520 extern const float GREEN_SATURATION_WEIGHT;
521 extern const float BLUE_SATURATION_WEIGHT;
522
523+class GLScreen;
524 class PrivateGLScreen;
525 class PrivateGLWindow;
526
527+namespace compiz
528+{
529+namespace opengl
530+{
531+typedef boost::function <bool (const CompRect &src,
532+ const CompRect &dst,
533+ GLbitfield mask,
534+ GLenum filter)> BlitFramebufferFunc;
535+
536+class DirectDrawObject;
537+class FramebufferObject;
538+class BindableFramebuffer;
539+
540+/**
541+ * Convenience method to construct a framebuffer object that
542+ * supports GLX_EXT_blit_framebuffer and a fallback path
543+ */
544+DirectDrawObject *createBlittableFramebufferObjectWithFallback(const CompSize &sz, GLScreen *gScreen);
545+
546+namespace impl
547+{
548+class FramebufferObject;
549+}
550+}
551+}
552+
553+typedef compiz::opengl::impl::FramebufferObject GLFramebufferObject;
554+
555 extern GLushort defaultColor[4];
556
557 #ifndef GLX_EXT_texture_from_pixmap
558@@ -313,6 +332,18 @@
559 GLsizei width,
560 GLsizei height);
561
562+ /* GLX_EXT_blit_framebuffer */
563+ typedef void (*GLBlitFramebufferProc) (GLint srcX0,
564+ GLint srcY0,
565+ GLint srcX1,
566+ GLint srcY1,
567+ GLint dstX0,
568+ GLint dstY0,
569+ GLint dstX1,
570+ GLint dstY1,
571+ GLbitfield mask,
572+ GLenum filter);
573+
574
575 /* GL_ARB_shader_objects */
576 #ifndef USE_GLES
577@@ -413,11 +444,12 @@
578 extern GLDisableVertexAttribArrayProc disableVertexAttribArray;
579 extern GLVertexAttribPointerProc vertexAttribPointer;
580
581- extern GLGenRenderbuffersProc genRenderbuffers;
582- extern GLDeleteRenderbuffersProc deleteRenderbuffers;
583- extern GLBindRenderbufferProc bindRenderbuffer;
584+ extern GLGenRenderbuffersProc genRenderbuffers;
585+ extern GLDeleteRenderbuffersProc deleteRenderbuffers;
586+ extern GLBindRenderbufferProc bindRenderbuffer;
587 extern GLFramebufferRenderbufferProc framebufferRenderbuffer;
588- extern GLRenderbufferStorageProc renderbufferStorage;
589+ extern GLRenderbufferStorageProc renderbufferStorage;
590+ extern GLBlitFramebufferProc blitFramebuffer;
591
592 #ifndef USE_GLES
593 extern GLCreateShaderObjectARBProc createShaderObjectARB;
594@@ -579,7 +611,6 @@
595 extern GLScreenPaintAttrib defaultScreenPaintAttrib;
596
597 class GLScreen;
598-class GLFramebufferObject;
599 class GLScreenInterface;
600 extern template class WrapableInterface<GLScreen, GLScreenInterface>;
601
602@@ -658,9 +689,9 @@
603 * @param scratchFbo Describes the final composited FBO that is
604 * to be rendered.
605 */
606- virtual void glPaintCompositedOutput (const CompRegion &region,
607- GLFramebufferObject *fbo,
608- unsigned int mask);
609+ virtual void glPaintCompositedOutput (const CompRegion &region,
610+ compiz::opengl::DirectDrawObject *fbo,
611+ unsigned int mask);
612
613 /**
614 * Hookable function used by plugins to determine stenciling mask
615@@ -759,13 +790,42 @@
616 /**
617 * Returns the FBO compiz is using for the screen
618 */
619- GLFramebufferObject *fbo ();
620+ compiz::opengl::FramebufferObject * fbo ();
621+
622+ /**
623+ * Binds a framebuffer for drawing, returns the old bindable
624+ */
625+ compiz::opengl::BindableFramebuffer *
626+ bindFramebufferForDrawing (compiz::opengl::BindableFramebuffer *);
627+
628+ /**
629+ * Binds a framebuffer for reading, returns the old reading
630+ */
631+ compiz::opengl::BindableFramebuffer *
632+ bindFramebufferForReading (compiz::opengl::BindableFramebuffer *);
633+
634+ /**
635+ * Gets the currently bound draw framebuffer
636+ */
637+ compiz::opengl::BindableFramebuffer *
638+ drawFramebuffer ();
639+
640+ /**
641+ * Gets the backbuffer as a BindableFramebuffer
642+ */
643+ compiz::opengl::BindableFramebuffer *
644+ backbuffer ();
645
646 /**
647 * Returns a default icon texture
648 */
649 GLTexture *defaultIcon ();
650
651+ /**
652+ * Returns the current framebuffer function for blitting the framebuffer
653+ */
654+ const compiz::opengl::BlitFramebufferFunc & blitFramebufferFunc ();
655+
656 void resetRasterPos ();
657
658 bool glInitContext (XVisualInfo *);
659@@ -786,7 +846,7 @@
660
661 WRAPABLE_HND (5, GLScreenInterface, GLMatrix *, projectionMatrix);
662 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
663- const CompRegion &, GLFramebufferObject *, unsigned int);
664+ const CompRegion &, compiz::opengl::DirectDrawObject *, unsigned int);
665
666 WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
667 GLVertexBuffer &,
668
669=== added directory 'plugins/opengl/src/fbdirectdraw'
670=== added file 'plugins/opengl/src/fbdirectdraw/CMakeLists.txt'
671--- plugins/opengl/src/fbdirectdraw/CMakeLists.txt 1970-01-01 00:00:00 +0000
672+++ plugins/opengl/src/fbdirectdraw/CMakeLists.txt 2013-02-28 02:29:22 +0000
673@@ -0,0 +1,32 @@
674+INCLUDE_DIRECTORIES (
675+ ${COMPIZ_OPENGL_PLUGIN_SOURCE_DIR}
676+ ${COMPIZ_OPENGL_PLUGIN_INCLUDE_DIR}
677+ ${CMAKE_CURRENT_SOURCE_DIR}/include
678+ ${CMAKE_CURRENT_SOURCE_DIR}/src
679+
680+ ${Boost_INCLUDE_DIRS}
681+)
682+
683+LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
684+
685+SET(
686+ SRCS
687+ ${CMAKE_CURRENT_SOURCE_DIR}/src/framebuffer-direct-draw.cpp
688+)
689+
690+ADD_LIBRARY(
691+ compiz_opengl_framebuffer_direct_draw STATIC
692+
693+ ${SRCS}
694+)
695+
696+if (COMPIZ_BUILD_TESTING)
697+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
698+endif (COMPIZ_BUILD_TESTING)
699+
700+TARGET_LINK_LIBRARIES(
701+ compiz_opengl_framebuffer_direct_draw
702+
703+ compiz_region
704+ compiz_logmessage
705+)
706
707=== added directory 'plugins/opengl/src/fbdirectdraw/include'
708=== added file 'plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h'
709--- plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h 1970-01-01 00:00:00 +0000
710+++ plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h 2013-02-28 02:29:22 +0000
711@@ -0,0 +1,111 @@
712+/*
713+ * Compiz, opengl plugin, FramebufferDirectDraw class
714+ *
715+ * Copyright (c) 2012 Canonical Ltd.
716+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
717+ *
718+ * Permission is hereby granted, free of charge, to any person obtaining a
719+ * copy of this software and associated documentation files (the "Software"),
720+ * to deal in the Software without restriction, including without limitation
721+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
722+ * and/or sell copies of the Software, and to permit persons to whom the
723+ * Software is furnished to do so, subject to the following conditions:
724+ *
725+ * The above copyright notice and this permission notice shall be included in
726+ * all copies or substantial portions of the Software.
727+ *
728+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
729+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
730+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
731+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
732+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
733+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
734+ * DEALINGS IN THE SOFTWARE.
735+ */
736+#ifndef _COMPIZ_OPENGL_FRAMEBUFFER_DIRECT_DRAW_H
737+#define _COMPIZ_OPENGL_FRAMEBUFFER_DIRECT_DRAW_H
738+
739+#include <memory>
740+#include <boost/shared_ptr.hpp>
741+#include <core/rect.h>
742+#include <opengl/framebufferobject.h>
743+
744+class GLVertexBuffer;
745+
746+namespace compiz
747+{
748+namespace opengl
749+{
750+namespace impl
751+{
752+namespace cglfb = compiz::opengl;
753+
754+class PrivateDirectDrawStrategies;
755+
756+class DirectDrawStrategies :
757+ public cglfb::DirectDrawStrategies
758+{
759+ public:
760+
761+ typedef boost::shared_ptr <DirectDrawStrategies> Ptr;
762+
763+ DirectDrawStrategies (const RectangularDrawList &strategies);
764+
765+ void draw (const CompRect &src,
766+ const CompRect &dst,
767+ BlitMask mask,
768+ Filter filter);
769+
770+ private:
771+
772+ std::auto_ptr <PrivateDirectDrawStrategies> priv;
773+};
774+
775+class PrivateDirectDrawObject;
776+
777+class DirectDrawObject :
778+ virtual public cglfb::FramebufferObject,
779+ public cglfb::DirectDrawObject
780+{
781+ public:
782+
783+ DirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &,
784+ const boost::shared_ptr <cglfb::FramebufferObject> &,
785+ const boost::shared_ptr <cglfb::BindableFramebuffer> &);
786+
787+ bool allocate (const CompSize &size,
788+ const char *image = NULL,
789+ GLenum format = GL_RGBA,
790+ GLenum type = GL_UNSIGNED_BYTE);
791+ bool checkStatus ();
792+ GLTexture * tex ();
793+
794+ void directDraw (const CompRect &src,
795+ const CompRect &dst,
796+ cglfb::BlitMask mask,
797+ cglfb::Filter filter);
798+
799+ private:
800+
801+ GLuint getResourceId () const;
802+ bool setBindStatus (GLenum);
803+ void updateAllocation (GLenum);
804+
805+ PrivateDirectDrawObject *priv;
806+};
807+
808+typedef boost::function <cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *)>
809+ BindReadBufferFunc;
810+
811+bool rectangleDrawFromReadBuffer (const CompRect &src,
812+ const CompRect &dst,
813+ GLbitfield mask,
814+ GLenum filter,
815+ cglfb::BindableFramebuffer *bindable,
816+ const BindReadBufferFunc &func,
817+ cglfb::RectangularDraw strategy);
818+}
819+}
820+}
821+
822+#endif
823
824=== added directory 'plugins/opengl/src/fbdirectdraw/src'
825=== added file 'plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp'
826--- plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp 1970-01-01 00:00:00 +0000
827+++ plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp 2013-02-28 02:29:22 +0000
828@@ -0,0 +1,177 @@
829+/*
830+ * Compiz, opengl plugin, DirectDrawFramebufferStrategies class
831+ *
832+ * Copyright (c) 2012 Canonical Ltd.
833+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
834+ *
835+ * Permission is hereby granted, free of charge, to any person obtaining a
836+ * copy of this software and associated documentation files (the "Software"),
837+ * to deal in the Software without restriction, including without limitation
838+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
839+ * and/or sell copies of the Software, and to permit persons to whom the
840+ * Software is furnished to do so, subject to the following conditions:
841+ *
842+ * The above copyright notice and this permission notice shall be included in
843+ * all copies or substantial portions of the Software.
844+ *
845+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
846+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
847+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
848+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
849+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
850+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
851+ * DEALINGS IN THE SOFTWARE.
852+ */
853+#include "framebuffer-direct-draw.h"
854+
855+namespace cglfb = compiz::opengl;
856+namespace cglfbi = compiz::opengl::impl;
857+
858+class GLTexture;
859+class GLVertexBuffer;
860+
861+namespace compiz
862+{
863+namespace opengl
864+{
865+namespace impl
866+{
867+class PrivateDirectDrawStrategies
868+{
869+ public:
870+
871+ PrivateDirectDrawStrategies (const cglfb::RectangularDrawList &strategies) :
872+ rectDrawList (strategies)
873+ {
874+ }
875+
876+ cglfb::RectangularDrawList rectDrawList;
877+};
878+
879+class PrivateDirectDrawObject
880+{
881+ public:
882+
883+ PrivateDirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &strategies,
884+ const boost::shared_ptr <cglfb::FramebufferObject> &object,
885+ const boost::shared_ptr <cglfb::BindableFramebuffer> &bindable) :
886+ directDrawStrategies (strategies),
887+ framebufferObject (object),
888+ bindableFramebuffer (bindable)
889+ {
890+ };
891+
892+ boost::shared_ptr <cglfb::DirectDrawStrategies> directDrawStrategies;
893+ boost::shared_ptr <cglfb::FramebufferObject> framebufferObject;
894+ boost::shared_ptr <cglfb::BindableFramebuffer> bindableFramebuffer;
895+};
896+}
897+}
898+}
899+
900+cglfbi::DirectDrawObject::DirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &strategies,
901+ const boost::shared_ptr <cglfb::FramebufferObject> &object,
902+ const boost::shared_ptr <cglfb::BindableFramebuffer> &bindable) :
903+ priv (new cglfbi::PrivateDirectDrawObject (strategies, object, bindable))
904+{
905+}
906+
907+bool
908+cglfbi::DirectDrawObject::allocate (const CompSize &size, const char *image,
909+ GLenum format, GLenum type)
910+{
911+ return priv->framebufferObject->allocate (size, image, format, type);
912+}
913+
914+bool
915+cglfbi::DirectDrawObject::checkStatus ()
916+{
917+ return priv->framebufferObject->checkStatus ();
918+}
919+
920+GLTexture *
921+cglfbi::DirectDrawObject::tex ()
922+{
923+ return priv->framebufferObject->tex ();
924+}
925+
926+GLuint
927+cglfbi::DirectDrawObject::getResourceId () const
928+{
929+ return priv->bindableFramebuffer->getResourceId ();
930+}
931+
932+bool
933+cglfbi::DirectDrawObject::setBindStatus (GLenum status)
934+{
935+ return priv->bindableFramebuffer->setBindStatus (status);
936+}
937+
938+void
939+cglfbi::DirectDrawObject::updateAllocation (GLenum bindPoint)
940+{
941+ return priv->bindableFramebuffer->updateAllocation (bindPoint);
942+}
943+
944+void
945+cglfbi::DirectDrawObject::directDraw (const CompRect &src,
946+ const CompRect &dst,
947+ cglfb::BlitMask mask,
948+ cglfb::Filter filter)
949+{
950+ if (!checkStatus ())
951+ return;
952+
953+ priv->directDrawStrategies->draw (src, dst, mask, filter);
954+}
955+
956+bool
957+cglfbi::rectangleDrawFromReadBuffer (const CompRect &src,
958+ const CompRect &dst,
959+ GLbitfield mask,
960+ GLenum filter,
961+ cglfb::BindableFramebuffer *bindable,
962+ const cglfbi::BindReadBufferFunc &bindReadBuffer,
963+ cglfb::RectangularDraw strategy)
964+{
965+ bool status = false;
966+ /* Bind to the read framebuffer first */
967+ cglfb::BindableFramebuffer *old = bindReadBuffer (bindable);
968+
969+ if (old)
970+ status = strategy (src, dst, mask, filter);
971+
972+ /* Intentionally not rebinding the old one */
973+
974+ return status;
975+}
976+
977+cglfbi::DirectDrawStrategies::DirectDrawStrategies (const cglfb::RectangularDrawList &strategies) :
978+ priv (new cglfbi::PrivateDirectDrawStrategies (strategies))
979+{
980+}
981+
982+void
983+cglfbi::DirectDrawStrategies::draw (const CompRect &src,
984+ const CompRect &dst,
985+ cglfb::BlitMask mask,
986+ cglfb::Filter filter)
987+{
988+ if (!mask)
989+ return;
990+
991+ const GLbitfield glMask = (mask & cglfb::ColorData ? GL_COLOR_BUFFER_BIT : 0) |
992+ (mask & cglfb::StencilData ? GL_STENCIL_BUFFER_BIT : 0);
993+ const GLenum glFilter = (filter == cglfb::Fast ? GL_NEAREST : GL_LINEAR);
994+
995+ while (!priv->rectDrawList.empty ())
996+ {
997+ const cglfb::RectangularDraw &strategy = priv->rectDrawList.back ();
998+
999+ /* If one method fails, try the next */
1000+ if (!strategy (src, dst, glMask, glFilter))
1001+ priv->rectDrawList.pop_back ();
1002+ else
1003+ break;
1004+ }
1005+}
1006
1007=== added directory 'plugins/opengl/src/fbdirectdraw/tests'
1008=== added file 'plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt'
1009--- plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
1010+++ plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt 2013-02-28 02:29:22 +0000
1011@@ -0,0 +1,24 @@
1012+find_library (GMOCK_LIBRARY gmock)
1013+find_library (GMOCK_MAIN_LIBRARY gmock_main)
1014+
1015+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
1016+ message ("Google Mock and Google Test not found - cannot build tests!")
1017+ set (COMPIZ_BUILD_TESTING OFF)
1018+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
1019+
1020+include_directories (${GTEST_INCLUDE_DIRS})
1021+
1022+link_directories (${COMPIZ_LIBRARY_DIRS})
1023+
1024+add_executable (compiz_test_opengl_framebuffer_direct_draw
1025+ ${CMAKE_CURRENT_SOURCE_DIR}/test-opengl-framebuffer-direct-draw.cpp)
1026+
1027+target_link_libraries (compiz_test_opengl_framebuffer_direct_draw
1028+ compiz_opengl_framebuffer_direct_draw
1029+ ${GTEST_BOTH_LIBRARIES}
1030+ ${GMOCK_LIBRARY}
1031+ ${GMOCK_MAIN_LIBRARY}
1032+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
1033+ )
1034+
1035+compiz_discover_tests (compiz_test_opengl_framebuffer_direct_draw COVERAGE compiz_opengl_framebuffer_direct_draw)
1036
1037=== added file 'plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp'
1038--- plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp 1970-01-01 00:00:00 +0000
1039+++ plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp 2013-02-28 02:29:22 +0000
1040@@ -0,0 +1,237 @@
1041+/*
1042+ * Compiz, opengl plugin, DirectDrawFramebufferStrategies class
1043+ *
1044+ * Copyright (c) 2012 Canonical Ltd.
1045+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
1046+ *
1047+ * Permission is hereby granted, free of charge, to any person obtaining a
1048+ * copy of this software and associated documentation files (the "Software"),
1049+ * to deal in the Software without restriction, including without limitation
1050+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1051+ * and/or sell copies of the Software, and to permit persons to whom the
1052+ * Software is furnished to do so, subject to the following conditions:
1053+ *
1054+ * The above copyright notice and this permission notice shall be included in
1055+ * all copies or substantial portions of the Software.
1056+ *
1057+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1058+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1059+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1060+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1061+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1062+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1063+ * DEALINGS IN THE SOFTWARE.
1064+ */
1065+#include <memory>
1066+#include <boost/function.hpp>
1067+#include <boost/bind.hpp>
1068+#include <gtest/gtest.h>
1069+#include <gmock/gmock.h>
1070+#include <opengl/opengl-api.h>
1071+#include <opengl/framebufferobject.h>
1072+#include "framebuffer-direct-draw.h"
1073+
1074+using ::testing::Return;
1075+using ::testing::_;
1076+using ::testing::Expectation;
1077+using ::testing::StrictMock;
1078+using ::testing::NiceMock;
1079+using ::testing::ReturnNull;
1080+
1081+namespace cglfb = compiz::opengl;
1082+namespace cglfbi = compiz::opengl::impl;
1083+
1084+namespace
1085+{
1086+class MockDrawStrategy
1087+{
1088+ public:
1089+
1090+ MOCK_METHOD4 (draw, bool (const CompRect &,
1091+ const CompRect &,
1092+ GLbitfield,
1093+ GLenum));
1094+};
1095+
1096+class MockBindLocation :
1097+ public cglfb::BindLocation
1098+{
1099+ public:
1100+
1101+ MOCK_METHOD1 (bind, cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *));
1102+ MOCK_METHOD0 (getCurrentlyBound, cglfb::BindableFramebuffer * ());
1103+};
1104+
1105+class MockBindable :
1106+ public cglfb::BindableFramebuffer
1107+{
1108+ public:
1109+
1110+ MOCK_METHOD1 (updateAllocation, void (GLenum));
1111+ MOCK_METHOD1 (setBindStatus, bool (GLenum));
1112+ MOCK_CONST_METHOD0 (getResourceId, GLuint ());
1113+};
1114+
1115+}
1116+
1117+class FBDirectDrawStrategies :
1118+ public ::testing::Test
1119+{
1120+ public:
1121+
1122+ FBDirectDrawStrategies () :
1123+ blitFramebuffer (boost::bind (&MockDrawStrategy::draw, &mpfb, _1, _2, _3, _4)),
1124+ rtdraw (boost::bind (&MockDrawStrategy::draw, &mdr,
1125+ _1, _2, _3, _4))
1126+ {
1127+ }
1128+
1129+ void SetUpStrategyList (const cglfb::RectangularDraw &blit,
1130+ const cglfb::RectangularDraw &draw)
1131+ {
1132+ strategyList.clear ();
1133+ strategyList.push_back (draw);
1134+ strategyList.push_back (blit);
1135+ }
1136+
1137+ virtual void SetUp ()
1138+ {
1139+ boost::function <cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *)> readBind
1140+ (boost::bind (&MockBindLocation::bind, &mockBindLocation, _1));
1141+ blitFramebufferWithReadPushed = boost::bind (&cglfbi::rectangleDrawFromReadBuffer,
1142+ _1, _2, _3, _4,
1143+ &mockBindable,
1144+ readBind,
1145+ blitFramebuffer);
1146+
1147+ SetUpStrategyList (blitFramebuffer, rtdraw);
1148+ directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
1149+ }
1150+
1151+ std::auto_ptr <cglfbi::DirectDrawStrategies> directDraw;
1152+ MockDrawStrategy mpfb;
1153+ cglfb::RectangularDraw blitFramebuffer;
1154+ cglfb::RectangularDraw blitFramebufferWithReadPushed;
1155+ MockDrawStrategy mdr;
1156+ StrictMock <MockBindable> mockBindable;
1157+ StrictMock <MockBindLocation> mockBindLocation;
1158+ cglfb::RectangularDraw rtdraw;
1159+ cglfb::RectangularDrawList strategyList;
1160+
1161+};
1162+
1163+TEST_F (FBDirectDrawStrategies, BufferBitsSet)
1164+{
1165+ CompRect srcAndDst (0, 0, 0, 0);
1166+
1167+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, GL_COLOR_BUFFER_BIT |
1168+ GL_STENCIL_BUFFER_BIT,
1169+ _)).WillOnce (Return (true));
1170+
1171+ directDraw->draw (srcAndDst,
1172+ srcAndDst,
1173+ static_cast <cglfb::BlitMask> (cglfb::ColorData |
1174+ cglfb::StencilData),
1175+ cglfb::Good);
1176+}
1177+
1178+TEST_F (FBDirectDrawStrategies, BufferNoBitsSet)
1179+{
1180+ CompRect srcAndDst (0, 0, 0, 0);
1181+
1182+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, 0,
1183+ _)).Times (0);
1184+
1185+ directDraw->draw (srcAndDst,
1186+ srcAndDst,
1187+ static_cast <cglfb::BlitMask> (0),
1188+ cglfb::Good);
1189+}
1190+
1191+TEST_F (FBDirectDrawStrategies, GoodToLinear)
1192+{
1193+ CompRect srcAndDst (0, 0, 0, 0);
1194+
1195+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
1196+ GL_LINEAR)).WillOnce (Return (true));
1197+
1198+ directDraw->draw (srcAndDst,
1199+ srcAndDst,
1200+ cglfb::ColorData,
1201+ cglfb::Good);
1202+}
1203+
1204+TEST_F (FBDirectDrawStrategies, FastToNearest)
1205+{
1206+ CompRect srcAndDst (0, 0, 0, 0);
1207+
1208+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
1209+ GL_NEAREST)).WillOnce (Return (true));
1210+
1211+ directDraw->draw (srcAndDst,
1212+ srcAndDst,
1213+ cglfb::ColorData,
1214+ cglfb::Fast);
1215+}
1216+
1217+TEST_F (FBDirectDrawStrategies, RevertToPaintWhenBlitUnavailable)
1218+{
1219+ CompRect srcAndDst (0, 0, 0, 0);
1220+
1221+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
1222+ _)).WillOnce (Return (false));
1223+ EXPECT_CALL (mdr, draw (srcAndDst, srcAndDst, _, _));
1224+
1225+ directDraw->draw (srcAndDst,
1226+ srcAndDst,
1227+ cglfb::ColorData,
1228+ cglfb::Fast);
1229+}
1230+
1231+TEST_F (FBDirectDrawStrategies, RevertOnBlitUnavailablePermanent)
1232+{
1233+ StrictMock <MockDrawStrategy> strictMdr;
1234+ CompRect srcAndDst (0, 0, 0, 0);
1235+
1236+ rtdraw = boost::bind (&MockDrawStrategy::draw, &strictMdr, _1, _2, _3, _4);
1237+
1238+ SetUpStrategyList (blitFramebuffer, rtdraw);
1239+ directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
1240+
1241+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _, _)).WillOnce (Return (false));
1242+ ON_CALL (strictMdr, draw (_, _, _, _)).WillByDefault (Return (true));
1243+ EXPECT_CALL (strictMdr, draw (srcAndDst, srcAndDst, _, _)).Times (2);
1244+
1245+ directDraw->draw (srcAndDst,
1246+ srcAndDst,
1247+ cglfb::ColorData,
1248+ cglfb::Fast);
1249+ directDraw->draw (srcAndDst,
1250+ srcAndDst,
1251+ cglfb::ColorData,
1252+ cglfb::Fast);
1253+}
1254+
1255+TEST_F (FBDirectDrawStrategies, BindReadFramebufferOnBlit)
1256+{
1257+ CompRect srcAndDst (0, 0, 0, 0);
1258+
1259+ SetUpStrategyList (blitFramebufferWithReadPushed, rtdraw);
1260+ directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
1261+
1262+ MockBindable backBuffer;
1263+
1264+ EXPECT_CALL (mockBindLocation, bind (&mockBindable)).WillOnce (Return (&backBuffer));
1265+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _, _)).WillOnce (Return (false));
1266+ ON_CALL (mdr, draw (_, _, _, _)).WillByDefault (Return (true));
1267+ EXPECT_CALL (mdr, draw (srcAndDst, srcAndDst, _, _)).Times (2);
1268+
1269+ directDraw->draw (srcAndDst,
1270+ srcAndDst,
1271+ cglfb::ColorData,
1272+ cglfb::Fast);
1273+ directDraw->draw (srcAndDst,
1274+ srcAndDst,
1275+ cglfb::ColorData,
1276+ cglfb::Fast);
1277+}
1278
1279=== modified file 'plugins/opengl/src/framebufferobject.cpp'
1280--- plugins/opengl/src/framebufferobject.cpp 2012-08-06 09:44:49 +0000
1281+++ plugins/opengl/src/framebufferobject.cpp 2013-02-28 02:29:22 +0000
1282@@ -22,88 +22,96 @@
1283 *
1284 * Authors: Pekka Paalanen <ppaalanen@gmail.com>
1285 */
1286-
1287+#include <memory>
1288 #include <map>
1289+#include <opengl/opengl.h>
1290 #include <opengl/framebufferobject.h>
1291 #include <opengl/texture.h>
1292
1293+#include "framebuffer-direct-draw.h"
1294+
1295+namespace cglfb = compiz::opengl;
1296+namespace cglfbi = compiz::opengl::impl;
1297+
1298+namespace compiz
1299+{
1300+namespace opengl
1301+{
1302+namespace impl
1303+{
1304 struct PrivateGLFramebufferObject
1305 {
1306 PrivateGLFramebufferObject () :
1307 fboId (0),
1308- pushedId (0),
1309 glTex (NULL),
1310 status (-1)
1311 {
1312 }
1313
1314- void pushFBO ();
1315- void popFBO ();
1316-
1317 GLuint fboId;
1318- GLuint pushedId;
1319 GLuint rbStencilId;
1320 GLTexture *glTex;
1321
1322 GLint status;
1323
1324- static GLuint boundId;
1325- static std::map<GLuint, GLFramebufferObject *> idMap;
1326+ std::auto_ptr <cglfb::DirectDrawStrategies> mDirectDraw;
1327+ GLVertexBuffer *vertexBuffer;
1328 };
1329
1330-GLuint PrivateGLFramebufferObject::boundId = 0;
1331-std::map<GLuint, GLFramebufferObject *> PrivateGLFramebufferObject::idMap;
1332-
1333-void
1334-PrivateGLFramebufferObject::pushFBO ()
1335-{
1336- pushedId = boundId;
1337- if (boundId != fboId)
1338- {
1339- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, fboId);
1340- boundId = fboId;
1341- }
1342-}
1343-
1344-void
1345-PrivateGLFramebufferObject::popFBO ()
1346-{
1347- if (boundId != pushedId)
1348- {
1349- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, pushedId);
1350- boundId = pushedId;
1351- }
1352-}
1353-
1354-GLFramebufferObject::GLFramebufferObject () :
1355- priv (new PrivateGLFramebufferObject)
1356+}
1357+}
1358+}
1359+
1360+GLuint
1361+cglfbi::FramebufferObject::getResourceId () const
1362+{
1363+ return priv->fboId;
1364+}
1365+
1366+bool
1367+cglfbi::FramebufferObject::setBindStatus (GLenum status)
1368+{
1369+ priv->status = status;
1370+ return checkStatus ();
1371+}
1372+
1373+void
1374+cglfbi::FramebufferObject::updateAllocation (GLenum bindingLocation)
1375+{
1376+ if (priv->status == -1)
1377+ {
1378+ (*GL::framebufferTexture2D) (bindingLocation, GL::COLOR_ATTACHMENT0,
1379+ priv->glTex->target (),
1380+ priv->glTex->name (), 0);
1381+ (*GL::framebufferRenderbuffer) (bindingLocation, GL::DEPTH_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1382+ (*GL::framebufferRenderbuffer) (bindingLocation, GL::STENCIL_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1383+ }
1384+
1385+}
1386+
1387+cglfbi::FramebufferObject::FramebufferObject () :
1388+ priv (new cglfbi::PrivateGLFramebufferObject ())
1389 {
1390 (*GL::genFramebuffers) (1, &priv->fboId);
1391 (*GL::genRenderbuffers) (1, &priv->rbStencilId);
1392-
1393- if (priv->fboId != 0)
1394- PrivateGLFramebufferObject::idMap[priv->fboId] = this;
1395 }
1396
1397-GLFramebufferObject::~GLFramebufferObject ()
1398+cglfbi::FramebufferObject::~FramebufferObject ()
1399 {
1400 if (priv->glTex)
1401 GLTexture::decRef (priv->glTex);
1402
1403- PrivateGLFramebufferObject::idMap.erase (priv->fboId);
1404 (*GL::deleteFramebuffers) (1, &priv->fboId);
1405 (*GL::deleteRenderbuffers) (1, &priv->rbStencilId);
1406
1407-
1408 delete priv;
1409 }
1410
1411 bool
1412-GLFramebufferObject::allocate (const CompSize &size, const char *image,
1413- GLenum format, GLenum type)
1414+cglfbi::FramebufferObject::allocate (const CompSize &size,
1415+ const char *image,
1416+ GLenum format, GLenum type)
1417 {
1418- priv->status = -1;
1419-
1420 if (!priv->glTex ||
1421 size.width () != priv->glTex->width () ||
1422 size.height () != priv->glTex->height ())
1423@@ -125,86 +133,39 @@
1424 (*GL::bindRenderbuffer) (GL::RENDERBUFFER, priv->rbStencilId);
1425 (*GL::renderbufferStorage) (GL::RENDERBUFFER, GL::DEPTH24_STENCIL8, size.width (), size.height ());
1426 }
1427+
1428+ priv->status = -1;
1429 }
1430
1431- priv->pushFBO ();
1432-
1433- (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,
1434- priv->glTex->target (),
1435- priv->glTex->name (), 0);
1436-
1437- priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);
1438-
1439- priv->popFBO ();
1440 return true;
1441 }
1442
1443-GLFramebufferObject *
1444-GLFramebufferObject::bind ()
1445-{
1446- GLFramebufferObject *old = NULL;
1447-
1448- if (priv->boundId != 0)
1449- {
1450- std::map<GLuint, GLFramebufferObject *>::iterator it;
1451- it = PrivateGLFramebufferObject::idMap.find (priv->boundId);
1452-
1453- if (it != PrivateGLFramebufferObject::idMap.end ())
1454- old = it->second;
1455- else
1456- compLogMessage ("opengl", CompLogLevelError,
1457- "An FBO without GLFramebufferObject cannot be restored");
1458- }
1459-
1460- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, priv->fboId);
1461- priv->boundId = priv->fboId;
1462-
1463- (*GL::framebufferRenderbuffer) (GL::FRAMEBUFFER, GL::DEPTH_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1464- (*GL::framebufferRenderbuffer) (GL::FRAMEBUFFER, GL::STENCIL_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1465-
1466- return old;
1467-}
1468-
1469-// static
1470-void
1471-GLFramebufferObject::rebind (GLFramebufferObject *fbo)
1472-{
1473- GLuint id = fbo ? fbo->priv->fboId : 0;
1474-
1475- if (id != fbo->priv->boundId)
1476- {
1477- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, id);
1478- fbo->priv->boundId = id;
1479- }
1480-}
1481-
1482-static const char *
1483+namespace
1484+{
1485+const char *
1486 getFboErrorString (GLint status)
1487 {
1488 switch (status)
1489 {
1490- case GL::FRAMEBUFFER_COMPLETE:
1491+ case GL::FRAMEBUFFER_COMPLETE:
1492 return "GL::FRAMEBUFFER_COMPLETE";
1493- case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1494+ case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1495 return "GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
1496- case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1497+ case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1498 return "GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
1499- case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1500+ case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1501 return "GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
1502- case GL::FRAMEBUFFER_UNSUPPORTED:
1503+ case GL::FRAMEBUFFER_UNSUPPORTED:
1504 return "GL::FRAMEBUFFER_UNSUPPORTED";
1505 default:
1506 return "unexpected status";
1507 }
1508 }
1509+}
1510
1511 bool
1512-GLFramebufferObject::checkStatus ()
1513+cglfbi::FramebufferObject::checkStatus ()
1514 {
1515- priv->pushFBO ();
1516- priv-> status = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER);
1517- priv->popFBO ();
1518-
1519 if (priv->status == static_cast <GLint> (GL::FRAMEBUFFER_COMPLETE))
1520 return true;
1521
1522@@ -215,7 +176,54 @@
1523 }
1524
1525 GLTexture *
1526-GLFramebufferObject::tex ()
1527+cglfbi::FramebufferObject::tex ()
1528 {
1529 return priv->glTex;
1530 }
1531+
1532+class cglfbi::FBOBindLocation::Private
1533+{
1534+ public:
1535+
1536+ Private (GLenum binding,
1537+ cglfb::BindableFramebuffer *back) :
1538+ mCurrentlyBound (back),
1539+ mBindPoint (binding)
1540+ {
1541+ }
1542+
1543+ cglfb::BindableFramebuffer *mCurrentlyBound;
1544+ GLenum mBindPoint;
1545+};
1546+
1547+cglfbi::FBOBindLocation::FBOBindLocation (GLenum binding,
1548+ cglfb::BindableFramebuffer *back) :
1549+ priv (new cglfbi::FBOBindLocation::Private (binding, back))
1550+{
1551+}
1552+
1553+cglfb::BindableFramebuffer *
1554+cglfbi::FBOBindLocation::bind (cglfb::BindableFramebuffer *next)
1555+{
1556+ if (priv->mCurrentlyBound == next)
1557+ return next;
1558+
1559+ (*GL::bindFramebuffer) (priv->mBindPoint, next->getResourceId ());
1560+ next->updateAllocation (priv->mBindPoint);
1561+ if (!next->setBindStatus ((*GL::checkFramebufferStatus) (priv->mBindPoint)))
1562+ {
1563+ (*GL::bindFramebuffer) (priv->mBindPoint, priv->mCurrentlyBound->getResourceId ());
1564+ return NULL;
1565+ }
1566+
1567+ cglfb::BindableFramebuffer *last = priv->mCurrentlyBound;
1568+ priv->mCurrentlyBound = next;
1569+ return last;
1570+}
1571+
1572+cglfb::BindableFramebuffer *
1573+cglfbi::FBOBindLocation::getCurrentlyBound ()
1574+{
1575+ return priv->mCurrentlyBound;
1576+}
1577+
1578
1579=== modified file 'plugins/opengl/src/paint.cpp'
1580--- plugins/opengl/src/paint.cpp 2013-01-03 16:05:26 +0000
1581+++ plugins/opengl/src/paint.cpp 2013-02-28 02:29:22 +0000
1582@@ -44,6 +44,7 @@
1583 #define DEG2RAD (M_PI / 180.0f)
1584
1585 using namespace compiz::opengl;
1586+namespace cglfb = compiz::opengl;
1587
1588 GLScreenPaintAttrib defaultScreenPaintAttrib = {
1589 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA
1590@@ -432,6 +433,8 @@
1591 continue;
1592 }
1593
1594+ gw = GLWindow::get (w);
1595+
1596 const CompRegion &clip =
1597 (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ?
1598 gw->clip () : region;
1599@@ -672,89 +675,16 @@
1600 }
1601
1602 void
1603-GLScreen::glPaintCompositedOutput (const CompRegion &region,
1604- GLFramebufferObject *fbo,
1605- unsigned int mask)
1606+GLScreen::glPaintCompositedOutput (const CompRegion &region,
1607+ compiz::opengl::DirectDrawObject *fbo,
1608+ unsigned int mask)
1609 {
1610 WRAPABLE_HND_FUNCTN (glPaintCompositedOutput, region, fbo, mask)
1611
1612- GLMatrix sTransform;
1613- const GLTexture::Matrix & texmatrix = fbo->tex ()->matrix ();
1614- GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
1615-
1616- streamingBuffer->begin (GL_TRIANGLES);
1617-
1618- if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
1619- {
1620- GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, 0.0f);
1621- GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, screen->width ());
1622- GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, 0.0f);
1623- GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, screen->height ());
1624-
1625- const GLfloat vertexData[] = {
1626- 0.0f, 0.0f, 0.0f,
1627- 0.0f, (float)screen->height (), 0.0f,
1628- (float)screen->width (), 0.0f, 0.0f,
1629-
1630- 0.0f, (float)screen->height (), 0.0f,
1631- (float)screen->width (), (float)screen->height (), 0.0f,
1632- (float)screen->width (), 0.0f, 0.0f,
1633- };
1634-
1635- const GLfloat textureData[] = {
1636- tx1, ty1,
1637- tx1, ty2,
1638- tx2, ty1,
1639- tx1, ty2,
1640- tx2, ty2,
1641- tx2, ty1,
1642- };
1643-
1644- streamingBuffer->addVertices (6, &vertexData[0]);
1645- streamingBuffer->addTexCoords (0, 6, &textureData[0]);
1646- }
1647- else
1648- {
1649- BoxPtr pBox = const_cast <Region> (region.handle ())->rects;
1650- int nBox = const_cast <Region> (region.handle ())->numRects;
1651-
1652- while (nBox--)
1653- {
1654- GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, pBox->x1);
1655- GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, pBox->x2);
1656- GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y1);
1657- GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y2);
1658-
1659- const GLfloat vertexData[] = {
1660- (float)pBox->x1, (float)pBox->y1, 0.0f,
1661- (float)pBox->x1, (float)pBox->y2, 0.0f,
1662- (float)pBox->x2, (float)pBox->y1, 0.0f,
1663-
1664- (float)pBox->x1, (float)pBox->y2, 0.0f,
1665- (float)pBox->x2, (float)pBox->y2, 0.0f,
1666- (float)pBox->x2, (float)pBox->y1, 0.0f,
1667- };
1668-
1669- const GLfloat textureData[] = {
1670- tx1, ty1,
1671- tx1, ty2,
1672- tx2, ty1,
1673- tx1, ty2,
1674- tx2, ty2,
1675- tx2, ty1,
1676- };
1677-
1678- streamingBuffer->addVertices (6, &vertexData[0]);
1679- streamingBuffer->addTexCoords (0, 6, &textureData[0]);
1680- pBox++;
1681- }
1682- }
1683-
1684- streamingBuffer->end ();
1685- fbo->tex ()->enable (GLTexture::Fast);
1686- sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
1687- streamingBuffer->render (sTransform);
1688- fbo->tex ()->disable ();
1689+ /* Draw every rect individually, this could be a little slow
1690+ * for lots of rects, but the general usecase isn't that */
1691+ foreach (const CompRect &r, region.rects ())
1692+ fbo->directDraw (r, r, cglfb::ColorData, cglfb::Fast);
1693 }
1694
1695 static void
1696
1697=== modified file 'plugins/opengl/src/privates.h'
1698--- plugins/opengl/src/privates.h 2013-01-03 16:05:26 +0000
1699+++ plugins/opengl/src/privates.h 2013-02-28 02:29:22 +0000
1700@@ -29,22 +29,28 @@
1701 #define _OPENGL_PRIVATES_H
1702
1703 #include <memory>
1704-
1705 #include <composite/composite.h>
1706 #include <opengl/opengl.h>
1707 #include <core/atoms.h>
1708 #include <core/configurerequestbuffer.h>
1709-
1710-#ifdef USE_GLES
1711 #include <opengl/framebufferobject.h>
1712-#endif
1713-
1714 #include <opengl/doublebuffer.h>
1715
1716 #include "privatetexture.h"
1717 #include "privatevertexbuffer.h"
1718 #include "opengl_options.h"
1719
1720+namespace compiz
1721+{
1722+ namespace opengl
1723+ {
1724+ namespace impl
1725+ {
1726+ class DirectDrawObject;
1727+ }
1728+ }
1729+}
1730+
1731 extern CompOutput *targetOutput;
1732
1733 class GLDoubleBuffer :
1734@@ -86,6 +92,17 @@
1735 Window mOutput;
1736 };
1737
1738+namespace compiz
1739+{
1740+ namespace opengl
1741+ {
1742+ bool blitFramebufferGLX (const CompRect &src,
1743+ const CompRect &dst,
1744+ GLbitfield mask,
1745+ GLenum filter);
1746+ }
1747+}
1748+
1749 #else
1750
1751 class EGLDoubleBuffer :
1752@@ -109,6 +126,17 @@
1753 EGLSurface const & mSurface;
1754 };
1755
1756+namespace compiz
1757+{
1758+ namespace opengl
1759+ {
1760+ bool blitFramebufferEGL (const CompRect &src,
1761+ const CompRect &dst,
1762+ GLbitfield mask,
1763+ GLenum filter);
1764+ }
1765+}
1766+
1767 #endif
1768
1769 class GLIcon
1770@@ -120,6 +148,16 @@
1771 GLTexture::List textures;
1772 };
1773
1774+class BindableBackbuffer :
1775+ public compiz::opengl::BindableFramebuffer
1776+{
1777+ public:
1778+
1779+ GLuint getResourceId () const;
1780+ bool setBindStatus (GLenum);
1781+ void updateAllocation (GLenum);
1782+};
1783+
1784 class PrivateGLScreen :
1785 public ScreenInterface,
1786 public compiz::composite::PaintHandler,
1787@@ -197,8 +235,9 @@
1788 GLXDoubleBuffer doubleBuffer;
1789 #endif
1790
1791- GLFramebufferObject *scratchFbo;
1792- CompRegion outputRegion;
1793+ std::auto_ptr <compiz::opengl::DirectDrawObject> scratchFbo;
1794+ compiz::opengl::BlitFramebufferFunc blitFramebuffer;
1795+ CompRegion outputRegion;
1796
1797 XRectangle lastViewport;
1798 bool refreshSubBuffer;
1799@@ -222,6 +261,9 @@
1800 Pixmap rootPixmapCopy;
1801 CompSize rootPixmapSize;
1802
1803+ BindableBackbuffer backbuffer;
1804+ compiz::opengl::impl::FBOBindLocation drawFramebufferBinding;
1805+ compiz::opengl::impl::FBOBindLocation readFramebufferBinding;
1806 const char *glVendor, *glRenderer, *glVersion;
1807
1808 mutable CompString prevRegex;
1809
1810=== modified file 'plugins/opengl/src/screen.cpp'
1811--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
1812+++ plugins/opengl/src/screen.cpp 2013-02-28 02:29:22 +0000
1813@@ -36,6 +36,7 @@
1814 #include <boost/make_shared.hpp>
1815
1816 #include "privates.h"
1817+#include "framebuffer-direct-draw.h"
1818 #include "blacklist/blacklist.h"
1819
1820 #include <dlfcn.h>
1821@@ -67,6 +68,26 @@
1822
1823
1824 using namespace compiz::opengl;
1825+namespace cglfb = compiz::opengl;
1826+namespace cgli = compiz::opengl::impl;
1827+
1828+namespace compiz
1829+{
1830+ namespace opengl
1831+ {
1832+#ifndef USE_GLES
1833+ bool blitFramebufferGLX (const CompRect &src,
1834+ const CompRect &dst,
1835+ GLbitfield mask,
1836+ GLenum filter);
1837+#else
1838+ bool blitFramebufferEGL (const CompRect &src,
1839+ const CompRect &dst,
1840+ GLbitfield mask,
1841+ GLenum filter);
1842+#endif
1843+ }
1844+}
1845
1846 namespace GL {
1847 #ifdef USE_GLES
1848@@ -164,11 +185,12 @@
1849 GLDisableVertexAttribArrayProc disableVertexAttribArray = NULL;
1850 GLVertexAttribPointerProc vertexAttribPointer = NULL;
1851
1852- GLGenRenderbuffersProc genRenderbuffers = NULL;
1853- GLDeleteRenderbuffersProc deleteRenderbuffers = NULL;
1854+ GLGenRenderbuffersProc genRenderbuffers = NULL;
1855+ GLDeleteRenderbuffersProc deleteRenderbuffers = NULL;
1856 GLFramebufferRenderbufferProc framebufferRenderbuffer = NULL;
1857- GLBindRenderbufferProc bindRenderbuffer = NULL;
1858- GLRenderbufferStorageProc renderbufferStorage = NULL;
1859+ GLBindRenderbufferProc bindRenderbuffer = NULL;
1860+ GLRenderbufferStorageProc renderbufferStorage = NULL;
1861+ GLBlitFramebufferProc blitFramebuffer = NULL;
1862
1863 bool textureFromPixmap = true;
1864 bool textureRectangle = false;
1865@@ -299,6 +321,115 @@
1866 GLScreen *gScreen;
1867 };
1868
1869+namespace
1870+{
1871+bool defaultRectangularFramebufferDraw (GLVertexBuffer *vertexBuffer,
1872+ GLFramebufferObject *fbo,
1873+ const CompRect &src,
1874+ const CompRect &dst,
1875+ GLbitfield mask,
1876+ GLenum filter)
1877+{
1878+ GLTexture *texture = fbo->tex ();
1879+ GLMatrix sTransform;
1880+ const GLTexture::Matrix & texmatrix = texture->matrix ();
1881+ const GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, src.x1 ());
1882+ const GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, src.x2 ());
1883+ const GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, src.y1 ());
1884+ const GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, src.y2 ());
1885+
1886+ const GLfloat vx1 = src.x1 ();
1887+ const GLfloat vx2 = src.x2 ();
1888+ const GLfloat vy1 = src.y1 ();
1889+ const GLfloat vy2 = src.y2 ();
1890+
1891+ const GLTexture::Filter texFilter =
1892+ (filter == GL_LINEAR) ? GLTexture::Good :
1893+ GLTexture::Fast;
1894+
1895+ GLfloat vertexData[] = {
1896+ vx1, vy1, 0.0f,
1897+ vx1, vy2, 0.0f,
1898+ vx2, vy1, 0.0f,
1899+
1900+ vx1, vy2, 0.0f,
1901+ vx2, vy2, 0.0f,
1902+ vx2, vy1, 0.0f,
1903+ };
1904+
1905+ GLfloat textureData[] = {
1906+ tx1, ty1,
1907+ tx1, ty2,
1908+ tx2, ty1,
1909+ tx1, ty2,
1910+ tx2, ty2,
1911+ tx2, ty1,
1912+ };
1913+
1914+ vertexBuffer->begin (GL_TRIANGLES);
1915+ vertexBuffer->addVertices (6, vertexData);
1916+ vertexBuffer->addTexCoords (0, 6, textureData);
1917+
1918+ if (vertexBuffer->end ())
1919+ {
1920+ texture->enable (texFilter);
1921+ sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
1922+ vertexBuffer->render (sTransform);
1923+ texture->disable ();
1924+ }
1925+
1926+ return true;
1927+}
1928+
1929+void initDirectDraw (cgli::DirectDrawStrategies::Ptr &directDraw,
1930+ const compiz::opengl::RectangularDraw &blitFramebuffer,
1931+ const compiz::opengl::RectangularDraw &rectangularTextureDraw,
1932+ const cgli::BindReadBufferFunc &func,
1933+ compiz::opengl::BindableFramebuffer *bindable)
1934+{
1935+ cglfb::RectangularDraw blitFramebufferBound (
1936+ boost::bind (
1937+ cgli::rectangleDrawFromReadBuffer,
1938+ _1, _2, _3, _4,
1939+ bindable,
1940+ func,
1941+ blitFramebuffer));
1942+
1943+ /* Tries each of these from back to front */
1944+ cglfb::RectangularDrawList strategies;
1945+
1946+ strategies.push_back (rectangularTextureDraw);
1947+ strategies.push_back (blitFramebufferBound);
1948+ directDraw.reset (new cgli::DirectDrawStrategies (strategies));
1949+}
1950+}
1951+
1952+namespace compiz
1953+{
1954+namespace opengl
1955+{
1956+DirectDrawObject *
1957+createBlittableFramebufferObjectWithFallback (const CompSize &sz,
1958+ GLScreen *gScreen)
1959+{
1960+ boost::shared_ptr <cgli::DirectDrawStrategies> directDraw;
1961+ boost::shared_ptr <cgli::FramebufferObject> fbo (boost::make_shared <cgli::FramebufferObject> ());
1962+ cglfb::RectangularDraw rectangularTextureDraw (boost::bind (defaultRectangularFramebufferDraw,
1963+ GLVertexBuffer::streamingBuffer (),
1964+ fbo.get (),
1965+ _1, _2, _3, _4));
1966+ initDirectDraw (directDraw,
1967+ gScreen->blitFramebufferFunc (),
1968+ rectangularTextureDraw,
1969+ boost::bind (&GLScreen::bindFramebufferForReading, gScreen, _1),
1970+ fbo.get ());
1971+ DirectDrawObject *dd (new cgli::DirectDrawObject (directDraw, fbo, fbo));
1972+ dd->allocate (*screen, NULL, GL_BGRA);
1973+ return dd;
1974+}
1975+}
1976+}
1977+
1978 #ifndef USE_GLES
1979
1980 namespace compiz
1981@@ -591,6 +722,7 @@
1982 if (GL::textureFromPixmap)
1983 registerBindPixmap (EglTexture::bindPixmapToTexture);
1984
1985+ priv->blitFramebuffer = boost::bind (compiz::opengl::blitFramebufferEGL, _1, _2, _3, _4);
1986 priv->incorrectRefreshRate = false;
1987
1988 #else
1989@@ -779,6 +911,10 @@
1990 GL::fboSupported = true;
1991 }
1992
1993+ if (GL::fboSupported &&
1994+ strstr (glExtensions, "GL_EXT_framebuffer_blit"))
1995+ GL::blitFramebuffer = (GL::GLBlitFramebufferProc) getProcAddress ("glBlitFramebufferEXT");
1996+
1997 GL::fboStencilSupported = GL::fboSupported &&
1998 strstr (glExtensions, "GL_EXT_packed_depth_stencil");
1999
2000@@ -895,13 +1031,13 @@
2001
2002 if (GL::textureFromPixmap)
2003 registerBindPixmap (TfpTexture::bindPixmapToTexture);
2004+
2005+ priv->blitFramebuffer = boost::bind (compiz::opengl::blitFramebufferGLX, _1, _2, _3, _4);
2006 #endif
2007
2008 if (GL::fboSupported)
2009- {
2010- priv->scratchFbo = new GLFramebufferObject;
2011- priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
2012- }
2013+ priv->scratchFbo.reset (compiz::opengl::createBlittableFramebufferObjectWithFallback (*screen,
2014+ this));
2015
2016 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
2017
2018@@ -1209,9 +1345,6 @@
2019 glXDestroyContext (screen->dpy (), priv->ctx);
2020 #endif
2021
2022- if (priv->scratchFbo)
2023- delete priv->scratchFbo;
2024-
2025 delete priv;
2026 }
2027
2028@@ -1234,6 +1367,7 @@
2029 doubleBuffer (screen->dpy (), *screen, surface),
2030 #endif
2031 scratchFbo (NULL),
2032+ blitFramebuffer (),
2033 outputRegion (),
2034 refreshSubBuffer (false),
2035 lastMask (0),
2036@@ -1246,6 +1380,10 @@
2037 autoProgram (new GLScreenAutoProgram(gs)),
2038 rootPixmapCopy (None),
2039 rootPixmapSize (),
2040+ drawFramebufferBinding (GL::DRAW_FRAMEBUFFER,
2041+ &backbuffer),
2042+ readFramebufferBinding (GL::READ_FRAMEBUFFER,
2043+ &backbuffer),
2044 glVendor (NULL),
2045 glRenderer (NULL),
2046 glVersion (NULL),
2047@@ -1441,11 +1579,19 @@
2048 void
2049 PrivateGLScreen::outputChangeNotify ()
2050 {
2051+ compiz::opengl::BindableFramebuffer *previousReadBuffer =
2052+ readFramebufferBinding.bind (&backbuffer);
2053+ compiz::opengl::BindableFramebuffer *previousDrawBuffer =
2054+ drawFramebufferBinding.bind (&backbuffer);
2055+
2056 screen->outputChangeNotify ();
2057
2058- if (scratchFbo)
2059+ if (scratchFbo.get ())
2060 scratchFbo->allocate (*screen, NULL, GL_BGRA);
2061 updateView ();
2062+
2063+ readFramebufferBinding.bind (previousReadBuffer);
2064+ drawFramebufferBinding.bind (previousDrawBuffer);
2065 }
2066
2067 #ifndef USE_GLES
2068@@ -1670,9 +1816,9 @@
2069 WRAPABLE_DEF (projectionMatrix)
2070
2071 void
2072-GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
2073- GLFramebufferObject *fbo,
2074- unsigned int mask)
2075+GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
2076+ compiz::opengl::DirectDrawObject *fbo,
2077+ unsigned int mask)
2078 WRAPABLE_DEF (glPaintCompositedOutput, region, fbo, mask)
2079
2080 void
2081@@ -1899,6 +2045,30 @@
2082
2083 }
2084
2085+bool
2086+cglfb::blitFramebufferGLX (const CompRect &src,
2087+ const CompRect &dst,
2088+ GLbitfield mask,
2089+ GLenum filter)
2090+{
2091+ /* Must have GL_EXT_blit_framebuffer */
2092+ if (!GL::blitFramebuffer)
2093+ return false;
2094+
2095+ /* Be sure to invert y-coords too */
2096+ (*GL::blitFramebuffer) (src.x1 (), // sx0
2097+ screen->height () - src.y2 (), // sy0
2098+ src.x2 (), // sx1
2099+ screen->height () - src.y1 (), // sy1
2100+ dst.x1 (), // dx0
2101+ screen->height () - dst.y2 (), // dy0
2102+ dst.x2 (), // dx1,
2103+ screen->height () - dst.y1 (), // dy1
2104+ GL_COLOR_BUFFER_BIT,
2105+ GL_LINEAR);
2106+ return true;
2107+}
2108+
2109 #else
2110
2111 EGLDoubleBuffer::EGLDoubleBuffer (Display *d,
2112@@ -1957,6 +2127,16 @@
2113 {
2114 }
2115
2116+bool
2117+cglfb::blitFramebufferEGL (const CompRect &src,
2118+ const CompRect &dst,
2119+ GLbitfield mask,
2120+ GLenum filter)
2121+{
2122+ /* Not supported on OpenGL|ES2 */
2123+ return false;
2124+}
2125+
2126 #endif
2127
2128 void
2129@@ -1977,17 +2157,11 @@
2130 glDepthMask (GL_FALSE);
2131 glStencilMask (0);
2132
2133- GLFramebufferObject *oldFbo = NULL;
2134- bool useFbo = false;
2135+ compiz::opengl::BindableFramebuffer *oldFbo = NULL;
2136
2137 /* Clear the color buffer where appropriate */
2138- if (GL::fboEnabled && scratchFbo)
2139- {
2140- oldFbo = scratchFbo->bind ();
2141- useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
2142- if (!useFbo)
2143- GLFramebufferObject::rebind (oldFbo);
2144- }
2145+ if (GL::fboEnabled && scratchFbo.get ())
2146+ oldFbo = drawFramebufferBinding.bind (scratchFbo.get ());
2147
2148 #ifdef UNSAFE_ARM_SGX_FIXME
2149 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2150@@ -2080,13 +2254,10 @@
2151
2152 glViewport (0, 0, screen->width (), screen->height ());
2153
2154- if (useFbo)
2155+ if (oldFbo)
2156 {
2157- GLFramebufferObject::rebind (oldFbo);
2158-
2159- // FIXME: does not work if screen dimensions exceed max texture size
2160- // We should try to use glBlitFramebuffer instead.
2161- gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);
2162+ drawFramebufferBinding.bind (oldFbo);
2163+ gScreen->glPaintCompositedOutput (screen->region (), scratchFbo.get (), mask);
2164 }
2165
2166 if (cScreen->outputWindowChanged ())
2167@@ -2101,13 +2272,13 @@
2168 }
2169
2170 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2171- bool fullscreen = useFbo ||
2172+ bool fullscreen = oldFbo ||
2173 alwaysSwap ||
2174 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2175 commonFrontbuffer);
2176
2177 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2178- doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
2179+ doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, oldFbo ? true : false);
2180 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2181 doubleBuffer.render (tmpRegion, fullscreen);
2182
2183@@ -2195,10 +2366,40 @@
2184 }
2185 }
2186
2187-GLFramebufferObject *
2188+compiz::opengl::FramebufferObject *
2189 GLScreen::fbo ()
2190 {
2191- return priv->scratchFbo;
2192+ return priv->scratchFbo.get ();
2193+}
2194+
2195+compiz::opengl::BindableFramebuffer *
2196+GLScreen::backbuffer ()
2197+{
2198+ return &priv->backbuffer;
2199+}
2200+
2201+compiz::opengl::BindableFramebuffer *
2202+GLScreen::drawFramebuffer ()
2203+{
2204+ return priv->drawFramebufferBinding.getCurrentlyBound ();
2205+}
2206+
2207+compiz::opengl::BindableFramebuffer *
2208+GLScreen::bindFramebufferForDrawing (compiz::opengl::BindableFramebuffer *next)
2209+{
2210+ return priv->drawFramebufferBinding.bind (next);
2211+}
2212+
2213+compiz::opengl::BindableFramebuffer *
2214+GLScreen::bindFramebufferForReading (compiz::opengl::BindableFramebuffer *next)
2215+{
2216+ return priv->readFramebufferBinding.bind (next);
2217+}
2218+
2219+const cglfb::BlitFramebufferFunc &
2220+GLScreen::blitFramebufferFunc ()
2221+{
2222+ return priv->blitFramebuffer;
2223 }
2224
2225 GLTexture *
2226@@ -2240,3 +2441,19 @@
2227 priv->rasterPos.setY (0);
2228 }
2229
2230+GLuint
2231+BindableBackbuffer::getResourceId () const
2232+{
2233+ return 0;
2234+}
2235+
2236+bool
2237+BindableBackbuffer::setBindStatus (GLenum)
2238+{
2239+ return true;
2240+}
2241+
2242+void
2243+BindableBackbuffer::updateAllocation (GLenum)
2244+{
2245+}
2246
2247=== modified file 'plugins/water/src/water.cpp'
2248--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
2249+++ plugins/water/src/water.cpp 2013-02-28 02:29:22 +0000
2250@@ -62,7 +62,11 @@
2251 if (!useFbo)
2252 return false;
2253
2254- oldFbo = waterFbo[fIndex]->bind ();
2255+ oldFbo = gScreen->bindFramebufferForDrawing (waterFbo[fIndex]);
2256+
2257+ if (!oldFbo)
2258+ return false;
2259+
2260 glGetIntegerv(GL_VIEWPORT, &oldViewport[0]);
2261 glViewport (0, 0, texWidth, texHeight);
2262
2263@@ -72,7 +76,7 @@
2264 void
2265 WaterScreen::fboEpilogue ()
2266 {
2267- GLFramebufferObject::rebind (oldFbo);
2268+ gScreen->bindFramebufferForDrawing (oldFbo);
2269 glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
2270 }
2271
2272@@ -305,28 +309,32 @@
2273 waterFbo[i]->allocate (size, (char *) t0,
2274 GL_BGRA, GL_UNSIGNED_BYTE);
2275 // check if FBOs are working. If not, fallback to software textures
2276- oldFbo = waterFbo[i]->bind ();
2277- waterFbo[i]->rebind (oldFbo);
2278- if (!waterFbo[i]->checkStatus ())
2279+ oldFbo = gScreen->bindFramebufferForDrawing (waterFbo[i]);
2280+ if (!oldFbo)
2281 {
2282 useFbo = false;
2283 delete waterFbo[i];
2284 break;
2285 }
2286+ gScreen->bindFramebufferForDrawing (oldFbo);
2287 }
2288 }
2289 }
2290
2291 void
2292-WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2293- GLFramebufferObject *fbo,
2294- unsigned int mask)
2295+WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2296+ compiz::opengl::DirectDrawObject *fbo,
2297+ unsigned int mask)
2298 {
2299 if (count)
2300 {
2301 if (GL::vboEnabled && GL::shaders)
2302 {
2303- GLFramebufferObject::rebind (oldFbo);
2304+ /* This seems redundant to me */
2305+ gScreen->bindFramebufferForDrawing (oldFbo);
2306+
2307+ oldFbo = NULL;
2308+
2309 glViewport (oldViewport[0], oldViewport[1],
2310 oldViewport[2], oldViewport[3]);
2311
2312
2313=== modified file 'plugins/water/src/water.h'
2314--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
2315+++ plugins/water/src/water.h 2013-02-28 02:29:22 +0000
2316@@ -64,9 +64,9 @@
2317
2318 void handleEvent (XEvent *);
2319
2320- void glPaintCompositedOutput (const CompRegion &region,
2321- GLFramebufferObject *fbo,
2322- unsigned int mask);
2323+ void glPaintCompositedOutput (const CompRegion &region,
2324+ compiz::opengl::DirectDrawObject *fbo,
2325+ unsigned int mask);
2326 void preparePaint (int);
2327 void donePaint ();
2328
2329@@ -100,7 +100,7 @@
2330
2331 GLFramebufferObject *waterFbo[TEXTURE_NUM];
2332
2333- GLFramebufferObject *oldFbo;
2334+ compiz::opengl::BindableFramebuffer *oldFbo;
2335 GLint oldViewport[4];
2336 int fboIndex;
2337 bool useFbo;
2338
2339=== added file 'src/asyncserverwindow.h'
2340--- src/asyncserverwindow.h 1970-01-01 00:00:00 +0000
2341+++ src/asyncserverwindow.h 2013-02-28 02:29:22 +0000
2342@@ -0,0 +1,52 @@
2343+/*
2344+ * Copyright © 2012 Sam Spilsbury
2345+ *
2346+ * Permission to use, copy, modify, distribute, and sell this software
2347+ * and its documentation for any purpose is hereby granted without
2348+ * fee, provided that the above copyright notice appear in all copies
2349+ * and that both that copyright notice and this permission notice
2350+ * appear in supporting documentation, and that the name of
2351+ * Canonical Ltd. not be used in advertising or publicity pertaining to
2352+ * distribution of the software without specific, written prior permission.
2353+ * Canonical Ltd. makes no representations about the suitability of this
2354+ * software for any purpose. It is provided "as is" without express or
2355+ * implied warranty.
2356+ *
2357+ * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2358+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2359+ * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2360+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2361+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2362+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2363+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2364+ *
2365+ * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2366+ */
2367+#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H
2368+#define _COMPIZ_ASYNC_SERVER_WINDOW_H
2369+
2370+#include <X11/Xlib.h>
2371+
2372+namespace compiz
2373+{
2374+namespace window
2375+{
2376+class AsyncServerWindow
2377+{
2378+ public:
2379+
2380+ virtual ~AsyncServerWindow () {};
2381+
2382+ virtual int requestConfigureOnClient (const XWindowChanges &xwc,
2383+ unsigned int valueMask) = 0;
2384+ virtual int requestConfigureOnWrapper (const XWindowChanges &xwc,
2385+ unsigned int valueMask) = 0;
2386+ virtual int requestConfigureOnFrame (const XWindowChanges &xwc,
2387+ unsigned int valueMask) = 0;
2388+ virtual void sendSyntheticConfigureNotify () = 0;
2389+ virtual bool hasCustomShape () const = 0;
2390+};
2391+}
2392+}
2393+
2394+#endif
2395
2396=== removed file 'src/asyncserverwindow.h'
2397--- src/asyncserverwindow.h 2012-12-13 11:12:32 +0000
2398+++ src/asyncserverwindow.h 1970-01-01 00:00:00 +0000
2399@@ -1,52 +0,0 @@
2400-/*
2401- * Copyright © 2012 Sam Spilsbury
2402- *
2403- * Permission to use, copy, modify, distribute, and sell this software
2404- * and its documentation for any purpose is hereby granted without
2405- * fee, provided that the above copyright notice appear in all copies
2406- * and that both that copyright notice and this permission notice
2407- * appear in supporting documentation, and that the name of
2408- * Canonical Ltd. not be used in advertising or publicity pertaining to
2409- * distribution of the software without specific, written prior permission.
2410- * Canonical Ltd. makes no representations about the suitability of this
2411- * software for any purpose. It is provided "as is" without express or
2412- * implied warranty.
2413- *
2414- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2415- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2416- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2417- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2418- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2419- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2420- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2421- *
2422- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2423- */
2424-#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H
2425-#define _COMPIZ_ASYNC_SERVER_WINDOW_H
2426-
2427-#include <X11/Xlib.h>
2428-
2429-namespace compiz
2430-{
2431-namespace window
2432-{
2433-class AsyncServerWindow
2434-{
2435- public:
2436-
2437- virtual ~AsyncServerWindow () {};
2438-
2439- virtual int requestConfigureOnClient (const XWindowChanges &xwc,
2440- unsigned int valueMask) = 0;
2441- virtual int requestConfigureOnWrapper (const XWindowChanges &xwc,
2442- unsigned int valueMask) = 0;
2443- virtual int requestConfigureOnFrame (const XWindowChanges &xwc,
2444- unsigned int valueMask) = 0;
2445- virtual void sendSyntheticConfigureNotify () = 0;
2446- virtual bool hasCustomShape () const = 0;
2447-};
2448-}
2449-}
2450-
2451-#endif
2452
2453=== added file 'src/configurerequestbuffer-impl.h'
2454--- src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000
2455+++ src/configurerequestbuffer-impl.h 2013-02-28 02:29:22 +0000
2456@@ -0,0 +1,145 @@
2457+/*
2458+ * Copyright © 2012 Sam Spilsbury
2459+ *
2460+ * Permission to use, copy, modify, distribute, and sell this software
2461+ * and its documentation for any purpose is hereby granted without
2462+ * fee, provided that the above copyright notice appear in all copies
2463+ * and that both that copyright notice and this permission notice
2464+ * appear in supporting documentation, and that the name of
2465+ * Canonical Ltd. not be used in advertising or publicity pertaining to
2466+ * distribution of the software without specific, written prior permission.
2467+ * Canonical Ltd. makes no representations about the suitability of this
2468+ * software for any purpose. It is provided "as is" without express or
2469+ * implied warranty.
2470+ *
2471+ * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2472+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2473+ * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2474+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2475+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2476+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2477+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2478+ *
2479+ * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2480+ */
2481+#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
2482+#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
2483+
2484+#include <memory>
2485+#include <vector>
2486+#include <boost/weak_ptr.hpp>
2487+#include <boost/shared_ptr.hpp>
2488+#include <boost/function.hpp>
2489+#include <X11/Xlib.h>
2490+
2491+#include <core/configurerequestbuffer.h>
2492+
2493+namespace compiz
2494+{
2495+namespace window
2496+{
2497+class AsyncServerWindow;
2498+namespace configure_buffers
2499+{
2500+
2501+class Lockable
2502+{
2503+ public:
2504+
2505+ typedef boost::shared_ptr <Lockable> Ptr;
2506+ typedef boost::weak_ptr <Lockable> Weak;
2507+
2508+ virtual ~Lockable () {}
2509+
2510+ virtual void lock () = 0;
2511+};
2512+
2513+class BufferLock :
2514+ public Lockable,
2515+ public Releasable
2516+{
2517+ public:
2518+ typedef boost::shared_ptr <BufferLock> Ptr;
2519+
2520+ virtual ~BufferLock () {}
2521+};
2522+
2523+class CountedFreeze
2524+{
2525+ public:
2526+
2527+ virtual ~CountedFreeze () {}
2528+
2529+ virtual void freeze () = 0;
2530+ virtual void release () = 0;
2531+
2532+ virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0;
2533+};
2534+
2535+class ConfigureRequestBuffer :
2536+ public CountedFreeze,
2537+ public Buffer
2538+{
2539+ public:
2540+
2541+ typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory;
2542+
2543+ void freeze ();
2544+ void release ();
2545+
2546+ void untrackLock (compiz::window::configure_buffers::BufferLock *lock);
2547+
2548+ void pushClientRequest (const XWindowChanges &xwc, unsigned int mask);
2549+ void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask);
2550+ void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask);
2551+ void pushSyntheticConfigureNotify ();
2552+ compiz::window::configure_buffers::Releasable::Ptr obtainLock ();
2553+
2554+ /* Implement getAttributes and require that
2555+ * the queue is released before calling through
2556+ * to the SyncServerWindow */
2557+ bool queryAttributes (XWindowAttributes &attrib);
2558+ bool queryFrameAttributes (XWindowAttributes &attrib);
2559+ XRectangle * queryShapeRectangles (int kind,
2560+ int *count,
2561+ int *ordering);
2562+
2563+ void forceRelease ();
2564+
2565+ static compiz::window::configure_buffers::Buffer::Ptr
2566+ Create (AsyncServerWindow *asyncServerWindow,
2567+ SyncServerWindow *syncServerWindow,
2568+ const LockFactory &factory);
2569+
2570+ private:
2571+
2572+ ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
2573+ SyncServerWindow *syncServerWindow,
2574+ const LockFactory &factory);
2575+
2576+ class Private;
2577+ std::auto_ptr <Private> priv;
2578+};
2579+
2580+class ConfigureBufferLock :
2581+ public compiz::window::configure_buffers::BufferLock
2582+{
2583+ public:
2584+
2585+ typedef boost::shared_ptr <ConfigureBufferLock> Ptr;
2586+
2587+ ConfigureBufferLock (CountedFreeze *);
2588+ ~ConfigureBufferLock ();
2589+
2590+ void lock ();
2591+ void release ();
2592+
2593+ private:
2594+
2595+ class Private;
2596+ std::auto_ptr <Private> priv;
2597+};
2598+}
2599+}
2600+}
2601+#endif
2602
2603=== removed file 'src/configurerequestbuffer-impl.h'
2604--- src/configurerequestbuffer-impl.h 2012-12-13 11:12:32 +0000
2605+++ src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000
2606@@ -1,145 +0,0 @@
2607-/*
2608- * Copyright © 2012 Sam Spilsbury
2609- *
2610- * Permission to use, copy, modify, distribute, and sell this software
2611- * and its documentation for any purpose is hereby granted without
2612- * fee, provided that the above copyright notice appear in all copies
2613- * and that both that copyright notice and this permission notice
2614- * appear in supporting documentation, and that the name of
2615- * Canonical Ltd. not be used in advertising or publicity pertaining to
2616- * distribution of the software without specific, written prior permission.
2617- * Canonical Ltd. makes no representations about the suitability of this
2618- * software for any purpose. It is provided "as is" without express or
2619- * implied warranty.
2620- *
2621- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2622- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2623- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2624- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2625- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2626- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2627- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2628- *
2629- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2630- */
2631-#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
2632-#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
2633-
2634-#include <memory>
2635-#include <vector>
2636-#include <boost/weak_ptr.hpp>
2637-#include <boost/shared_ptr.hpp>
2638-#include <boost/function.hpp>
2639-#include <X11/Xlib.h>
2640-
2641-#include <core/configurerequestbuffer.h>
2642-
2643-namespace compiz
2644-{
2645-namespace window
2646-{
2647-class AsyncServerWindow;
2648-namespace configure_buffers
2649-{
2650-
2651-class Lockable
2652-{
2653- public:
2654-
2655- typedef boost::shared_ptr <Lockable> Ptr;
2656- typedef boost::weak_ptr <Lockable> Weak;
2657-
2658- virtual ~Lockable () {}
2659-
2660- virtual void lock () = 0;
2661-};
2662-
2663-class BufferLock :
2664- public Lockable,
2665- public Releasable
2666-{
2667- public:
2668- typedef boost::shared_ptr <BufferLock> Ptr;
2669-
2670- virtual ~BufferLock () {}
2671-};
2672-
2673-class CountedFreeze
2674-{
2675- public:
2676-
2677- virtual ~CountedFreeze () {}
2678-
2679- virtual void freeze () = 0;
2680- virtual void release () = 0;
2681-
2682- virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0;
2683-};
2684-
2685-class ConfigureRequestBuffer :
2686- public CountedFreeze,
2687- public Buffer
2688-{
2689- public:
2690-
2691- typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory;
2692-
2693- void freeze ();
2694- void release ();
2695-
2696- void untrackLock (compiz::window::configure_buffers::BufferLock *lock);
2697-
2698- void pushClientRequest (const XWindowChanges &xwc, unsigned int mask);
2699- void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask);
2700- void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask);
2701- void pushSyntheticConfigureNotify ();
2702- compiz::window::configure_buffers::Releasable::Ptr obtainLock ();
2703-
2704- /* Implement getAttributes and require that
2705- * the queue is released before calling through
2706- * to the SyncServerWindow */
2707- bool queryAttributes (XWindowAttributes &attrib);
2708- bool queryFrameAttributes (XWindowAttributes &attrib);
2709- XRectangle * queryShapeRectangles (int kind,
2710- int *count,
2711- int *ordering);
2712-
2713- void forceRelease ();
2714-
2715- static compiz::window::configure_buffers::Buffer::Ptr
2716- Create (AsyncServerWindow *asyncServerWindow,
2717- SyncServerWindow *syncServerWindow,
2718- const LockFactory &factory);
2719-
2720- private:
2721-
2722- ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
2723- SyncServerWindow *syncServerWindow,
2724- const LockFactory &factory);
2725-
2726- class Private;
2727- std::auto_ptr <Private> priv;
2728-};
2729-
2730-class ConfigureBufferLock :
2731- public compiz::window::configure_buffers::BufferLock
2732-{
2733- public:
2734-
2735- typedef boost::shared_ptr <ConfigureBufferLock> Ptr;
2736-
2737- ConfigureBufferLock (CountedFreeze *);
2738- ~ConfigureBufferLock ();
2739-
2740- void lock ();
2741- void release ();
2742-
2743- private:
2744-
2745- class Private;
2746- std::auto_ptr <Private> priv;
2747-};
2748-}
2749-}
2750-}
2751-#endif
2752
2753=== added file 'src/configurerequestbuffer.cpp'
2754--- src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
2755+++ src/configurerequestbuffer.cpp 2013-02-28 02:29:22 +0000
2756@@ -0,0 +1,363 @@
2757+/*
2758+ * Copyright © 2012 Sam Spilsbury
2759+ *
2760+ * Permission to use, copy, modify, distribute, and sell this software
2761+ * and its documentation for any purpose is hereby granted without
2762+ * fee, provided that the above copyright notice appear in all copies
2763+ * and that both that copyright notice and this permission notice
2764+ * appear in supporting documentation, and that the name of
2765+ * Canonical Ltd. not be used in advertising or publicity pertaining to
2766+ * distribution of the software without specific, written prior permission.
2767+ * Canonical Ltd. makes no representations about the suitability of this
2768+ * software for any purpose. It is provided "as is" without express or
2769+ * implied warranty.
2770+ *
2771+ * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2772+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
2773+ * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2774+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2775+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2776+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
2777+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2778+ *
2779+ * Authored by: Sam Spilsbury <smspillaz@gmail.com>
2780+ */
2781+#include <cstdio>
2782+#include <cassert>
2783+#include <boost/foreach.hpp>
2784+#include <boost/weak_ptr.hpp>
2785+#include <boost/bind.hpp>
2786+#include "asyncserverwindow.h"
2787+#include "configurerequestbuffer-impl.h"
2788+
2789+#ifndef foreach
2790+#define foreach BOOST_FOREACH
2791+#endif
2792+
2793+namespace crb = compiz::window::configure_buffers;
2794+namespace cw = compiz::window;
2795+
2796+class crb::ConfigureRequestBuffer::Private
2797+{
2798+ public:
2799+
2800+ typedef crb::Lockable::Weak LockObserver;
2801+
2802+ Private (cw::AsyncServerWindow *asyncServerWindow,
2803+ cw::SyncServerWindow *syncServerWindow,
2804+ const crb::ConfigureRequestBuffer::LockFactory &lockFactory) :
2805+ clientChangeMask (0),
2806+ wrapperChangeMask (0),
2807+ frameChangeMask (0),
2808+ sendSyntheticConfigure (false),
2809+ lockCount (0),
2810+ asyncServerWindow (asyncServerWindow),
2811+ syncServerWindow (syncServerWindow),
2812+ lockFactory (lockFactory)
2813+ {
2814+ }
2815+
2816+ void dispatchConfigure (bool force = false);
2817+
2818+ XWindowChanges clientChanges;
2819+ unsigned int clientChangeMask;
2820+
2821+ XWindowChanges wrapperChanges;
2822+ unsigned int wrapperChangeMask;
2823+
2824+ XWindowChanges frameChanges;
2825+ unsigned int frameChangeMask;
2826+
2827+ bool sendSyntheticConfigure;
2828+
2829+ unsigned int lockCount;
2830+
2831+ cw::AsyncServerWindow *asyncServerWindow;
2832+ cw::SyncServerWindow *syncServerWindow;
2833+
2834+ crb::ConfigureRequestBuffer::LockFactory lockFactory;
2835+ std::vector <LockObserver> locks;
2836+};
2837+
2838+void
2839+crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force)
2840+{
2841+ const unsigned int allEventMasks = 0x7f;
2842+ bool immediate = frameChangeMask & (CWStackMode | CWSibling);
2843+
2844+ /* This is a stop-gap solution for not having a plugin API to
2845+ * query the window shape. Once we have that, we can safely
2846+ * remove these and require the queue to be unlocked when that
2847+ * happens. Its a separate unit of work for improving resize
2848+ * performance anyways.
2849+ */
2850+ immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth));
2851+ immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
2852+ immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
2853+ immediate |= force;
2854+
2855+ bool clientDispatch = (clientChangeMask & allEventMasks);
2856+ bool wrapperDispatch = (wrapperChangeMask & allEventMasks);
2857+ bool frameDispatch = (frameChangeMask & allEventMasks);
2858+
2859+ bool dispatch = !lockCount && (clientDispatch ||
2860+ wrapperDispatch ||
2861+ frameDispatch ||
2862+ sendSyntheticConfigure);
2863+
2864+ if (dispatch || immediate)
2865+ {
2866+ if (frameDispatch)
2867+ {
2868+ asyncServerWindow->requestConfigureOnFrame (frameChanges,
2869+ frameChangeMask);
2870+ frameChangeMask = 0;
2871+ }
2872+
2873+ if (wrapperDispatch)
2874+ {
2875+ asyncServerWindow->requestConfigureOnWrapper (wrapperChanges,
2876+ wrapperChangeMask);
2877+ wrapperChangeMask = 0;
2878+ }
2879+
2880+ if (clientDispatch)
2881+ {
2882+ asyncServerWindow->requestConfigureOnClient (clientChanges,
2883+ clientChangeMask);
2884+ clientChangeMask = 0;
2885+ }
2886+
2887+ if (sendSyntheticConfigure)
2888+ {
2889+ asyncServerWindow->sendSyntheticConfigureNotify ();
2890+ sendSyntheticConfigure = false;
2891+ }
2892+
2893+ foreach (const LockObserver &lock, locks)
2894+ {
2895+ crb::Lockable::Ptr strongLock (lock.lock ());
2896+
2897+ /* We might be in a lock's destructor so check
2898+ * if this can really be re-locked, if not, its
2899+ * no big deal as the lock is going away anyways
2900+ */
2901+ if (strongLock)
2902+ strongLock->lock ();
2903+ }
2904+ }
2905+}
2906+
2907+void
2908+crb::ConfigureRequestBuffer::freeze ()
2909+{
2910+ priv->lockCount++;
2911+
2912+ assert (priv->lockCount <= priv->locks.size ());
2913+}
2914+
2915+void
2916+crb::ConfigureRequestBuffer::release ()
2917+{
2918+ assert (priv->lockCount);
2919+
2920+ priv->lockCount--;
2921+
2922+ priv->dispatchConfigure ();
2923+}
2924+
2925+namespace
2926+{
2927+void applyChangeToXWC (const XWindowChanges &from,
2928+ XWindowChanges &to,
2929+ unsigned int mask)
2930+{
2931+ if (mask & CWX)
2932+ to.x = from.x;
2933+
2934+ if (mask & CWY)
2935+ to.y = from.y;
2936+
2937+ if (mask & CWWidth)
2938+ to.width = from.width;
2939+
2940+ if (mask & CWHeight)
2941+ to.height = from.height;
2942+
2943+ if (mask & CWBorderWidth)
2944+ to.border_width = from.border_width;
2945+
2946+ if (mask & CWSibling)
2947+ to.sibling = from.sibling;
2948+
2949+ if (mask & CWStackMode)
2950+ to.stack_mode = from.stack_mode;
2951+}
2952+}
2953+
2954+void
2955+crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc,
2956+ unsigned int mask)
2957+{
2958+ applyChangeToXWC (xwc, priv->clientChanges, mask);
2959+ priv->clientChangeMask |= mask;
2960+
2961+ priv->dispatchConfigure ();
2962+}
2963+
2964+void
2965+crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc,
2966+ unsigned int mask)
2967+{
2968+ applyChangeToXWC (xwc, priv->wrapperChanges, mask);
2969+ priv->wrapperChangeMask |= mask;
2970+
2971+ priv->dispatchConfigure ();
2972+}
2973+
2974+void
2975+crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc,
2976+ unsigned int mask)
2977+{
2978+ applyChangeToXWC (xwc, priv->frameChanges, mask);
2979+ priv->frameChangeMask |= mask;
2980+
2981+ priv->dispatchConfigure ();
2982+}
2983+
2984+void
2985+crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify ()
2986+{
2987+ priv->sendSyntheticConfigure = true;
2988+
2989+ priv->dispatchConfigure ();
2990+}
2991+
2992+crb::Releasable::Ptr
2993+crb::ConfigureRequestBuffer::obtainLock ()
2994+{
2995+ crb::BufferLock::Ptr lock (priv->lockFactory (this));
2996+
2997+ priv->locks.push_back (crb::Lockable::Weak (lock));
2998+ lock->lock ();
2999+
3000+ return lock;
3001+}
3002+
3003+namespace
3004+{
3005+bool isLock (const crb::Lockable::Weak &lockable,
3006+ crb::BufferLock *lock)
3007+{
3008+ crb::Lockable::Ptr strongLockable (lockable.lock ());
3009+
3010+ /* Asserting that the lock did not go away without telling
3011+ * us first */
3012+ assert (strongLockable.get ());
3013+
3014+ if (strongLockable.get () == lock)
3015+ return true;
3016+
3017+ return false;
3018+}
3019+}
3020+
3021+void
3022+crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock)
3023+{
3024+ std::remove_if (priv->locks.begin (),
3025+ priv->locks.end (),
3026+ boost::bind (isLock, _1, lock));
3027+}
3028+
3029+bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib)
3030+{
3031+ priv->dispatchConfigure (true);
3032+ return priv->syncServerWindow->queryAttributes (attrib);
3033+}
3034+
3035+bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib)
3036+{
3037+ priv->dispatchConfigure (true);
3038+ return priv->syncServerWindow->queryFrameAttributes (attrib);
3039+}
3040+
3041+/* This is more or less of a stop-gap for the fact that
3042+ * when resizing window we re-query the window shape
3043+ * and apply that to the frame. That's a separate unit of
3044+ * work and should be dealt with separately. For now, force
3045+ * a release of the queue whenever we do that so that
3046+ * XShapeGetRectangles doesn't return an unexpected value
3047+ */
3048+XRectangle *
3049+crb::ConfigureRequestBuffer::queryShapeRectangles (int kind,
3050+ int *count,
3051+ int *ordering)
3052+{
3053+ priv->dispatchConfigure (true);
3054+ return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering);
3055+}
3056+
3057+void crb::ConfigureRequestBuffer::forceRelease ()
3058+{
3059+ priv->dispatchConfigure (true);
3060+}
3061+
3062+crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
3063+ SyncServerWindow *syncServerWindow,
3064+ const crb::ConfigureRequestBuffer::LockFactory &factory) :
3065+ priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory))
3066+{
3067+}
3068+
3069+compiz::window::configure_buffers::Buffer::Ptr
3070+crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow,
3071+ SyncServerWindow *syncServerWindow,
3072+ const LockFactory &factory)
3073+{
3074+ return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow,
3075+ syncServerWindow,
3076+ factory));
3077+}
3078+
3079+class crb::ConfigureBufferLock::Private
3080+{
3081+ public:
3082+
3083+ Private (crb::CountedFreeze *freezable) :
3084+ freezable (freezable),
3085+ armed (false)
3086+ {
3087+ }
3088+
3089+ crb::CountedFreeze *freezable;
3090+ bool armed;
3091+};
3092+
3093+crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) :
3094+ priv (new crb::ConfigureBufferLock::Private (freezable))
3095+{
3096+}
3097+
3098+crb::ConfigureBufferLock::~ConfigureBufferLock ()
3099+{
3100+ release ();
3101+}
3102+
3103+void
3104+crb::ConfigureBufferLock::lock ()
3105+{
3106+ if (!priv->armed)
3107+ priv->freezable->freeze ();
3108+
3109+ priv->armed = true;
3110+}
3111+
3112+void
3113+crb::ConfigureBufferLock::release ()
3114+{
3115+ if (priv->armed)
3116+ priv->freezable->release ();
3117+
3118+ priv->armed = false;
3119+}
3120
3121=== removed file 'src/configurerequestbuffer.cpp'
3122--- src/configurerequestbuffer.cpp 2013-02-14 12:12:53 +0000
3123+++ src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
3124@@ -1,363 +0,0 @@
3125-/*
3126- * Copyright © 2012 Sam Spilsbury
3127- *
3128- * Permission to use, copy, modify, distribute, and sell this software
3129- * and its documentation for any purpose is hereby granted without
3130- * fee, provided that the above copyright notice appear in all copies
3131- * and that both that copyright notice and this permission notice
3132- * appear in supporting documentation, and that the name of
3133- * Canonical Ltd. not be used in advertising or publicity pertaining to
3134- * distribution of the software without specific, written prior permission.
3135- * Canonical Ltd. makes no representations about the suitability of this
3136- * software for any purpose. It is provided "as is" without express or
3137- * implied warranty.
3138- *
3139- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3140- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
3141- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3142- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
3143- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
3144- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
3145- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3146- *
3147- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
3148- */
3149-#include <cstdio>
3150-#include <cassert>
3151-#include <boost/foreach.hpp>
3152-#include <boost/weak_ptr.hpp>
3153-#include <boost/bind.hpp>
3154-#include "asyncserverwindow.h"
3155-#include "configurerequestbuffer-impl.h"
3156-
3157-#ifndef foreach
3158-#define foreach BOOST_FOREACH
3159-#endif
3160-
3161-namespace crb = compiz::window::configure_buffers;
3162-namespace cw = compiz::window;
3163-
3164-class crb::ConfigureRequestBuffer::Private
3165-{
3166- public:
3167-
3168- typedef crb::Lockable::Weak LockObserver;
3169-
3170- Private (cw::AsyncServerWindow *asyncServerWindow,
3171- cw::SyncServerWindow *syncServerWindow,
3172- const crb::ConfigureRequestBuffer::LockFactory &lockFactory) :
3173- clientChangeMask (0),
3174- wrapperChangeMask (0),
3175- frameChangeMask (0),
3176- sendSyntheticConfigure (false),
3177- lockCount (0),
3178- asyncServerWindow (asyncServerWindow),
3179- syncServerWindow (syncServerWindow),
3180- lockFactory (lockFactory)
3181- {
3182- }
3183-
3184- void dispatchConfigure (bool force = false);
3185-
3186- XWindowChanges clientChanges;
3187- unsigned int clientChangeMask;
3188-
3189- XWindowChanges wrapperChanges;
3190- unsigned int wrapperChangeMask;
3191-
3192- XWindowChanges frameChanges;
3193- unsigned int frameChangeMask;
3194-
3195- bool sendSyntheticConfigure;
3196-
3197- unsigned int lockCount;
3198-
3199- cw::AsyncServerWindow *asyncServerWindow;
3200- cw::SyncServerWindow *syncServerWindow;
3201-
3202- crb::ConfigureRequestBuffer::LockFactory lockFactory;
3203- std::vector <LockObserver> locks;
3204-};
3205-
3206-void
3207-crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force)
3208-{
3209- const unsigned int allEventMasks = 0x7f;
3210- bool immediate = frameChangeMask & (CWStackMode | CWSibling);
3211-
3212- /* This is a stop-gap solution for not having a plugin API to
3213- * query the window shape. Once we have that, we can safely
3214- * remove these and require the queue to be unlocked when that
3215- * happens. Its a separate unit of work for improving resize
3216- * performance anyways.
3217- */
3218- immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth));
3219- immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
3220- immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
3221- immediate |= force;
3222-
3223- bool clientDispatch = (clientChangeMask & allEventMasks);
3224- bool wrapperDispatch = (wrapperChangeMask & allEventMasks);
3225- bool frameDispatch = (frameChangeMask & allEventMasks);
3226-
3227- bool dispatch = !lockCount && (clientDispatch ||
3228- wrapperDispatch ||
3229- frameDispatch ||
3230- sendSyntheticConfigure);
3231-
3232- if (dispatch || immediate)
3233- {
3234- if (frameDispatch)
3235- {
3236- asyncServerWindow->requestConfigureOnFrame (frameChanges,
3237- frameChangeMask);
3238- frameChangeMask = 0;
3239- }
3240-
3241- if (wrapperDispatch)
3242- {
3243- asyncServerWindow->requestConfigureOnWrapper (wrapperChanges,
3244- wrapperChangeMask);
3245- wrapperChangeMask = 0;
3246- }
3247-
3248- if (clientDispatch)
3249- {
3250- asyncServerWindow->requestConfigureOnClient (clientChanges,
3251- clientChangeMask);
3252- clientChangeMask = 0;
3253- }
3254-
3255- if (sendSyntheticConfigure)
3256- {
3257- asyncServerWindow->sendSyntheticConfigureNotify ();
3258- sendSyntheticConfigure = false;
3259- }
3260-
3261- foreach (const LockObserver &lock, locks)
3262- {
3263- crb::Lockable::Ptr strongLock (lock.lock ());
3264-
3265- /* We might be in a lock's destructor so check
3266- * if this can really be re-locked, if not, its
3267- * no big deal as the lock is going away anyways
3268- */
3269- if (strongLock)
3270- strongLock->lock ();
3271- }
3272- }
3273-}
3274-
3275-void
3276-crb::ConfigureRequestBuffer::freeze ()
3277-{
3278- priv->lockCount++;
3279-
3280- assert (priv->lockCount <= priv->locks.size ());
3281-}
3282-
3283-void
3284-crb::ConfigureRequestBuffer::release ()
3285-{
3286- assert (priv->lockCount);
3287-
3288- priv->lockCount--;
3289-
3290- priv->dispatchConfigure ();
3291-}
3292-
3293-namespace
3294-{
3295-void applyChangeToXWC (const XWindowChanges &from,
3296- XWindowChanges &to,
3297- unsigned int mask)
3298-{
3299- if (mask & CWX)
3300- to.x = from.x;
3301-
3302- if (mask & CWY)
3303- to.y = from.y;
3304-
3305- if (mask & CWWidth)
3306- to.width = from.width;
3307-
3308- if (mask & CWHeight)
3309- to.height = from.height;
3310-
3311- if (mask & CWBorderWidth)
3312- to.border_width = from.border_width;
3313-
3314- if (mask & CWSibling)
3315- to.sibling = from.sibling;
3316-
3317- if (mask & CWStackMode)
3318- to.stack_mode = from.stack_mode;
3319-}
3320-}
3321-
3322-void
3323-crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc,
3324- unsigned int mask)
3325-{
3326- applyChangeToXWC (xwc, priv->clientChanges, mask);
3327- priv->clientChangeMask |= mask;
3328-
3329- priv->dispatchConfigure ();
3330-}
3331-
3332-void
3333-crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc,
3334- unsigned int mask)
3335-{
3336- applyChangeToXWC (xwc, priv->wrapperChanges, mask);
3337- priv->wrapperChangeMask |= mask;
3338-
3339- priv->dispatchConfigure ();
3340-}
3341-
3342-void
3343-crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc,
3344- unsigned int mask)
3345-{
3346- applyChangeToXWC (xwc, priv->frameChanges, mask);
3347- priv->frameChangeMask |= mask;
3348-
3349- priv->dispatchConfigure ();
3350-}
3351-
3352-void
3353-crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify ()
3354-{
3355- priv->sendSyntheticConfigure = true;
3356-
3357- priv->dispatchConfigure ();
3358-}
3359-
3360-crb::Releasable::Ptr
3361-crb::ConfigureRequestBuffer::obtainLock ()
3362-{
3363- crb::BufferLock::Ptr lock (priv->lockFactory (this));
3364-
3365- priv->locks.push_back (crb::Lockable::Weak (lock));
3366- lock->lock ();
3367-
3368- return lock;
3369-}
3370-
3371-namespace
3372-{
3373-bool isLock (const crb::Lockable::Weak &lockable,
3374- crb::BufferLock *lock)
3375-{
3376- crb::Lockable::Ptr strongLockable (lockable.lock ());
3377-
3378- /* Asserting that the lock did not go away without telling
3379- * us first */
3380- assert (strongLockable.get ());
3381-
3382- if (strongLockable.get () == lock)
3383- return true;
3384-
3385- return false;
3386-}
3387-}
3388-
3389-void
3390-crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock)
3391-{
3392- std::remove_if (priv->locks.begin (),
3393- priv->locks.end (),
3394- boost::bind (isLock, _1, lock));
3395-}
3396-
3397-bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib)
3398-{
3399- priv->dispatchConfigure (true);
3400- return priv->syncServerWindow->queryAttributes (attrib);
3401-}
3402-
3403-bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib)
3404-{
3405- priv->dispatchConfigure (true);
3406- return priv->syncServerWindow->queryFrameAttributes (attrib);
3407-}
3408-
3409-/* This is more or less of a stop-gap for the fact that
3410- * when resizing window we re-query the window shape
3411- * and apply that to the frame. That's a separate unit of
3412- * work and should be dealt with separately. For now, force
3413- * a release of the queue whenever we do that so that
3414- * XShapeGetRectangles doesn't return an unexpected value
3415- */
3416-XRectangle *
3417-crb::ConfigureRequestBuffer::queryShapeRectangles (int kind,
3418- int *count,
3419- int *ordering)
3420-{
3421- priv->dispatchConfigure (true);
3422- return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering);
3423-}
3424-
3425-void crb::ConfigureRequestBuffer::forceRelease ()
3426-{
3427- priv->dispatchConfigure (true);
3428-}
3429-
3430-crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
3431- SyncServerWindow *syncServerWindow,
3432- const crb::ConfigureRequestBuffer::LockFactory &factory) :
3433- priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory))
3434-{
3435-}
3436-
3437-compiz::window::configure_buffers::Buffer::Ptr
3438-crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow,
3439- SyncServerWindow *syncServerWindow,
3440- const LockFactory &factory)
3441-{
3442- return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow,
3443- syncServerWindow,
3444- factory));
3445-}
3446-
3447-class crb::ConfigureBufferLock::Private
3448-{
3449- public:
3450-
3451- Private (crb::CountedFreeze *freezable) :
3452- freezable (freezable),
3453- armed (false)
3454- {
3455- }
3456-
3457- crb::CountedFreeze *freezable;
3458- bool armed;
3459-};
3460-
3461-crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) :
3462- priv (new crb::ConfigureBufferLock::Private (freezable))
3463-{
3464-}
3465-
3466-crb::ConfigureBufferLock::~ConfigureBufferLock ()
3467-{
3468- release ();
3469-}
3470-
3471-void
3472-crb::ConfigureBufferLock::lock ()
3473-{
3474- if (!priv->armed)
3475- priv->freezable->freeze ();
3476-
3477- priv->armed = true;
3478-}
3479-
3480-void
3481-crb::ConfigureBufferLock::release ()
3482-{
3483- if (priv->armed)
3484- priv->freezable->release ();
3485-
3486- priv->armed = false;
3487-}
3488
3489=== removed file 'src/serverwindow.h'
3490=== added file 'src/syncserverwindow.h'
3491--- src/syncserverwindow.h 1970-01-01 00:00:00 +0000
3492+++ src/syncserverwindow.h 2013-02-28 02:29:22 +0000
3493@@ -0,0 +1,49 @@
3494+/*
3495+ * Copyright © 2012 Sam Spilsbury
3496+ *
3497+ * Permission to use, copy, modify, distribute, and sell this software
3498+ * and its documentation for any purpose is hereby granted without
3499+ * fee, provided that the above copyright notice appear in all copies
3500+ * and that both that copyright notice and this permission notice
3501+ * appear in supporting documentation, and that the name of
3502+ * Canonical Ltd. not be used in advertising or publicity pertaining to
3503+ * distribution of the software without specific, written prior permission.
3504+ * Canonical Ltd. makes no representations about the suitability of this
3505+ * software for any purpose. It is provided "as is" without express or
3506+ * implied warranty.
3507+ *
3508+ * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3509+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
3510+ * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3511+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
3512+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
3513+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
3514+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3515+ *
3516+ * Authored by: Sam Spilsbury <smspillaz@gmail.com>
3517+ */
3518+#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H
3519+#define _COMPIZ_SYNC_SERVER_WINDOW_H
3520+
3521+#include <X11/Xlib.h>
3522+
3523+namespace compiz
3524+{
3525+namespace window
3526+{
3527+class SyncServerWindow
3528+{
3529+ public:
3530+
3531+ virtual ~SyncServerWindow () {}
3532+
3533+ virtual bool queryAttributes (XWindowAttributes &attrib) = 0;
3534+ virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0;
3535+ virtual XRectangle * queryShapeRectangles (int kind,
3536+ int *count,
3537+ int *ordering) = 0;
3538+};
3539+}
3540+}
3541+
3542+#endif
3543
3544=== removed file 'src/syncserverwindow.h'
3545--- src/syncserverwindow.h 2012-12-13 11:12:32 +0000
3546+++ src/syncserverwindow.h 1970-01-01 00:00:00 +0000
3547@@ -1,49 +0,0 @@
3548-/*
3549- * Copyright © 2012 Sam Spilsbury
3550- *
3551- * Permission to use, copy, modify, distribute, and sell this software
3552- * and its documentation for any purpose is hereby granted without
3553- * fee, provided that the above copyright notice appear in all copies
3554- * and that both that copyright notice and this permission notice
3555- * appear in supporting documentation, and that the name of
3556- * Canonical Ltd. not be used in advertising or publicity pertaining to
3557- * distribution of the software without specific, written prior permission.
3558- * Canonical Ltd. makes no representations about the suitability of this
3559- * software for any purpose. It is provided "as is" without express or
3560- * implied warranty.
3561- *
3562- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3563- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
3564- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3565- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
3566- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
3567- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
3568- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3569- *
3570- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
3571- */
3572-#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H
3573-#define _COMPIZ_SYNC_SERVER_WINDOW_H
3574-
3575-#include <X11/Xlib.h>
3576-
3577-namespace compiz
3578-{
3579-namespace window
3580-{
3581-class SyncServerWindow
3582-{
3583- public:
3584-
3585- virtual ~SyncServerWindow () {}
3586-
3587- virtual bool queryAttributes (XWindowAttributes &attrib) = 0;
3588- virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0;
3589- virtual XRectangle * queryShapeRectangles (int kind,
3590- int *count,
3591- int *ordering) = 0;
3592-};
3593-}
3594-}
3595-
3596-#endif
3597
3598=== added file 'src/tests/test_configurerequestbuffer.cpp'
3599--- src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
3600+++ src/tests/test_configurerequestbuffer.cpp 2013-02-28 02:29:22 +0000
3601@@ -0,0 +1,667 @@
3602+/*
3603+ * Copyright © 2012 Sam Spilsbury
3604+ *
3605+ * Permission to use, copy, modify, distribute, and sell this software
3606+ * and its documentation for any purpose is hereby granted without
3607+ * fee, provided that the above copyright notice appear in all copies
3608+ * and that both that copyright notice and this permission notice
3609+ * appear in supporting documentation, and that the name of
3610+ * Canonical Ltd. not be used in advertising or publicity pertaining to
3611+ * distribution of the software without specific, written prior permission.
3612+ * Canonical Ltd. makes no representations about the suitability of this
3613+ * software for any purpose. It is provided "as is" without express or
3614+ * implied warranty.
3615+ *
3616+ * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3617+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
3618+ * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3619+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
3620+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
3621+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
3622+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3623+ *
3624+ * Authored by: Sam Spilsbury <smspillaz@gmail.com>
3625+ */
3626+#include <deque>
3627+#include <boost/shared_ptr.hpp>
3628+#include <boost/make_shared.hpp>
3629+#include <boost/bind.hpp>
3630+#include <gmock/gmock.h>
3631+#include <gtest/gtest.h>
3632+#include <X11/Xlib.h>
3633+
3634+#include "configurerequestbuffer-impl.h"
3635+#include "asyncserverwindow.h"
3636+
3637+namespace crb = compiz::window::configure_buffers;
3638+namespace cw = compiz::window;
3639+
3640+using testing::_;
3641+using testing::NiceMock;
3642+using testing::Return;
3643+using testing::Invoke;
3644+using testing::WithArgs;
3645+using testing::SetArgReferee;
3646+using testing::DoAll;
3647+using testing::InSequence;
3648+using testing::ReturnNull;
3649+using testing::IsNull;
3650+
3651+class MockAsyncServerWindow :
3652+ public cw::AsyncServerWindow
3653+{
3654+ public:
3655+
3656+ MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int));
3657+ MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int));
3658+ MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int));
3659+ MOCK_METHOD0 (sendSyntheticConfigureNotify, void ());
3660+ MOCK_CONST_METHOD0 (hasCustomShape, bool ());
3661+};
3662+
3663+class MockSyncServerWindow :
3664+ public cw::SyncServerWindow
3665+{
3666+ public:
3667+
3668+ MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &));
3669+ MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &));
3670+ MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *));
3671+};
3672+
3673+namespace
3674+{
3675+int REQUEST_X = 1;
3676+int REQUEST_Y = 2;
3677+int REQUEST_WIDTH = 3;
3678+int REQUEST_HEIGHT = 4;
3679+int REQUEST_BORDER = 5;
3680+
3681+Window REQUEST_ABOVE = 6;
3682+unsigned int REQUEST_MODE = 7;
3683+
3684+crb::BufferLock::Ptr
3685+CreateNormalLock (crb::CountedFreeze *cf)
3686+{
3687+ return boost::make_shared <crb::ConfigureBufferLock> (cf);
3688+}
3689+
3690+}
3691+
3692+MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges")
3693+{
3694+ if (vm & CWX)
3695+ if (xwc.x != arg.x)
3696+ return false;
3697+
3698+ if (vm & CWY)
3699+ if (xwc.y != arg.y)
3700+ return false;
3701+
3702+ if (vm & CWWidth)
3703+ if (xwc.width != arg.width)
3704+ return false;
3705+
3706+ if (vm & CWHeight)
3707+ if (xwc.height != arg.height)
3708+ return false;
3709+
3710+ if (vm & CWBorderWidth)
3711+ if (xwc.border_width != arg.border_width)
3712+ return false;
3713+
3714+ if (vm & CWStackMode)
3715+ if (xwc.stack_mode != arg.stack_mode)
3716+ return false;
3717+
3718+ if (vm & CWSibling)
3719+ if (xwc.sibling != arg.sibling)
3720+ return false;
3721+
3722+ return true;
3723+}
3724+
3725+class ConfigureRequestBuffer :
3726+ public testing::Test
3727+{
3728+ public:
3729+
3730+ ConfigureRequestBuffer ()
3731+ {
3732+ /* Initialize xwc, we control it
3733+ * through the value masks */
3734+ xwc.x = REQUEST_X;
3735+ xwc.y = REQUEST_Y;
3736+ xwc.width = REQUEST_WIDTH;
3737+ xwc.height = REQUEST_HEIGHT;
3738+ xwc.border_width = REQUEST_BORDER;
3739+ xwc.sibling = REQUEST_ABOVE;
3740+ xwc.stack_mode = REQUEST_MODE;
3741+ }
3742+
3743+ protected:
3744+
3745+ XWindowChanges xwc;
3746+ MockAsyncServerWindow asyncServerWindow;
3747+ MockSyncServerWindow syncServerWindow;
3748+};
3749+
3750+class ConfigureRequestBufferDispatch :
3751+ public ConfigureRequestBuffer
3752+{
3753+ protected:
3754+
3755+ ConfigureRequestBufferDispatch () :
3756+ ConfigureRequestBuffer (),
3757+ factory (boost::bind (CreateNormalLock, _1)),
3758+ buffer (
3759+ crb::ConfigureRequestBuffer::Create (&asyncServerWindow,
3760+ &syncServerWindow,
3761+ factory))
3762+ {
3763+ }
3764+
3765+ crb::ConfigureRequestBuffer::LockFactory factory;
3766+ crb::Buffer::Ptr buffer;
3767+};
3768+
3769+TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify)
3770+{
3771+ EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ());
3772+
3773+ buffer->pushSyntheticConfigureNotify ();
3774+}
3775+
3776+TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate)
3777+{
3778+ unsigned int valueMask = CWX | CWY | CWBorderWidth |
3779+ CWSibling | CWStackMode;
3780+
3781+ EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
3782+ valueMask));
3783+
3784+ buffer->pushClientRequest (xwc, valueMask);
3785+}
3786+
3787+TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate)
3788+{
3789+ unsigned int valueMask = CWX | CWY | CWBorderWidth |
3790+ CWSibling | CWStackMode;
3791+
3792+ EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
3793+ valueMask));
3794+
3795+ buffer->pushWrapperRequest (xwc, valueMask);
3796+}
3797+
3798+TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate)
3799+{
3800+ unsigned int valueMask = CWX | CWY | CWBorderWidth |
3801+ CWSibling | CWStackMode;
3802+
3803+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3804+ valueMask));
3805+
3806+ buffer->pushFrameRequest (xwc, valueMask);
3807+}
3808+
3809+TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked)
3810+{
3811+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3812+
3813+ unsigned int valueMask = 0;
3814+
3815+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3816+
3817+ buffer->pushFrameRequest (xwc, valueMask);
3818+}
3819+
3820+TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked)
3821+{
3822+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3823+
3824+ unsigned int valueMask = CWX;
3825+
3826+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3827+
3828+ buffer->pushFrameRequest (xwc, valueMask);
3829+
3830+ valueMask |= CWY;
3831+
3832+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3833+
3834+ buffer->pushFrameRequest (xwc, valueMask);
3835+
3836+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3837+ valueMask));
3838+
3839+ lock->release ();
3840+}
3841+
3842+/*
3843+ * This test is disabled until we can expose the QueryShapeRectangles API
3844+ * to plugins
3845+ */
3846+TEST_F (ConfigureRequestBufferDispatch, DISABLED_PushUpdateLockedReleaseInOrder)
3847+{
3848+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3849+
3850+ unsigned int valueMask = CWX | CWY;
3851+
3852+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3853+ EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0);
3854+ EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0);
3855+
3856+ buffer->pushClientRequest (xwc, valueMask);
3857+ buffer->pushWrapperRequest (xwc, 0);
3858+ buffer->pushFrameRequest (xwc, 0);
3859+
3860+ InSequence s;
3861+
3862+ /* Always frame -> wrapper -> client */
3863+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3864+ valueMask));
3865+ EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
3866+ valueMask));
3867+ EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
3868+ valueMask));
3869+
3870+ lock->release ();
3871+}
3872+
3873+TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer)
3874+{
3875+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3876+
3877+ unsigned int valueMask = CWX | CWY;
3878+
3879+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3880+
3881+ buffer->pushFrameRequest (xwc, valueMask);
3882+
3883+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3884+ valueMask));
3885+
3886+ lock->release ();
3887+}
3888+
3889+TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer)
3890+{
3891+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3892+
3893+ unsigned int valueMask = CWX | CWY;
3894+
3895+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
3896+
3897+ buffer->pushFrameRequest (xwc, valueMask);
3898+
3899+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3900+ valueMask));
3901+}
3902+
3903+TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack)
3904+{
3905+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3906+
3907+ unsigned int valueMask = CWStackMode | CWSibling;
3908+
3909+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3910+ valueMask));
3911+
3912+ buffer->pushFrameRequest (xwc, valueMask);
3913+}
3914+
3915+TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWindowSizeChange)
3916+{
3917+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3918+
3919+ unsigned int valueMask = CWWidth | CWHeight | CWBorderWidth;
3920+
3921+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
3922+ valueMask));
3923+
3924+ buffer->pushFrameRequest (xwc, valueMask);
3925+}
3926+
3927+TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnClientReposition)
3928+{
3929+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3930+
3931+ unsigned int valueMask = CWX | CWY;
3932+
3933+ EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
3934+ valueMask));
3935+
3936+ buffer->pushClientRequest (xwc, valueMask);
3937+}
3938+
3939+TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWrapperReposition)
3940+{
3941+ crb::Releasable::Ptr lock (buffer->obtainLock ());
3942+
3943+ unsigned int valueMask = CWX | CWY;
3944+
3945+ EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
3946+ valueMask));
3947+
3948+ buffer->pushWrapperRequest (xwc, valueMask);
3949+}
3950+
3951+namespace
3952+{
3953+class MockLock :
3954+ public crb::BufferLock
3955+{
3956+ public:
3957+
3958+ /* We're currently importing the locks statefulness and coupling
3959+ * the caller with that */
3960+ MockLock () :
3961+ armed (false)
3962+ {
3963+ ON_CALL (*this, lock ()).WillByDefault (
3964+ Invoke (this, &MockLock::FreezeIfUnarmed));
3965+ ON_CALL (*this, release ()).WillByDefault (
3966+ Invoke (this, &MockLock::ReleaseIfArmed));
3967+ }
3968+
3969+ void OperateOver (crb::CountedFreeze *cf)
3970+ {
3971+ countedFreeze = cf;
3972+ }
3973+
3974+ void FreezeIfUnarmed ()
3975+ {
3976+ if (!armed)
3977+ {
3978+ countedFreeze->freeze ();
3979+ armed = true;
3980+ }
3981+ }
3982+
3983+ void ReleaseIfArmed ()
3984+ {
3985+ if (armed)
3986+ {
3987+ countedFreeze->release ();
3988+ armed = false;
3989+ }
3990+ }
3991+
3992+ typedef boost::shared_ptr <MockLock> Ptr;
3993+
3994+ MOCK_METHOD0 (lock, void ());
3995+ MOCK_METHOD0 (release, void ());
3996+
3997+ private:
3998+
3999+ crb::CountedFreeze *countedFreeze;
4000+ bool armed;
4001+};
4002+
4003+class MockLockFactory
4004+{
4005+ public:
4006+
4007+ crb::BufferLock::Ptr
4008+ CreateMockLock (crb::CountedFreeze *cf)
4009+ {
4010+ MockLock::Ptr mockLock (locks.front ());
4011+ mockLock->OperateOver (cf);
4012+
4013+ locks.pop_front ();
4014+
4015+ return mockLock;
4016+ }
4017+
4018+ void
4019+ QueueLockForCreation (const MockLock::Ptr &lock)
4020+ {
4021+ locks.push_back (lock);
4022+ }
4023+
4024+ private:
4025+
4026+ std::deque <MockLock::Ptr> locks;
4027+};
4028+}
4029+
4030+class ConfigureRequestBufferLockBehaviour :
4031+ public ConfigureRequestBuffer
4032+{
4033+ public:
4034+
4035+ ConfigureRequestBufferLockBehaviour () :
4036+ ConfigureRequestBuffer (),
4037+ lock (boost::make_shared <MockLock> ()),
4038+ factory (
4039+ boost::bind (&MockLockFactory::CreateMockLock,
4040+ &mockLockFactory,
4041+ _1)),
4042+ buffer (
4043+ crb::ConfigureRequestBuffer::Create (
4044+ &asyncServerWindow,
4045+ &syncServerWindow,
4046+ factory))
4047+
4048+ {
4049+ mockLockFactory.QueueLockForCreation (lock);
4050+ }
4051+
4052+ protected:
4053+
4054+ typedef NiceMock <MockAsyncServerWindow> NiceServerWindow;
4055+ typedef crb::ConfigureRequestBuffer::LockFactory LockFactory;
4056+
4057+ MockLock::Ptr lock;
4058+ MockLockFactory mockLockFactory;
4059+
4060+ LockFactory factory;
4061+ crb::Buffer::Ptr buffer;
4062+};
4063+
4064+TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease)
4065+{
4066+ EXPECT_CALL (*lock, lock ());
4067+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4068+
4069+ unsigned int valueMask = CWX | CWY;
4070+
4071+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4072+
4073+ buffer->pushFrameRequest (xwc, valueMask);
4074+
4075+ /* We are releasing this lock */
4076+ EXPECT_CALL (*lock, release ());
4077+
4078+ /* Now the buffer will dispatch is configure request */
4079+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4080+
4081+ /* Rearm locks on release */
4082+ EXPECT_CALL (*lock, lock ());
4083+
4084+ /* Directly release the queue */
4085+ releasable->release ();
4086+}
4087+
4088+TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired)
4089+{
4090+ /* Locks get armed on construction */
4091+ EXPECT_CALL (*lock, lock ());
4092+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4093+
4094+ /* No call to requestConfigureOnFrame if there's nothing to be configured */
4095+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4096+
4097+ /* We are releasing this lock */
4098+ EXPECT_CALL (*lock, release ());
4099+
4100+ /* No rearm - we haven't released the whole buffer */
4101+ EXPECT_CALL (*lock, lock ()).Times (0);
4102+
4103+ /* Directly release the queue */
4104+ releasable->release ();
4105+}
4106+
4107+TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady)
4108+{
4109+ /* Locks get armed on construction */
4110+ EXPECT_CALL (*lock, lock ());
4111+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4112+
4113+ /* We are releasing this lock */
4114+ EXPECT_CALL (*lock, release ());
4115+
4116+ /* No call to requestConfigureOnFrame if there's nothing to be configured */
4117+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4118+
4119+ /* No rearm - we haven't released it */
4120+ EXPECT_CALL (*lock, lock ()).Times (0);
4121+
4122+ /* Directly release the queue */
4123+ releasable->release ();
4124+
4125+ /* Since we're now going to push something to a queue
4126+ * that's effectively not locked, the locks should now
4127+ * be released */
4128+ unsigned int valueMask = CWX | CWY;
4129+
4130+ /* Now rearm it */
4131+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4132+ EXPECT_CALL (*lock, lock ());
4133+
4134+ buffer->pushFrameRequest (xwc, valueMask);
4135+}
4136+
4137+TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease)
4138+{
4139+ MockLock::Ptr second (boost::make_shared <MockLock> ());
4140+ mockLockFactory.QueueLockForCreation (second);
4141+
4142+ /* Locks get armed on construction */
4143+ EXPECT_CALL (*lock, lock ());
4144+ EXPECT_CALL (*second, lock ());
4145+
4146+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4147+ crb::Releasable::Ptr otherReleasable (buffer->obtainLock ());
4148+
4149+ /* We are releasing this lock */
4150+ EXPECT_CALL (*lock, release ());
4151+
4152+ /* No call to requestConfigureOnFrame if there's nothing to be configured */
4153+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4154+
4155+ /* No rearm - we haven't released it */
4156+ EXPECT_CALL (*lock, lock ()).Times (0);
4157+
4158+ releasable->release ();
4159+}
4160+
4161+TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm)
4162+{
4163+ /* Locks get armed on construction */
4164+ EXPECT_CALL (*lock, lock ());
4165+
4166+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4167+
4168+ unsigned int valueMask = CWX | CWY;
4169+
4170+ /* Queue locked */
4171+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4172+
4173+ buffer->pushFrameRequest (xwc, valueMask);
4174+
4175+ /* Queue forceably unlocked, locks rearmed */
4176+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4177+ EXPECT_CALL (*lock, lock ());
4178+
4179+ /* Expect a call to XGetWindowAttributes */
4180+ EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _))
4181+ .WillOnce (
4182+ ReturnNull ());
4183+
4184+ int a, b;
4185+
4186+ EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ());
4187+}
4188+
4189+TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm)
4190+{
4191+ /* Locks get armed on construction */
4192+ EXPECT_CALL (*lock, lock ());
4193+
4194+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4195+
4196+ unsigned int valueMask = CWX | CWY;
4197+
4198+ /* Queue locked */
4199+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4200+
4201+ buffer->pushFrameRequest (xwc, valueMask);
4202+
4203+ /* Queue forceably unlocked, locks rearmed */
4204+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4205+ EXPECT_CALL (*lock, lock ());
4206+
4207+ /* Expect a call to XGetWindowAttributes */
4208+ XWindowAttributes xwa;
4209+ EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
4210+ .WillOnce (
4211+ DoAll (
4212+ SetArgReferee <0> (xwa),
4213+ Return (true)));
4214+
4215+ buffer->queryFrameAttributes (xwa);
4216+}
4217+
4218+TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm)
4219+{
4220+ /* Locks get armed on construction */
4221+ EXPECT_CALL (*lock, lock ());
4222+
4223+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4224+
4225+ unsigned int valueMask = CWX | CWY;
4226+
4227+ /* Queue locked */
4228+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4229+
4230+ buffer->pushFrameRequest (xwc, valueMask);
4231+
4232+ /* Queue forceably unlocked, locks rearmed */
4233+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4234+ EXPECT_CALL (*lock, lock ());
4235+
4236+ /* Expect a call to XGetWindowAttributes */
4237+ XWindowAttributes xwa;
4238+ EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
4239+ .WillOnce (
4240+ DoAll (
4241+ SetArgReferee <0> (xwa),
4242+ Return (true)));
4243+
4244+ buffer->queryFrameAttributes (xwa);
4245+}
4246+
4247+TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm)
4248+{
4249+ /* Locks get armed on construction */
4250+ EXPECT_CALL (*lock, lock ());
4251+
4252+ crb::Releasable::Ptr releasable (buffer->obtainLock ());
4253+
4254+ unsigned int valueMask = CWX | CWY;
4255+
4256+ /* Queue locked */
4257+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4258+
4259+ buffer->pushFrameRequest (xwc, valueMask);
4260+
4261+ /* Queue forceably unlocked, locks rearmed */
4262+ EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4263+ EXPECT_CALL (*lock, lock ());
4264+
4265+ /* Force release */
4266+ buffer->forceRelease ();
4267+}
4268+
4269
4270=== removed file 'src/tests/test_configurerequestbuffer.cpp'
4271--- src/tests/test_configurerequestbuffer.cpp 2012-12-13 14:07:01 +0000
4272+++ src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
4273@@ -1,667 +0,0 @@
4274-/*
4275- * Copyright © 2012 Sam Spilsbury
4276- *
4277- * Permission to use, copy, modify, distribute, and sell this software
4278- * and its documentation for any purpose is hereby granted without
4279- * fee, provided that the above copyright notice appear in all copies
4280- * and that both that copyright notice and this permission notice
4281- * appear in supporting documentation, and that the name of
4282- * Canonical Ltd. not be used in advertising or publicity pertaining to
4283- * distribution of the software without specific, written prior permission.
4284- * Canonical Ltd. makes no representations about the suitability of this
4285- * software for any purpose. It is provided "as is" without express or
4286- * implied warranty.
4287- *
4288- * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
4289- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
4290- * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
4291- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
4292- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4293- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
4294- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4295- *
4296- * Authored by: Sam Spilsbury <smspillaz@gmail.com>
4297- */
4298-#include <deque>
4299-#include <boost/shared_ptr.hpp>
4300-#include <boost/make_shared.hpp>
4301-#include <boost/bind.hpp>
4302-#include <gmock/gmock.h>
4303-#include <gtest/gtest.h>
4304-#include <X11/Xlib.h>
4305-
4306-#include "configurerequestbuffer-impl.h"
4307-#include "asyncserverwindow.h"
4308-
4309-namespace crb = compiz::window::configure_buffers;
4310-namespace cw = compiz::window;
4311-
4312-using testing::_;
4313-using testing::NiceMock;
4314-using testing::Return;
4315-using testing::Invoke;
4316-using testing::WithArgs;
4317-using testing::SetArgReferee;
4318-using testing::DoAll;
4319-using testing::InSequence;
4320-using testing::ReturnNull;
4321-using testing::IsNull;
4322-
4323-class MockAsyncServerWindow :
4324- public cw::AsyncServerWindow
4325-{
4326- public:
4327-
4328- MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int));
4329- MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int));
4330- MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int));
4331- MOCK_METHOD0 (sendSyntheticConfigureNotify, void ());
4332- MOCK_CONST_METHOD0 (hasCustomShape, bool ());
4333-};
4334-
4335-class MockSyncServerWindow :
4336- public cw::SyncServerWindow
4337-{
4338- public:
4339-
4340- MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &));
4341- MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &));
4342- MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *));
4343-};
4344-
4345-namespace
4346-{
4347-int REQUEST_X = 1;
4348-int REQUEST_Y = 2;
4349-int REQUEST_WIDTH = 3;
4350-int REQUEST_HEIGHT = 4;
4351-int REQUEST_BORDER = 5;
4352-
4353-Window REQUEST_ABOVE = 6;
4354-unsigned int REQUEST_MODE = 7;
4355-
4356-crb::BufferLock::Ptr
4357-CreateNormalLock (crb::CountedFreeze *cf)
4358-{
4359- return boost::make_shared <crb::ConfigureBufferLock> (cf);
4360-}
4361-
4362-}
4363-
4364-MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges")
4365-{
4366- if (vm & CWX)
4367- if (xwc.x != arg.x)
4368- return false;
4369-
4370- if (vm & CWY)
4371- if (xwc.y != arg.y)
4372- return false;
4373-
4374- if (vm & CWWidth)
4375- if (xwc.width != arg.width)
4376- return false;
4377-
4378- if (vm & CWHeight)
4379- if (xwc.height != arg.height)
4380- return false;
4381-
4382- if (vm & CWBorderWidth)
4383- if (xwc.border_width != arg.border_width)
4384- return false;
4385-
4386- if (vm & CWStackMode)
4387- if (xwc.stack_mode != arg.stack_mode)
4388- return false;
4389-
4390- if (vm & CWSibling)
4391- if (xwc.sibling != arg.sibling)
4392- return false;
4393-
4394- return true;
4395-}
4396-
4397-class ConfigureRequestBuffer :
4398- public testing::Test
4399-{
4400- public:
4401-
4402- ConfigureRequestBuffer ()
4403- {
4404- /* Initialize xwc, we control it
4405- * through the value masks */
4406- xwc.x = REQUEST_X;
4407- xwc.y = REQUEST_Y;
4408- xwc.width = REQUEST_WIDTH;
4409- xwc.height = REQUEST_HEIGHT;
4410- xwc.border_width = REQUEST_BORDER;
4411- xwc.sibling = REQUEST_ABOVE;
4412- xwc.stack_mode = REQUEST_MODE;
4413- }
4414-
4415- protected:
4416-
4417- XWindowChanges xwc;
4418- MockAsyncServerWindow asyncServerWindow;
4419- MockSyncServerWindow syncServerWindow;
4420-};
4421-
4422-class ConfigureRequestBufferDispatch :
4423- public ConfigureRequestBuffer
4424-{
4425- protected:
4426-
4427- ConfigureRequestBufferDispatch () :
4428- ConfigureRequestBuffer (),
4429- factory (boost::bind (CreateNormalLock, _1)),
4430- buffer (
4431- crb::ConfigureRequestBuffer::Create (&asyncServerWindow,
4432- &syncServerWindow,
4433- factory))
4434- {
4435- }
4436-
4437- crb::ConfigureRequestBuffer::LockFactory factory;
4438- crb::Buffer::Ptr buffer;
4439-};
4440-
4441-TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify)
4442-{
4443- EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ());
4444-
4445- buffer->pushSyntheticConfigureNotify ();
4446-}
4447-
4448-TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate)
4449-{
4450- unsigned int valueMask = CWX | CWY | CWBorderWidth |
4451- CWSibling | CWStackMode;
4452-
4453- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
4454- valueMask));
4455-
4456- buffer->pushClientRequest (xwc, valueMask);
4457-}
4458-
4459-TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate)
4460-{
4461- unsigned int valueMask = CWX | CWY | CWBorderWidth |
4462- CWSibling | CWStackMode;
4463-
4464- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
4465- valueMask));
4466-
4467- buffer->pushWrapperRequest (xwc, valueMask);
4468-}
4469-
4470-TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate)
4471-{
4472- unsigned int valueMask = CWX | CWY | CWBorderWidth |
4473- CWSibling | CWStackMode;
4474-
4475- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4476- valueMask));
4477-
4478- buffer->pushFrameRequest (xwc, valueMask);
4479-}
4480-
4481-TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked)
4482-{
4483- crb::Releasable::Ptr lock (buffer->obtainLock ());
4484-
4485- unsigned int valueMask = 0;
4486-
4487- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4488-
4489- buffer->pushFrameRequest (xwc, valueMask);
4490-}
4491-
4492-TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked)
4493-{
4494- crb::Releasable::Ptr lock (buffer->obtainLock ());
4495-
4496- unsigned int valueMask = CWX;
4497-
4498- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4499-
4500- buffer->pushFrameRequest (xwc, valueMask);
4501-
4502- valueMask |= CWY;
4503-
4504- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4505-
4506- buffer->pushFrameRequest (xwc, valueMask);
4507-
4508- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4509- valueMask));
4510-
4511- lock->release ();
4512-}
4513-
4514-/*
4515- * This test is disabled until we can expose the QueryShapeRectangles API
4516- * to plugins
4517- */
4518-TEST_F (ConfigureRequestBufferDispatch, DISABLED_PushUpdateLockedReleaseInOrder)
4519-{
4520- crb::Releasable::Ptr lock (buffer->obtainLock ());
4521-
4522- unsigned int valueMask = CWX | CWY;
4523-
4524- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4525- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0);
4526- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0);
4527-
4528- buffer->pushClientRequest (xwc, valueMask);
4529- buffer->pushWrapperRequest (xwc, 0);
4530- buffer->pushFrameRequest (xwc, 0);
4531-
4532- InSequence s;
4533-
4534- /* Always frame -> wrapper -> client */
4535- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4536- valueMask));
4537- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
4538- valueMask));
4539- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
4540- valueMask));
4541-
4542- lock->release ();
4543-}
4544-
4545-TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer)
4546-{
4547- crb::Releasable::Ptr lock (buffer->obtainLock ());
4548-
4549- unsigned int valueMask = CWX | CWY;
4550-
4551- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4552-
4553- buffer->pushFrameRequest (xwc, valueMask);
4554-
4555- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4556- valueMask));
4557-
4558- lock->release ();
4559-}
4560-
4561-TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer)
4562-{
4563- crb::Releasable::Ptr lock (buffer->obtainLock ());
4564-
4565- unsigned int valueMask = CWX | CWY;
4566-
4567- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4568-
4569- buffer->pushFrameRequest (xwc, valueMask);
4570-
4571- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4572- valueMask));
4573-}
4574-
4575-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack)
4576-{
4577- crb::Releasable::Ptr lock (buffer->obtainLock ());
4578-
4579- unsigned int valueMask = CWStackMode | CWSibling;
4580-
4581- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4582- valueMask));
4583-
4584- buffer->pushFrameRequest (xwc, valueMask);
4585-}
4586-
4587-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWindowSizeChange)
4588-{
4589- crb::Releasable::Ptr lock (buffer->obtainLock ());
4590-
4591- unsigned int valueMask = CWWidth | CWHeight | CWBorderWidth;
4592-
4593- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
4594- valueMask));
4595-
4596- buffer->pushFrameRequest (xwc, valueMask);
4597-}
4598-
4599-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnClientReposition)
4600-{
4601- crb::Releasable::Ptr lock (buffer->obtainLock ());
4602-
4603- unsigned int valueMask = CWX | CWY;
4604-
4605- EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
4606- valueMask));
4607-
4608- buffer->pushClientRequest (xwc, valueMask);
4609-}
4610-
4611-TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWrapperReposition)
4612-{
4613- crb::Releasable::Ptr lock (buffer->obtainLock ());
4614-
4615- unsigned int valueMask = CWX | CWY;
4616-
4617- EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
4618- valueMask));
4619-
4620- buffer->pushWrapperRequest (xwc, valueMask);
4621-}
4622-
4623-namespace
4624-{
4625-class MockLock :
4626- public crb::BufferLock
4627-{
4628- public:
4629-
4630- /* We're currently importing the locks statefulness and coupling
4631- * the caller with that */
4632- MockLock () :
4633- armed (false)
4634- {
4635- ON_CALL (*this, lock ()).WillByDefault (
4636- Invoke (this, &MockLock::FreezeIfUnarmed));
4637- ON_CALL (*this, release ()).WillByDefault (
4638- Invoke (this, &MockLock::ReleaseIfArmed));
4639- }
4640-
4641- void OperateOver (crb::CountedFreeze *cf)
4642- {
4643- countedFreeze = cf;
4644- }
4645-
4646- void FreezeIfUnarmed ()
4647- {
4648- if (!armed)
4649- {
4650- countedFreeze->freeze ();
4651- armed = true;
4652- }
4653- }
4654-
4655- void ReleaseIfArmed ()
4656- {
4657- if (armed)
4658- {
4659- countedFreeze->release ();
4660- armed = false;
4661- }
4662- }
4663-
4664- typedef boost::shared_ptr <MockLock> Ptr;
4665-
4666- MOCK_METHOD0 (lock, void ());
4667- MOCK_METHOD0 (release, void ());
4668-
4669- private:
4670-
4671- crb::CountedFreeze *countedFreeze;
4672- bool armed;
4673-};
4674-
4675-class MockLockFactory
4676-{
4677- public:
4678-
4679- crb::BufferLock::Ptr
4680- CreateMockLock (crb::CountedFreeze *cf)
4681- {
4682- MockLock::Ptr mockLock (locks.front ());
4683- mockLock->OperateOver (cf);
4684-
4685- locks.pop_front ();
4686-
4687- return mockLock;
4688- }
4689-
4690- void
4691- QueueLockForCreation (const MockLock::Ptr &lock)
4692- {
4693- locks.push_back (lock);
4694- }
4695-
4696- private:
4697-
4698- std::deque <MockLock::Ptr> locks;
4699-};
4700-}
4701-
4702-class ConfigureRequestBufferLockBehaviour :
4703- public ConfigureRequestBuffer
4704-{
4705- public:
4706-
4707- ConfigureRequestBufferLockBehaviour () :
4708- ConfigureRequestBuffer (),
4709- lock (boost::make_shared <MockLock> ()),
4710- factory (
4711- boost::bind (&MockLockFactory::CreateMockLock,
4712- &mockLockFactory,
4713- _1)),
4714- buffer (
4715- crb::ConfigureRequestBuffer::Create (
4716- &asyncServerWindow,
4717- &syncServerWindow,
4718- factory))
4719-
4720- {
4721- mockLockFactory.QueueLockForCreation (lock);
4722- }
4723-
4724- protected:
4725-
4726- typedef NiceMock <MockAsyncServerWindow> NiceServerWindow;
4727- typedef crb::ConfigureRequestBuffer::LockFactory LockFactory;
4728-
4729- MockLock::Ptr lock;
4730- MockLockFactory mockLockFactory;
4731-
4732- LockFactory factory;
4733- crb::Buffer::Ptr buffer;
4734-};
4735-
4736-TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease)
4737-{
4738- EXPECT_CALL (*lock, lock ());
4739- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4740-
4741- unsigned int valueMask = CWX | CWY;
4742-
4743- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4744-
4745- buffer->pushFrameRequest (xwc, valueMask);
4746-
4747- /* We are releasing this lock */
4748- EXPECT_CALL (*lock, release ());
4749-
4750- /* Now the buffer will dispatch is configure request */
4751- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4752-
4753- /* Rearm locks on release */
4754- EXPECT_CALL (*lock, lock ());
4755-
4756- /* Directly release the queue */
4757- releasable->release ();
4758-}
4759-
4760-TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired)
4761-{
4762- /* Locks get armed on construction */
4763- EXPECT_CALL (*lock, lock ());
4764- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4765-
4766- /* No call to requestConfigureOnFrame if there's nothing to be configured */
4767- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4768-
4769- /* We are releasing this lock */
4770- EXPECT_CALL (*lock, release ());
4771-
4772- /* No rearm - we haven't released the whole buffer */
4773- EXPECT_CALL (*lock, lock ()).Times (0);
4774-
4775- /* Directly release the queue */
4776- releasable->release ();
4777-}
4778-
4779-TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady)
4780-{
4781- /* Locks get armed on construction */
4782- EXPECT_CALL (*lock, lock ());
4783- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4784-
4785- /* We are releasing this lock */
4786- EXPECT_CALL (*lock, release ());
4787-
4788- /* No call to requestConfigureOnFrame if there's nothing to be configured */
4789- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4790-
4791- /* No rearm - we haven't released it */
4792- EXPECT_CALL (*lock, lock ()).Times (0);
4793-
4794- /* Directly release the queue */
4795- releasable->release ();
4796-
4797- /* Since we're now going to push something to a queue
4798- * that's effectively not locked, the locks should now
4799- * be released */
4800- unsigned int valueMask = CWX | CWY;
4801-
4802- /* Now rearm it */
4803- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4804- EXPECT_CALL (*lock, lock ());
4805-
4806- buffer->pushFrameRequest (xwc, valueMask);
4807-}
4808-
4809-TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease)
4810-{
4811- MockLock::Ptr second (boost::make_shared <MockLock> ());
4812- mockLockFactory.QueueLockForCreation (second);
4813-
4814- /* Locks get armed on construction */
4815- EXPECT_CALL (*lock, lock ());
4816- EXPECT_CALL (*second, lock ());
4817-
4818- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4819- crb::Releasable::Ptr otherReleasable (buffer->obtainLock ());
4820-
4821- /* We are releasing this lock */
4822- EXPECT_CALL (*lock, release ());
4823-
4824- /* No call to requestConfigureOnFrame if there's nothing to be configured */
4825- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4826-
4827- /* No rearm - we haven't released it */
4828- EXPECT_CALL (*lock, lock ()).Times (0);
4829-
4830- releasable->release ();
4831-}
4832-
4833-TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm)
4834-{
4835- /* Locks get armed on construction */
4836- EXPECT_CALL (*lock, lock ());
4837-
4838- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4839-
4840- unsigned int valueMask = CWX | CWY;
4841-
4842- /* Queue locked */
4843- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4844-
4845- buffer->pushFrameRequest (xwc, valueMask);
4846-
4847- /* Queue forceably unlocked, locks rearmed */
4848- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4849- EXPECT_CALL (*lock, lock ());
4850-
4851- /* Expect a call to XGetWindowAttributes */
4852- EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _))
4853- .WillOnce (
4854- ReturnNull ());
4855-
4856- int a, b;
4857-
4858- EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ());
4859-}
4860-
4861-TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm)
4862-{
4863- /* Locks get armed on construction */
4864- EXPECT_CALL (*lock, lock ());
4865-
4866- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4867-
4868- unsigned int valueMask = CWX | CWY;
4869-
4870- /* Queue locked */
4871- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4872-
4873- buffer->pushFrameRequest (xwc, valueMask);
4874-
4875- /* Queue forceably unlocked, locks rearmed */
4876- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4877- EXPECT_CALL (*lock, lock ());
4878-
4879- /* Expect a call to XGetWindowAttributes */
4880- XWindowAttributes xwa;
4881- EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
4882- .WillOnce (
4883- DoAll (
4884- SetArgReferee <0> (xwa),
4885- Return (true)));
4886-
4887- buffer->queryFrameAttributes (xwa);
4888-}
4889-
4890-TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm)
4891-{
4892- /* Locks get armed on construction */
4893- EXPECT_CALL (*lock, lock ());
4894-
4895- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4896-
4897- unsigned int valueMask = CWX | CWY;
4898-
4899- /* Queue locked */
4900- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4901-
4902- buffer->pushFrameRequest (xwc, valueMask);
4903-
4904- /* Queue forceably unlocked, locks rearmed */
4905- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4906- EXPECT_CALL (*lock, lock ());
4907-
4908- /* Expect a call to XGetWindowAttributes */
4909- XWindowAttributes xwa;
4910- EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
4911- .WillOnce (
4912- DoAll (
4913- SetArgReferee <0> (xwa),
4914- Return (true)));
4915-
4916- buffer->queryFrameAttributes (xwa);
4917-}
4918-
4919-TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm)
4920-{
4921- /* Locks get armed on construction */
4922- EXPECT_CALL (*lock, lock ());
4923-
4924- crb::Releasable::Ptr releasable (buffer->obtainLock ());
4925-
4926- unsigned int valueMask = CWX | CWY;
4927-
4928- /* Queue locked */
4929- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
4930-
4931- buffer->pushFrameRequest (xwc, valueMask);
4932-
4933- /* Queue forceably unlocked, locks rearmed */
4934- EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
4935- EXPECT_CALL (*lock, lock ());
4936-
4937- /* Force release */
4938- buffer->forceRelease ();
4939-}
4940-

Subscribers

People subscribed via source and target branches