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
=== added file 'include/core/configurerequestbuffer.h'
--- include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000
+++ include/core/configurerequestbuffer.h 2013-02-28 02:29:22 +0000
@@ -0,0 +1,73 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
26#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
27
28#include <boost/shared_ptr.hpp>
29#include <X11/Xlib.h>
30#include <syncserverwindow.h>
31
32namespace compiz
33{
34namespace window
35{
36namespace configure_buffers
37{
38class Releasable
39{
40 public:
41
42 typedef boost::shared_ptr <Releasable> Ptr;
43
44 virtual void release () = 0;
45};
46
47class Buffer :
48 public SyncServerWindow
49{
50 public:
51
52 typedef boost::shared_ptr <Buffer> Ptr;
53
54 virtual ~Buffer () {}
55
56 virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
57 virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
58 virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
59
60 virtual void pushSyntheticConfigureNotify () = 0;
61
62 virtual Releasable::Ptr obtainLock () = 0;
63
64 /* This API will all configure requests to be
65 * released. It should only be used in situations
66 * where you have a server grab and need
67 * to have complete sync with the server */
68 virtual void forceRelease () = 0;
69};
70}
71}
72}
73#endif
074
=== removed file 'include/core/configurerequestbuffer.h'
--- include/core/configurerequestbuffer.h 2012-12-13 11:12:32 +0000
+++ include/core/configurerequestbuffer.h 1970-01-01 00:00:00 +0000
@@ -1,73 +0,0 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
26#define _COMPIZ_CONFIGURE_REQUEST_BUFFER_H
27
28#include <boost/shared_ptr.hpp>
29#include <X11/Xlib.h>
30#include <syncserverwindow.h>
31
32namespace compiz
33{
34namespace window
35{
36namespace configure_buffers
37{
38class Releasable
39{
40 public:
41
42 typedef boost::shared_ptr <Releasable> Ptr;
43
44 virtual void release () = 0;
45};
46
47class Buffer :
48 public SyncServerWindow
49{
50 public:
51
52 typedef boost::shared_ptr <Buffer> Ptr;
53
54 virtual ~Buffer () {}
55
56 virtual void pushClientRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
57 virtual void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
58 virtual void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask) = 0;
59
60 virtual void pushSyntheticConfigureNotify () = 0;
61
62 virtual Releasable::Ptr obtainLock () = 0;
63
64 /* This API will all configure requests to be
65 * released. It should only be used in situations
66 * where you have a server grab and need
67 * to have complete sync with the server */
68 virtual void forceRelease () = 0;
69};
70}
71}
72}
73#endif
740
=== modified file 'plugins/opengl/CMakeLists.txt'
--- plugins/opengl/CMakeLists.txt 2012-12-12 07:33:12 +0000
+++ plugins/opengl/CMakeLists.txt 2013-02-28 02:29:22 +0000
@@ -5,15 +5,21 @@
5set (INTERNAL_LIBRARIES5set (INTERNAL_LIBRARIES
6 compiz_opengl_double_buffer6 compiz_opengl_double_buffer
7 compiz_opengl_fsregion7 compiz_opengl_fsregion
8 compiz_opengl_framebuffer_direct_draw
8 compiz_opengl_blacklist9 compiz_opengl_blacklist
9 compiz_opengl_glx_tfp_bind10 compiz_opengl_glx_tfp_bind
10)11)
1112
13set (COMPIZ_OPENGL_PLUGIN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
14set (COMPIZ_OPENGL_PLUGIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
15
12add_subdirectory (src/doublebuffer)16add_subdirectory (src/doublebuffer)
13add_subdirectory (src/fsregion)17add_subdirectory (src/fsregion)
18add_subdirectory (src/fbdirectdraw)
14add_subdirectory (src/blacklist)19add_subdirectory (src/blacklist)
15add_subdirectory (src/glxtfpbind)20add_subdirectory (src/glxtfpbind)
1621
22include_directories (src/fbdirectdraw/include)
17include_directories (src/glxtfpbind/include)23include_directories (src/glxtfpbind/include)
1824
19if (USE_GLES)25if (USE_GLES)
2026
=== modified file 'plugins/opengl/include/opengl/framebufferobject.h'
--- plugins/opengl/include/opengl/framebufferobject.h 2012-08-09 02:19:26 +0000
+++ plugins/opengl/include/opengl/framebufferobject.h 2013-02-28 02:29:22 +0000
@@ -26,29 +26,177 @@
26#ifndef _COMPIZ_GLFRAMEBUFFEROBJECT_H26#ifndef _COMPIZ_GLFRAMEBUFFEROBJECT_H
27#define _COMPIZ_GLFRAMEBUFFEROBJECT_H27#define _COMPIZ_GLFRAMEBUFFEROBJECT_H
2828
29#include <opengl/opengl.h>29#include <list>
30#include <boost/function.hpp>
31#include <opengl/opengl-api.h>
32#include <core/size.h>
33#include <core/rect.h>
34
35class GLVertexBuffer;
36class GLTexture;
37
38namespace compiz
39{
40namespace opengl
41{
42typedef enum _BlitMask
43{
44 ColorData = (1 << 0),
45 StencilData = (1 << 1)
46} BlitMask;
47
48typedef enum _Filter
49{
50 Fast = 0,
51 Good = 1,
52} Filter;
53
54typedef enum _BindPoint
55{
56 Read = 0,
57 Draw = 1
58} BindPoint;
59
60class BindableFramebuffer
61{
62 public:
63
64 virtual ~BindableFramebuffer () {}
65
66 virtual GLuint getResourceId () const = 0;
67 virtual bool setBindStatus (GLenum) = 0;
68 virtual void updateAllocation (GLenum) = 0;
69};
70
71class BindLocation
72{
73 public:
74
75 virtual ~BindLocation () {}
76
77 /**
78 * Bind the specified BindableFramebuffer to this bind location
79 * usually either as the read target or the draw target
80 *
81 * The previous FBO is no longer bound. If it was bound to the
82 * draw target, it will be safe to use its texture.
83 *
84 * This returns the last-bound BindableFramebuffer object on
85 * success and NULL on failure (no change). Call this again
86 * in order to restore that framebuffer
87 */
88 virtual BindableFramebuffer * bind (BindableFramebuffer *) = 0;
89 virtual BindableFramebuffer * getCurrentlyBound () = 0;
90};
91
92typedef boost::function <bool (const CompRect &src,
93 const CompRect &dst,
94 GLbitfield mask,
95 GLenum filter)> RectangularDraw;
96typedef std::list <RectangularDraw> RectangularDrawList;
97
98class DirectDrawStrategies
99{
100 public:
101
102 typedef boost::shared_ptr <DirectDrawStrategies> Ptr;
103
104 virtual ~DirectDrawStrategies () {}
105 virtual void draw (const CompRect &src,
106 const CompRect &dst,
107 BlitMask mask,
108 Filter filter) = 0;
109};
110
111class FramebufferObject
112{
113 public:
114
115 virtual ~FramebufferObject () {}
116
117 /**
118 * Ensure the texture is of the given size, recreating it if needed,
119 * and replace the FBO color attachment with it. The texture contents
120 * become undefined, unless specified in the 'image' argument.
121 * When specifying 'image', it's also possible to pass-in the
122 * desired image's 'format' and 'type'.
123 *
124 * Returns true on success, and false on texture allocation failure.
125 */
126 virtual bool allocate (const CompSize &size,
127 const char *image = NULL,
128 GLenum format = GL_RGBA,
129 GLenum type = GL_UNSIGNED_BYTE) = 0;
130
131 /**
132 * Check the FBO completeness. Returns true on complete.
133 * Otherwise returns false and reports the error to log.
134 */
135 virtual bool checkStatus () = 0;
136
137 /**
138 * Return a pointer to the texture that is the color attachment.
139 * This will return NULL, if allocate () has not been called, or
140 * the last allocate () call failed.
141 */
142 virtual GLTexture * tex () = 0;
143};
144
145class DirectDrawObject :
146 virtual public compiz::opengl::FramebufferObject,
147 virtual public compiz::opengl::BindableFramebuffer
148{
149 public:
150
151 virtual ~DirectDrawObject () {};
152
153 /**
154 * Draws a region of the framebuffer object as specified in
155 * framebuffer-specified co-ordinates as @src co-ordinates in
156 * the buffer currently bound co-ordinates @dst . @mask indicates
157 * what kind of data should be propogated downwards. @filter indicates
158 * what kind of filter should be used when drawing this buffer
159 *
160 * This since this code only draws a rectangular region from one
161 * framebuffer to another, it will try and use the fastest codepath
162 * possible, falling back to a simple textured draw if
163 * glBlitFramebuffer is not available
164 *
165 */
166 virtual void directDraw (const CompRect &src,
167 const CompRect &dst,
168 compiz::opengl::BlitMask mask,
169 compiz::opengl::Filter filter) = 0;
170};
171
172namespace impl
173{
174namespace cgl = compiz::opengl;
30175
31struct PrivateGLFramebufferObject;176struct PrivateGLFramebufferObject;
32177
33/**178class FBOBindLocation :
34 * Class representing a framebuffer object in GL, supporting only one179 public cgl::BindLocation
35 * color attachment as per GLES 2 spec. The color attachment is referred180{
36 * to as the texture (of the FBO).181 public:
37 *182
38 * Usage:183 FBOBindLocation (GLenum binding, BindableFramebuffer *back);
39 * 1. create a GLFramebufferObject (requires a GL context)184 BindableFramebuffer * bind (BindableFramebuffer *);
40 * 2. call allocate (size), and check status ()185 BindableFramebuffer * getCurrentlyBound ();
41 * 3. old = bind ()186
42 * 4. do your rendering187 private:
43 * 5. rebind (old)188
44 * 6. use the rendered texture via tex ()189 class Private;
45 * 7. go to 2 or 3, or delete to quit (requires a GL context)190 std::auto_ptr <Private> priv;
46 */191};
47class GLFramebufferObject192
48{193class FramebufferObject :
49 public:194 public cgl::FramebufferObject,
50 GLFramebufferObject ();195 public cgl::BindableFramebuffer
51 ~GLFramebufferObject ();196{
197 public:
198 FramebufferObject ();
199 ~FramebufferObject ();
52200
53 /**201 /**
54 * Ensure the texture is of the given size, recreating it if needed,202 * Ensure the texture is of the given size, recreating it if needed,
@@ -65,26 +213,6 @@
65 GLenum type = GL_UNSIGNED_BYTE);213 GLenum type = GL_UNSIGNED_BYTE);
66214
67 /**215 /**
68 * Bind this as the current FBO, previous binding in GL context is
69 * undone. GL rendering is now targeted to this FBO.
70 * Returns a pointer to the previously bound FBO, or NULL if
71 * the previous binding was zero (the window system provided
72 * framebuffer).
73 *
74 * The previous FBO is no longer bound, so you can use its
75 * texture. To restore the previous FBO, call rebind (FBO) with
76 * the returned pointer as the argument.
77 */
78 GLFramebufferObject *bind ();
79
80 /**
81 * Bind the given FBO as the current FBO, without looking up the
82 * previous binding. The argument can be NULL, in which case the
83 * window system provided framebuffer gets bound (FBO is unbound).
84 */
85 static void rebind (GLFramebufferObject *fbo);
86
87 /**
88 * Check the FBO completeness. Returns true on complete.216 * Check the FBO completeness. Returns true on complete.
89 * Otherwise returns false and reports the error to log.217 * Otherwise returns false and reports the error to log.
90 */218 */
@@ -95,10 +223,23 @@
95 * This will return NULL, if allocate () has not been called, or223 * This will return NULL, if allocate () has not been called, or
96 * the last allocate () call failed.224 * the last allocate () call failed.
97 */225 */
98 GLTexture *tex ();226 GLTexture * tex ();
99227
100 private:228 private:
229
230 /**
231 * Returns the framebuffer identifier
232 */
233 GLuint getResourceId () const;
234 bool setBindStatus (GLenum);
235 void updateAllocation (GLenum bindingLocation);
236
101 PrivateGLFramebufferObject *priv;237 PrivateGLFramebufferObject *priv;
102};238};
239}
240}
241}
242
243typedef compiz::opengl::impl::FramebufferObject GLFramebufferObject;
103244
104#endif // _COMPIZ_GLFRAMEBUFFEROBJECT_H245#endif // _COMPIZ_GLFRAMEBUFFEROBJECT_H
105246
=== added file 'plugins/opengl/include/opengl/opengl-api.h'
--- plugins/opengl/include/opengl/opengl-api.h 1970-01-01 00:00:00 +0000
+++ plugins/opengl/include/opengl/opengl-api.h 2013-02-28 02:29:22 +0000
@@ -0,0 +1,42 @@
1/*
2 * Copyright © 2008 Dennis Kasprzyk
3 * Copyright © 2007 Novell, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without
7 * fee, provided that the above copyright notice appear in all copies
8 * and that both that copyright notice and this permission notice
9 * appear in supporting documentation, and that the name of
10 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
11 * distribution of the software without specific, written prior permission.
12 * Dennis Kasprzyk makes no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without express or
14 * implied warranty.
15 *
16 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
22 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
25 * David Reveman <davidr@novell.com>
26 */
27
28#ifndef _COMPIZ_OPENGL_API_H
29#define _COMPIZ_OPENGL_API_H
30
31#ifdef USE_GLES
32#define SUPPORT_X11
33#include <GLES2/gl2.h>
34#include <GLES2/gl2ext.h>
35#include <EGL/egl.h>
36#include <EGL/eglext.h>
37#else
38#include <GL/gl.h>
39#include <GL/glx.h>
40#endif
41
42#endif
043
=== modified file 'plugins/opengl/include/opengl/opengl.h'
--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
+++ plugins/opengl/include/opengl/opengl.h 2013-02-28 02:29:22 +0000
@@ -28,29 +28,19 @@
28#ifndef _COMPIZ_OPENGL_H28#ifndef _COMPIZ_OPENGL_H
29#define _COMPIZ_OPENGL_H29#define _COMPIZ_OPENGL_H
3030
31#ifdef USE_GLES31#include <opengl/opengl-api.h>
32#define SUPPORT_X11
33#include <GLES2/gl2.h>
34#include <GLES2/gl2ext.h>
35#include <EGL/egl.h>
36#include <EGL/eglext.h>
37#else
38#include <GL/gl.h>
39#include <GL/glx.h>
40#endif
4132
42#include <core/size.h>33#include <core/size.h>
43#include <core/pluginclasshandler.h>34#include <core/pluginclasshandler.h>
4435
45#include <opengl/matrix.h>36#include <opengl/matrix.h>
46#include <opengl/texture.h>37#include <opengl/texture.h>
47#include <opengl/framebufferobject.h>
48#include <opengl/vertexbuffer.h>38#include <opengl/vertexbuffer.h>
49#include <opengl/program.h>39#include <opengl/program.h>
50#include <opengl/programcache.h>40#include <opengl/programcache.h>
51#include <opengl/shadercache.h>41#include <opengl/shadercache.h>
5242
53#define COMPIZ_OPENGL_ABI 643#define COMPIZ_OPENGL_ABI 7
5444
55/*45/*
56 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but46 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
@@ -84,9 +74,38 @@
84extern const float GREEN_SATURATION_WEIGHT;74extern const float GREEN_SATURATION_WEIGHT;
85extern const float BLUE_SATURATION_WEIGHT;75extern const float BLUE_SATURATION_WEIGHT;
8676
77class GLScreen;
87class PrivateGLScreen;78class PrivateGLScreen;
88class PrivateGLWindow;79class PrivateGLWindow;
8980
81namespace compiz
82{
83namespace opengl
84{
85typedef boost::function <bool (const CompRect &src,
86 const CompRect &dst,
87 GLbitfield mask,
88 GLenum filter)> BlitFramebufferFunc;
89
90class DirectDrawObject;
91class FramebufferObject;
92class BindableFramebuffer;
93
94/**
95 * Convenience method to construct a framebuffer object that
96 * supports GLX_EXT_blit_framebuffer and a fallback path
97 */
98DirectDrawObject *createBlittableFramebufferObjectWithFallback(const CompSize &sz, GLScreen *gScreen);
99
100namespace impl
101{
102class FramebufferObject;
103}
104}
105}
106
107typedef compiz::opengl::impl::FramebufferObject GLFramebufferObject;
108
90extern GLushort defaultColor[4];109extern GLushort defaultColor[4];
91110
92#ifndef GLX_EXT_texture_from_pixmap111#ifndef GLX_EXT_texture_from_pixmap
@@ -313,6 +332,18 @@
313 GLsizei width,332 GLsizei width,
314 GLsizei height);333 GLsizei height);
315334
335 /* GLX_EXT_blit_framebuffer */
336 typedef void (*GLBlitFramebufferProc) (GLint srcX0,
337 GLint srcY0,
338 GLint srcX1,
339 GLint srcY1,
340 GLint dstX0,
341 GLint dstY0,
342 GLint dstX1,
343 GLint dstY1,
344 GLbitfield mask,
345 GLenum filter);
346
316347
317 /* GL_ARB_shader_objects */348 /* GL_ARB_shader_objects */
318 #ifndef USE_GLES349 #ifndef USE_GLES
@@ -413,11 +444,12 @@
413 extern GLDisableVertexAttribArrayProc disableVertexAttribArray;444 extern GLDisableVertexAttribArrayProc disableVertexAttribArray;
414 extern GLVertexAttribPointerProc vertexAttribPointer;445 extern GLVertexAttribPointerProc vertexAttribPointer;
415446
416 extern GLGenRenderbuffersProc genRenderbuffers;447 extern GLGenRenderbuffersProc genRenderbuffers;
417 extern GLDeleteRenderbuffersProc deleteRenderbuffers;448 extern GLDeleteRenderbuffersProc deleteRenderbuffers;
418 extern GLBindRenderbufferProc bindRenderbuffer;449 extern GLBindRenderbufferProc bindRenderbuffer;
419 extern GLFramebufferRenderbufferProc framebufferRenderbuffer;450 extern GLFramebufferRenderbufferProc framebufferRenderbuffer;
420 extern GLRenderbufferStorageProc renderbufferStorage;451 extern GLRenderbufferStorageProc renderbufferStorage;
452 extern GLBlitFramebufferProc blitFramebuffer;
421453
422 #ifndef USE_GLES454 #ifndef USE_GLES
423 extern GLCreateShaderObjectARBProc createShaderObjectARB;455 extern GLCreateShaderObjectARBProc createShaderObjectARB;
@@ -579,7 +611,6 @@
579extern GLScreenPaintAttrib defaultScreenPaintAttrib;611extern GLScreenPaintAttrib defaultScreenPaintAttrib;
580612
581class GLScreen;613class GLScreen;
582class GLFramebufferObject;
583class GLScreenInterface;614class GLScreenInterface;
584extern template class WrapableInterface<GLScreen, GLScreenInterface>;615extern template class WrapableInterface<GLScreen, GLScreenInterface>;
585616
@@ -658,9 +689,9 @@
658 * @param scratchFbo Describes the final composited FBO that is689 * @param scratchFbo Describes the final composited FBO that is
659 * to be rendered.690 * to be rendered.
660 */691 */
661 virtual void glPaintCompositedOutput (const CompRegion &region,692 virtual void glPaintCompositedOutput (const CompRegion &region,
662 GLFramebufferObject *fbo,693 compiz::opengl::DirectDrawObject *fbo,
663 unsigned int mask);694 unsigned int mask);
664695
665 /**696 /**
666 * Hookable function used by plugins to determine stenciling mask697 * Hookable function used by plugins to determine stenciling mask
@@ -759,13 +790,42 @@
759 /**790 /**
760 * Returns the FBO compiz is using for the screen791 * Returns the FBO compiz is using for the screen
761 */792 */
762 GLFramebufferObject *fbo ();793 compiz::opengl::FramebufferObject * fbo ();
794
795 /**
796 * Binds a framebuffer for drawing, returns the old bindable
797 */
798 compiz::opengl::BindableFramebuffer *
799 bindFramebufferForDrawing (compiz::opengl::BindableFramebuffer *);
800
801 /**
802 * Binds a framebuffer for reading, returns the old reading
803 */
804 compiz::opengl::BindableFramebuffer *
805 bindFramebufferForReading (compiz::opengl::BindableFramebuffer *);
806
807 /**
808 * Gets the currently bound draw framebuffer
809 */
810 compiz::opengl::BindableFramebuffer *
811 drawFramebuffer ();
812
813 /**
814 * Gets the backbuffer as a BindableFramebuffer
815 */
816 compiz::opengl::BindableFramebuffer *
817 backbuffer ();
763818
764 /**819 /**
765 * Returns a default icon texture820 * Returns a default icon texture
766 */821 */
767 GLTexture *defaultIcon ();822 GLTexture *defaultIcon ();
768823
824 /**
825 * Returns the current framebuffer function for blitting the framebuffer
826 */
827 const compiz::opengl::BlitFramebufferFunc & blitFramebufferFunc ();
828
769 void resetRasterPos ();829 void resetRasterPos ();
770830
771 bool glInitContext (XVisualInfo *);831 bool glInitContext (XVisualInfo *);
@@ -786,7 +846,7 @@
786846
787 WRAPABLE_HND (5, GLScreenInterface, GLMatrix *, projectionMatrix);847 WRAPABLE_HND (5, GLScreenInterface, GLMatrix *, projectionMatrix);
788 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,848 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
789 const CompRegion &, GLFramebufferObject *, unsigned int);849 const CompRegion &, compiz::opengl::DirectDrawObject *, unsigned int);
790850
791 WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,851 WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
792 GLVertexBuffer &,852 GLVertexBuffer &,
793853
=== added directory 'plugins/opengl/src/fbdirectdraw'
=== added file 'plugins/opengl/src/fbdirectdraw/CMakeLists.txt'
--- plugins/opengl/src/fbdirectdraw/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/fbdirectdraw/CMakeLists.txt 2013-02-28 02:29:22 +0000
@@ -0,0 +1,32 @@
1INCLUDE_DIRECTORIES (
2 ${COMPIZ_OPENGL_PLUGIN_SOURCE_DIR}
3 ${COMPIZ_OPENGL_PLUGIN_INCLUDE_DIR}
4 ${CMAKE_CURRENT_SOURCE_DIR}/include
5 ${CMAKE_CURRENT_SOURCE_DIR}/src
6
7 ${Boost_INCLUDE_DIRS}
8)
9
10LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
11
12SET(
13 SRCS
14 ${CMAKE_CURRENT_SOURCE_DIR}/src/framebuffer-direct-draw.cpp
15)
16
17ADD_LIBRARY(
18 compiz_opengl_framebuffer_direct_draw STATIC
19
20 ${SRCS}
21)
22
23if (COMPIZ_BUILD_TESTING)
24ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
25endif (COMPIZ_BUILD_TESTING)
26
27TARGET_LINK_LIBRARIES(
28 compiz_opengl_framebuffer_direct_draw
29
30 compiz_region
31 compiz_logmessage
32)
033
=== added directory 'plugins/opengl/src/fbdirectdraw/include'
=== added file 'plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h'
--- plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h 2013-02-28 02:29:22 +0000
@@ -0,0 +1,111 @@
1/*
2 * Compiz, opengl plugin, FramebufferDirectDraw class
3 *
4 * Copyright (c) 2012 Canonical Ltd.
5 * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#ifndef _COMPIZ_OPENGL_FRAMEBUFFER_DIRECT_DRAW_H
26#define _COMPIZ_OPENGL_FRAMEBUFFER_DIRECT_DRAW_H
27
28#include <memory>
29#include <boost/shared_ptr.hpp>
30#include <core/rect.h>
31#include <opengl/framebufferobject.h>
32
33class GLVertexBuffer;
34
35namespace compiz
36{
37namespace opengl
38{
39namespace impl
40{
41namespace cglfb = compiz::opengl;
42
43class PrivateDirectDrawStrategies;
44
45class DirectDrawStrategies :
46 public cglfb::DirectDrawStrategies
47{
48 public:
49
50 typedef boost::shared_ptr <DirectDrawStrategies> Ptr;
51
52 DirectDrawStrategies (const RectangularDrawList &strategies);
53
54 void draw (const CompRect &src,
55 const CompRect &dst,
56 BlitMask mask,
57 Filter filter);
58
59 private:
60
61 std::auto_ptr <PrivateDirectDrawStrategies> priv;
62};
63
64class PrivateDirectDrawObject;
65
66class DirectDrawObject :
67 virtual public cglfb::FramebufferObject,
68 public cglfb::DirectDrawObject
69{
70 public:
71
72 DirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &,
73 const boost::shared_ptr <cglfb::FramebufferObject> &,
74 const boost::shared_ptr <cglfb::BindableFramebuffer> &);
75
76 bool allocate (const CompSize &size,
77 const char *image = NULL,
78 GLenum format = GL_RGBA,
79 GLenum type = GL_UNSIGNED_BYTE);
80 bool checkStatus ();
81 GLTexture * tex ();
82
83 void directDraw (const CompRect &src,
84 const CompRect &dst,
85 cglfb::BlitMask mask,
86 cglfb::Filter filter);
87
88 private:
89
90 GLuint getResourceId () const;
91 bool setBindStatus (GLenum);
92 void updateAllocation (GLenum);
93
94 PrivateDirectDrawObject *priv;
95};
96
97typedef boost::function <cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *)>
98 BindReadBufferFunc;
99
100bool rectangleDrawFromReadBuffer (const CompRect &src,
101 const CompRect &dst,
102 GLbitfield mask,
103 GLenum filter,
104 cglfb::BindableFramebuffer *bindable,
105 const BindReadBufferFunc &func,
106 cglfb::RectangularDraw strategy);
107}
108}
109}
110
111#endif
0112
=== added directory 'plugins/opengl/src/fbdirectdraw/src'
=== added file 'plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp'
--- plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp 2013-02-28 02:29:22 +0000
@@ -0,0 +1,177 @@
1/*
2 * Compiz, opengl plugin, DirectDrawFramebufferStrategies class
3 *
4 * Copyright (c) 2012 Canonical Ltd.
5 * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#include "framebuffer-direct-draw.h"
26
27namespace cglfb = compiz::opengl;
28namespace cglfbi = compiz::opengl::impl;
29
30class GLTexture;
31class GLVertexBuffer;
32
33namespace compiz
34{
35namespace opengl
36{
37namespace impl
38{
39class PrivateDirectDrawStrategies
40{
41 public:
42
43 PrivateDirectDrawStrategies (const cglfb::RectangularDrawList &strategies) :
44 rectDrawList (strategies)
45 {
46 }
47
48 cglfb::RectangularDrawList rectDrawList;
49};
50
51class PrivateDirectDrawObject
52{
53 public:
54
55 PrivateDirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &strategies,
56 const boost::shared_ptr <cglfb::FramebufferObject> &object,
57 const boost::shared_ptr <cglfb::BindableFramebuffer> &bindable) :
58 directDrawStrategies (strategies),
59 framebufferObject (object),
60 bindableFramebuffer (bindable)
61 {
62 };
63
64 boost::shared_ptr <cglfb::DirectDrawStrategies> directDrawStrategies;
65 boost::shared_ptr <cglfb::FramebufferObject> framebufferObject;
66 boost::shared_ptr <cglfb::BindableFramebuffer> bindableFramebuffer;
67};
68}
69}
70}
71
72cglfbi::DirectDrawObject::DirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &strategies,
73 const boost::shared_ptr <cglfb::FramebufferObject> &object,
74 const boost::shared_ptr <cglfb::BindableFramebuffer> &bindable) :
75 priv (new cglfbi::PrivateDirectDrawObject (strategies, object, bindable))
76{
77}
78
79bool
80cglfbi::DirectDrawObject::allocate (const CompSize &size, const char *image,
81 GLenum format, GLenum type)
82{
83 return priv->framebufferObject->allocate (size, image, format, type);
84}
85
86bool
87cglfbi::DirectDrawObject::checkStatus ()
88{
89 return priv->framebufferObject->checkStatus ();
90}
91
92GLTexture *
93cglfbi::DirectDrawObject::tex ()
94{
95 return priv->framebufferObject->tex ();
96}
97
98GLuint
99cglfbi::DirectDrawObject::getResourceId () const
100{
101 return priv->bindableFramebuffer->getResourceId ();
102}
103
104bool
105cglfbi::DirectDrawObject::setBindStatus (GLenum status)
106{
107 return priv->bindableFramebuffer->setBindStatus (status);
108}
109
110void
111cglfbi::DirectDrawObject::updateAllocation (GLenum bindPoint)
112{
113 return priv->bindableFramebuffer->updateAllocation (bindPoint);
114}
115
116void
117cglfbi::DirectDrawObject::directDraw (const CompRect &src,
118 const CompRect &dst,
119 cglfb::BlitMask mask,
120 cglfb::Filter filter)
121{
122 if (!checkStatus ())
123 return;
124
125 priv->directDrawStrategies->draw (src, dst, mask, filter);
126}
127
128bool
129cglfbi::rectangleDrawFromReadBuffer (const CompRect &src,
130 const CompRect &dst,
131 GLbitfield mask,
132 GLenum filter,
133 cglfb::BindableFramebuffer *bindable,
134 const cglfbi::BindReadBufferFunc &bindReadBuffer,
135 cglfb::RectangularDraw strategy)
136{
137 bool status = false;
138 /* Bind to the read framebuffer first */
139 cglfb::BindableFramebuffer *old = bindReadBuffer (bindable);
140
141 if (old)
142 status = strategy (src, dst, mask, filter);
143
144 /* Intentionally not rebinding the old one */
145
146 return status;
147}
148
149cglfbi::DirectDrawStrategies::DirectDrawStrategies (const cglfb::RectangularDrawList &strategies) :
150 priv (new cglfbi::PrivateDirectDrawStrategies (strategies))
151{
152}
153
154void
155cglfbi::DirectDrawStrategies::draw (const CompRect &src,
156 const CompRect &dst,
157 cglfb::BlitMask mask,
158 cglfb::Filter filter)
159{
160 if (!mask)
161 return;
162
163 const GLbitfield glMask = (mask & cglfb::ColorData ? GL_COLOR_BUFFER_BIT : 0) |
164 (mask & cglfb::StencilData ? GL_STENCIL_BUFFER_BIT : 0);
165 const GLenum glFilter = (filter == cglfb::Fast ? GL_NEAREST : GL_LINEAR);
166
167 while (!priv->rectDrawList.empty ())
168 {
169 const cglfb::RectangularDraw &strategy = priv->rectDrawList.back ();
170
171 /* If one method fails, try the next */
172 if (!strategy (src, dst, glMask, glFilter))
173 priv->rectDrawList.pop_back ();
174 else
175 break;
176 }
177}
0178
=== added directory 'plugins/opengl/src/fbdirectdraw/tests'
=== added file 'plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt'
--- plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt 2013-02-28 02:29:22 +0000
@@ -0,0 +1,24 @@
1find_library (GMOCK_LIBRARY gmock)
2find_library (GMOCK_MAIN_LIBRARY gmock_main)
3
4if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
5 message ("Google Mock and Google Test not found - cannot build tests!")
6 set (COMPIZ_BUILD_TESTING OFF)
7endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
8
9include_directories (${GTEST_INCLUDE_DIRS})
10
11link_directories (${COMPIZ_LIBRARY_DIRS})
12
13add_executable (compiz_test_opengl_framebuffer_direct_draw
14 ${CMAKE_CURRENT_SOURCE_DIR}/test-opengl-framebuffer-direct-draw.cpp)
15
16target_link_libraries (compiz_test_opengl_framebuffer_direct_draw
17 compiz_opengl_framebuffer_direct_draw
18 ${GTEST_BOTH_LIBRARIES}
19 ${GMOCK_LIBRARY}
20 ${GMOCK_MAIN_LIBRARY}
21 ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
22 )
23
24compiz_discover_tests (compiz_test_opengl_framebuffer_direct_draw COVERAGE compiz_opengl_framebuffer_direct_draw)
025
=== added file 'plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp'
--- plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp 2013-02-28 02:29:22 +0000
@@ -0,0 +1,237 @@
1/*
2 * Compiz, opengl plugin, DirectDrawFramebufferStrategies class
3 *
4 * Copyright (c) 2012 Canonical Ltd.
5 * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#include <memory>
26#include <boost/function.hpp>
27#include <boost/bind.hpp>
28#include <gtest/gtest.h>
29#include <gmock/gmock.h>
30#include <opengl/opengl-api.h>
31#include <opengl/framebufferobject.h>
32#include "framebuffer-direct-draw.h"
33
34using ::testing::Return;
35using ::testing::_;
36using ::testing::Expectation;
37using ::testing::StrictMock;
38using ::testing::NiceMock;
39using ::testing::ReturnNull;
40
41namespace cglfb = compiz::opengl;
42namespace cglfbi = compiz::opengl::impl;
43
44namespace
45{
46class MockDrawStrategy
47{
48 public:
49
50 MOCK_METHOD4 (draw, bool (const CompRect &,
51 const CompRect &,
52 GLbitfield,
53 GLenum));
54};
55
56class MockBindLocation :
57 public cglfb::BindLocation
58{
59 public:
60
61 MOCK_METHOD1 (bind, cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *));
62 MOCK_METHOD0 (getCurrentlyBound, cglfb::BindableFramebuffer * ());
63};
64
65class MockBindable :
66 public cglfb::BindableFramebuffer
67{
68 public:
69
70 MOCK_METHOD1 (updateAllocation, void (GLenum));
71 MOCK_METHOD1 (setBindStatus, bool (GLenum));
72 MOCK_CONST_METHOD0 (getResourceId, GLuint ());
73};
74
75}
76
77class FBDirectDrawStrategies :
78 public ::testing::Test
79{
80 public:
81
82 FBDirectDrawStrategies () :
83 blitFramebuffer (boost::bind (&MockDrawStrategy::draw, &mpfb, _1, _2, _3, _4)),
84 rtdraw (boost::bind (&MockDrawStrategy::draw, &mdr,
85 _1, _2, _3, _4))
86 {
87 }
88
89 void SetUpStrategyList (const cglfb::RectangularDraw &blit,
90 const cglfb::RectangularDraw &draw)
91 {
92 strategyList.clear ();
93 strategyList.push_back (draw);
94 strategyList.push_back (blit);
95 }
96
97 virtual void SetUp ()
98 {
99 boost::function <cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *)> readBind
100 (boost::bind (&MockBindLocation::bind, &mockBindLocation, _1));
101 blitFramebufferWithReadPushed = boost::bind (&cglfbi::rectangleDrawFromReadBuffer,
102 _1, _2, _3, _4,
103 &mockBindable,
104 readBind,
105 blitFramebuffer);
106
107 SetUpStrategyList (blitFramebuffer, rtdraw);
108 directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
109 }
110
111 std::auto_ptr <cglfbi::DirectDrawStrategies> directDraw;
112 MockDrawStrategy mpfb;
113 cglfb::RectangularDraw blitFramebuffer;
114 cglfb::RectangularDraw blitFramebufferWithReadPushed;
115 MockDrawStrategy mdr;
116 StrictMock <MockBindable> mockBindable;
117 StrictMock <MockBindLocation> mockBindLocation;
118 cglfb::RectangularDraw rtdraw;
119 cglfb::RectangularDrawList strategyList;
120
121};
122
123TEST_F (FBDirectDrawStrategies, BufferBitsSet)
124{
125 CompRect srcAndDst (0, 0, 0, 0);
126
127 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, GL_COLOR_BUFFER_BIT |
128 GL_STENCIL_BUFFER_BIT,
129 _)).WillOnce (Return (true));
130
131 directDraw->draw (srcAndDst,
132 srcAndDst,
133 static_cast <cglfb::BlitMask> (cglfb::ColorData |
134 cglfb::StencilData),
135 cglfb::Good);
136}
137
138TEST_F (FBDirectDrawStrategies, BufferNoBitsSet)
139{
140 CompRect srcAndDst (0, 0, 0, 0);
141
142 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, 0,
143 _)).Times (0);
144
145 directDraw->draw (srcAndDst,
146 srcAndDst,
147 static_cast <cglfb::BlitMask> (0),
148 cglfb::Good);
149}
150
151TEST_F (FBDirectDrawStrategies, GoodToLinear)
152{
153 CompRect srcAndDst (0, 0, 0, 0);
154
155 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
156 GL_LINEAR)).WillOnce (Return (true));
157
158 directDraw->draw (srcAndDst,
159 srcAndDst,
160 cglfb::ColorData,
161 cglfb::Good);
162}
163
164TEST_F (FBDirectDrawStrategies, FastToNearest)
165{
166 CompRect srcAndDst (0, 0, 0, 0);
167
168 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
169 GL_NEAREST)).WillOnce (Return (true));
170
171 directDraw->draw (srcAndDst,
172 srcAndDst,
173 cglfb::ColorData,
174 cglfb::Fast);
175}
176
177TEST_F (FBDirectDrawStrategies, RevertToPaintWhenBlitUnavailable)
178{
179 CompRect srcAndDst (0, 0, 0, 0);
180
181 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
182 _)).WillOnce (Return (false));
183 EXPECT_CALL (mdr, draw (srcAndDst, srcAndDst, _, _));
184
185 directDraw->draw (srcAndDst,
186 srcAndDst,
187 cglfb::ColorData,
188 cglfb::Fast);
189}
190
191TEST_F (FBDirectDrawStrategies, RevertOnBlitUnavailablePermanent)
192{
193 StrictMock <MockDrawStrategy> strictMdr;
194 CompRect srcAndDst (0, 0, 0, 0);
195
196 rtdraw = boost::bind (&MockDrawStrategy::draw, &strictMdr, _1, _2, _3, _4);
197
198 SetUpStrategyList (blitFramebuffer, rtdraw);
199 directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
200
201 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _, _)).WillOnce (Return (false));
202 ON_CALL (strictMdr, draw (_, _, _, _)).WillByDefault (Return (true));
203 EXPECT_CALL (strictMdr, draw (srcAndDst, srcAndDst, _, _)).Times (2);
204
205 directDraw->draw (srcAndDst,
206 srcAndDst,
207 cglfb::ColorData,
208 cglfb::Fast);
209 directDraw->draw (srcAndDst,
210 srcAndDst,
211 cglfb::ColorData,
212 cglfb::Fast);
213}
214
215TEST_F (FBDirectDrawStrategies, BindReadFramebufferOnBlit)
216{
217 CompRect srcAndDst (0, 0, 0, 0);
218
219 SetUpStrategyList (blitFramebufferWithReadPushed, rtdraw);
220 directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
221
222 MockBindable backBuffer;
223
224 EXPECT_CALL (mockBindLocation, bind (&mockBindable)).WillOnce (Return (&backBuffer));
225 EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _, _)).WillOnce (Return (false));
226 ON_CALL (mdr, draw (_, _, _, _)).WillByDefault (Return (true));
227 EXPECT_CALL (mdr, draw (srcAndDst, srcAndDst, _, _)).Times (2);
228
229 directDraw->draw (srcAndDst,
230 srcAndDst,
231 cglfb::ColorData,
232 cglfb::Fast);
233 directDraw->draw (srcAndDst,
234 srcAndDst,
235 cglfb::ColorData,
236 cglfb::Fast);
237}
0238
=== modified file 'plugins/opengl/src/framebufferobject.cpp'
--- plugins/opengl/src/framebufferobject.cpp 2012-08-06 09:44:49 +0000
+++ plugins/opengl/src/framebufferobject.cpp 2013-02-28 02:29:22 +0000
@@ -22,88 +22,96 @@
22 *22 *
23 * Authors: Pekka Paalanen <ppaalanen@gmail.com>23 * Authors: Pekka Paalanen <ppaalanen@gmail.com>
24 */24 */
2525#include <memory>
26#include <map>26#include <map>
27#include <opengl/opengl.h>
27#include <opengl/framebufferobject.h>28#include <opengl/framebufferobject.h>
28#include <opengl/texture.h>29#include <opengl/texture.h>
2930
31#include "framebuffer-direct-draw.h"
32
33namespace cglfb = compiz::opengl;
34namespace cglfbi = compiz::opengl::impl;
35
36namespace compiz
37{
38namespace opengl
39{
40namespace impl
41{
30struct PrivateGLFramebufferObject42struct PrivateGLFramebufferObject
31{43{
32 PrivateGLFramebufferObject () :44 PrivateGLFramebufferObject () :
33 fboId (0),45 fboId (0),
34 pushedId (0),
35 glTex (NULL),46 glTex (NULL),
36 status (-1)47 status (-1)
37 {48 {
38 }49 }
3950
40 void pushFBO ();
41 void popFBO ();
42
43 GLuint fboId;51 GLuint fboId;
44 GLuint pushedId;
45 GLuint rbStencilId;52 GLuint rbStencilId;
46 GLTexture *glTex;53 GLTexture *glTex;
4754
48 GLint status;55 GLint status;
4956
50 static GLuint boundId;57 std::auto_ptr <cglfb::DirectDrawStrategies> mDirectDraw;
51 static std::map<GLuint, GLFramebufferObject *> idMap;58 GLVertexBuffer *vertexBuffer;
52};59};
5360
54GLuint PrivateGLFramebufferObject::boundId = 0;61}
55std::map<GLuint, GLFramebufferObject *> PrivateGLFramebufferObject::idMap;62}
5663}
57void64
58PrivateGLFramebufferObject::pushFBO ()65GLuint
59{66cglfbi::FramebufferObject::getResourceId () const
60 pushedId = boundId;67{
61 if (boundId != fboId)68 return priv->fboId;
62 {69}
63 (*GL::bindFramebuffer) (GL::FRAMEBUFFER, fboId);70
64 boundId = fboId;71bool
65 }72cglfbi::FramebufferObject::setBindStatus (GLenum status)
66}73{
6774 priv->status = status;
68void75 return checkStatus ();
69PrivateGLFramebufferObject::popFBO ()76}
70{77
71 if (boundId != pushedId)78void
72 {79cglfbi::FramebufferObject::updateAllocation (GLenum bindingLocation)
73 (*GL::bindFramebuffer) (GL::FRAMEBUFFER, pushedId);80{
74 boundId = pushedId;81 if (priv->status == -1)
75 }82 {
76}83 (*GL::framebufferTexture2D) (bindingLocation, GL::COLOR_ATTACHMENT0,
7784 priv->glTex->target (),
78GLFramebufferObject::GLFramebufferObject () :85 priv->glTex->name (), 0);
79 priv (new PrivateGLFramebufferObject)86 (*GL::framebufferRenderbuffer) (bindingLocation, GL::DEPTH_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
87 (*GL::framebufferRenderbuffer) (bindingLocation, GL::STENCIL_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
88 }
89
90}
91
92cglfbi::FramebufferObject::FramebufferObject () :
93 priv (new cglfbi::PrivateGLFramebufferObject ())
80{94{
81 (*GL::genFramebuffers) (1, &priv->fboId);95 (*GL::genFramebuffers) (1, &priv->fboId);
82 (*GL::genRenderbuffers) (1, &priv->rbStencilId);96 (*GL::genRenderbuffers) (1, &priv->rbStencilId);
83
84 if (priv->fboId != 0)
85 PrivateGLFramebufferObject::idMap[priv->fboId] = this;
86}97}
8798
88GLFramebufferObject::~GLFramebufferObject ()99cglfbi::FramebufferObject::~FramebufferObject ()
89{100{
90 if (priv->glTex)101 if (priv->glTex)
91 GLTexture::decRef (priv->glTex);102 GLTexture::decRef (priv->glTex);
92103
93 PrivateGLFramebufferObject::idMap.erase (priv->fboId);
94 (*GL::deleteFramebuffers) (1, &priv->fboId);104 (*GL::deleteFramebuffers) (1, &priv->fboId);
95 (*GL::deleteRenderbuffers) (1, &priv->rbStencilId);105 (*GL::deleteRenderbuffers) (1, &priv->rbStencilId);
96106
97
98 delete priv;107 delete priv;
99}108}
100109
101bool110bool
102GLFramebufferObject::allocate (const CompSize &size, const char *image,111cglfbi::FramebufferObject::allocate (const CompSize &size,
103 GLenum format, GLenum type)112 const char *image,
113 GLenum format, GLenum type)
104{114{
105 priv->status = -1;
106
107 if (!priv->glTex ||115 if (!priv->glTex ||
108 size.width () != priv->glTex->width () ||116 size.width () != priv->glTex->width () ||
109 size.height () != priv->glTex->height ())117 size.height () != priv->glTex->height ())
@@ -125,86 +133,39 @@
125 (*GL::bindRenderbuffer) (GL::RENDERBUFFER, priv->rbStencilId);133 (*GL::bindRenderbuffer) (GL::RENDERBUFFER, priv->rbStencilId);
126 (*GL::renderbufferStorage) (GL::RENDERBUFFER, GL::DEPTH24_STENCIL8, size.width (), size.height ());134 (*GL::renderbufferStorage) (GL::RENDERBUFFER, GL::DEPTH24_STENCIL8, size.width (), size.height ());
127 }135 }
136
137 priv->status = -1;
128 }138 }
129139
130 priv->pushFBO ();
131
132 (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,
133 priv->glTex->target (),
134 priv->glTex->name (), 0);
135
136 priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);
137
138 priv->popFBO ();
139 return true;140 return true;
140}141}
141142
142GLFramebufferObject *143namespace
143GLFramebufferObject::bind ()144{
144{145const char *
145 GLFramebufferObject *old = NULL;
146
147 if (priv->boundId != 0)
148 {
149 std::map<GLuint, GLFramebufferObject *>::iterator it;
150 it = PrivateGLFramebufferObject::idMap.find (priv->boundId);
151
152 if (it != PrivateGLFramebufferObject::idMap.end ())
153 old = it->second;
154 else
155 compLogMessage ("opengl", CompLogLevelError,
156 "An FBO without GLFramebufferObject cannot be restored");
157 }
158
159 (*GL::bindFramebuffer) (GL::FRAMEBUFFER, priv->fboId);
160 priv->boundId = priv->fboId;
161
162 (*GL::framebufferRenderbuffer) (GL::FRAMEBUFFER, GL::DEPTH_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
163 (*GL::framebufferRenderbuffer) (GL::FRAMEBUFFER, GL::STENCIL_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
164
165 return old;
166}
167
168// static
169void
170GLFramebufferObject::rebind (GLFramebufferObject *fbo)
171{
172 GLuint id = fbo ? fbo->priv->fboId : 0;
173
174 if (id != fbo->priv->boundId)
175 {
176 (*GL::bindFramebuffer) (GL::FRAMEBUFFER, id);
177 fbo->priv->boundId = id;
178 }
179}
180
181static const char *
182getFboErrorString (GLint status)146getFboErrorString (GLint status)
183{147{
184 switch (status)148 switch (status)
185 {149 {
186 case GL::FRAMEBUFFER_COMPLETE:150 case GL::FRAMEBUFFER_COMPLETE:
187 return "GL::FRAMEBUFFER_COMPLETE";151 return "GL::FRAMEBUFFER_COMPLETE";
188 case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:152 case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
189 return "GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT";153 return "GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
190 case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:154 case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
191 return "GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";155 return "GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
192 case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:156 case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
193 return "GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS";157 return "GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
194 case GL::FRAMEBUFFER_UNSUPPORTED:158 case GL::FRAMEBUFFER_UNSUPPORTED:
195 return "GL::FRAMEBUFFER_UNSUPPORTED";159 return "GL::FRAMEBUFFER_UNSUPPORTED";
196 default:160 default:
197 return "unexpected status";161 return "unexpected status";
198 }162 }
199}163}
164}
200165
201bool166bool
202GLFramebufferObject::checkStatus ()167cglfbi::FramebufferObject::checkStatus ()
203{168{
204 priv->pushFBO ();
205 priv-> status = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER);
206 priv->popFBO ();
207
208 if (priv->status == static_cast <GLint> (GL::FRAMEBUFFER_COMPLETE))169 if (priv->status == static_cast <GLint> (GL::FRAMEBUFFER_COMPLETE))
209 return true;170 return true;
210171
@@ -215,7 +176,54 @@
215}176}
216177
217GLTexture *178GLTexture *
218GLFramebufferObject::tex ()179cglfbi::FramebufferObject::tex ()
219{180{
220 return priv->glTex;181 return priv->glTex;
221}182}
183
184class cglfbi::FBOBindLocation::Private
185{
186 public:
187
188 Private (GLenum binding,
189 cglfb::BindableFramebuffer *back) :
190 mCurrentlyBound (back),
191 mBindPoint (binding)
192 {
193 }
194
195 cglfb::BindableFramebuffer *mCurrentlyBound;
196 GLenum mBindPoint;
197};
198
199cglfbi::FBOBindLocation::FBOBindLocation (GLenum binding,
200 cglfb::BindableFramebuffer *back) :
201 priv (new cglfbi::FBOBindLocation::Private (binding, back))
202{
203}
204
205cglfb::BindableFramebuffer *
206cglfbi::FBOBindLocation::bind (cglfb::BindableFramebuffer *next)
207{
208 if (priv->mCurrentlyBound == next)
209 return next;
210
211 (*GL::bindFramebuffer) (priv->mBindPoint, next->getResourceId ());
212 next->updateAllocation (priv->mBindPoint);
213 if (!next->setBindStatus ((*GL::checkFramebufferStatus) (priv->mBindPoint)))
214 {
215 (*GL::bindFramebuffer) (priv->mBindPoint, priv->mCurrentlyBound->getResourceId ());
216 return NULL;
217 }
218
219 cglfb::BindableFramebuffer *last = priv->mCurrentlyBound;
220 priv->mCurrentlyBound = next;
221 return last;
222}
223
224cglfb::BindableFramebuffer *
225cglfbi::FBOBindLocation::getCurrentlyBound ()
226{
227 return priv->mCurrentlyBound;
228}
229
222230
=== modified file 'plugins/opengl/src/paint.cpp'
--- plugins/opengl/src/paint.cpp 2013-01-03 16:05:26 +0000
+++ plugins/opengl/src/paint.cpp 2013-02-28 02:29:22 +0000
@@ -44,6 +44,7 @@
44#define DEG2RAD (M_PI / 180.0f)44#define DEG2RAD (M_PI / 180.0f)
4545
46using namespace compiz::opengl;46using namespace compiz::opengl;
47namespace cglfb = compiz::opengl;
4748
48GLScreenPaintAttrib defaultScreenPaintAttrib = {49GLScreenPaintAttrib defaultScreenPaintAttrib = {
49 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA50 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA
@@ -432,6 +433,8 @@
432 continue;433 continue;
433 }434 }
434435
436 gw = GLWindow::get (w);
437
435 const CompRegion &clip =438 const CompRegion &clip =
436 (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ?439 (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK)) ?
437 gw->clip () : region;440 gw->clip () : region;
@@ -672,89 +675,16 @@
672}675}
673676
674void677void
675GLScreen::glPaintCompositedOutput (const CompRegion &region,678GLScreen::glPaintCompositedOutput (const CompRegion &region,
676 GLFramebufferObject *fbo,679 compiz::opengl::DirectDrawObject *fbo,
677 unsigned int mask)680 unsigned int mask)
678{681{
679 WRAPABLE_HND_FUNCTN (glPaintCompositedOutput, region, fbo, mask)682 WRAPABLE_HND_FUNCTN (glPaintCompositedOutput, region, fbo, mask)
680683
681 GLMatrix sTransform;684 /* Draw every rect individually, this could be a little slow
682 const GLTexture::Matrix & texmatrix = fbo->tex ()->matrix ();685 * for lots of rects, but the general usecase isn't that */
683 GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();686 foreach (const CompRect &r, region.rects ())
684687 fbo->directDraw (r, r, cglfb::ColorData, cglfb::Fast);
685 streamingBuffer->begin (GL_TRIANGLES);
686
687 if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
688 {
689 GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, 0.0f);
690 GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, screen->width ());
691 GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, 0.0f);
692 GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, screen->height ());
693
694 const GLfloat vertexData[] = {
695 0.0f, 0.0f, 0.0f,
696 0.0f, (float)screen->height (), 0.0f,
697 (float)screen->width (), 0.0f, 0.0f,
698
699 0.0f, (float)screen->height (), 0.0f,
700 (float)screen->width (), (float)screen->height (), 0.0f,
701 (float)screen->width (), 0.0f, 0.0f,
702 };
703
704 const GLfloat textureData[] = {
705 tx1, ty1,
706 tx1, ty2,
707 tx2, ty1,
708 tx1, ty2,
709 tx2, ty2,
710 tx2, ty1,
711 };
712
713 streamingBuffer->addVertices (6, &vertexData[0]);
714 streamingBuffer->addTexCoords (0, 6, &textureData[0]);
715 }
716 else
717 {
718 BoxPtr pBox = const_cast <Region> (region.handle ())->rects;
719 int nBox = const_cast <Region> (region.handle ())->numRects;
720
721 while (nBox--)
722 {
723 GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, pBox->x1);
724 GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, pBox->x2);
725 GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y1);
726 GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y2);
727
728 const GLfloat vertexData[] = {
729 (float)pBox->x1, (float)pBox->y1, 0.0f,
730 (float)pBox->x1, (float)pBox->y2, 0.0f,
731 (float)pBox->x2, (float)pBox->y1, 0.0f,
732
733 (float)pBox->x1, (float)pBox->y2, 0.0f,
734 (float)pBox->x2, (float)pBox->y2, 0.0f,
735 (float)pBox->x2, (float)pBox->y1, 0.0f,
736 };
737
738 const GLfloat textureData[] = {
739 tx1, ty1,
740 tx1, ty2,
741 tx2, ty1,
742 tx1, ty2,
743 tx2, ty2,
744 tx2, ty1,
745 };
746
747 streamingBuffer->addVertices (6, &vertexData[0]);
748 streamingBuffer->addTexCoords (0, 6, &textureData[0]);
749 pBox++;
750 }
751 }
752
753 streamingBuffer->end ();
754 fbo->tex ()->enable (GLTexture::Fast);
755 sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
756 streamingBuffer->render (sTransform);
757 fbo->tex ()->disable ();
758}688}
759689
760static void690static void
761691
=== modified file 'plugins/opengl/src/privates.h'
--- plugins/opengl/src/privates.h 2013-01-03 16:05:26 +0000
+++ plugins/opengl/src/privates.h 2013-02-28 02:29:22 +0000
@@ -29,22 +29,28 @@
29#define _OPENGL_PRIVATES_H29#define _OPENGL_PRIVATES_H
3030
31#include <memory>31#include <memory>
32
33#include <composite/composite.h>32#include <composite/composite.h>
34#include <opengl/opengl.h>33#include <opengl/opengl.h>
35#include <core/atoms.h>34#include <core/atoms.h>
36#include <core/configurerequestbuffer.h>35#include <core/configurerequestbuffer.h>
37
38#ifdef USE_GLES
39#include <opengl/framebufferobject.h>36#include <opengl/framebufferobject.h>
40#endif
41
42#include <opengl/doublebuffer.h>37#include <opengl/doublebuffer.h>
4338
44#include "privatetexture.h"39#include "privatetexture.h"
45#include "privatevertexbuffer.h"40#include "privatevertexbuffer.h"
46#include "opengl_options.h"41#include "opengl_options.h"
4742
43namespace compiz
44{
45 namespace opengl
46 {
47 namespace impl
48 {
49 class DirectDrawObject;
50 }
51 }
52}
53
48extern CompOutput *targetOutput;54extern CompOutput *targetOutput;
4955
50class GLDoubleBuffer :56class GLDoubleBuffer :
@@ -86,6 +92,17 @@
86 Window mOutput;92 Window mOutput;
87};93};
8894
95namespace compiz
96{
97 namespace opengl
98 {
99 bool blitFramebufferGLX (const CompRect &src,
100 const CompRect &dst,
101 GLbitfield mask,
102 GLenum filter);
103 }
104}
105
89#else106#else
90107
91class EGLDoubleBuffer :108class EGLDoubleBuffer :
@@ -109,6 +126,17 @@
109 EGLSurface const & mSurface;126 EGLSurface const & mSurface;
110};127};
111128
129namespace compiz
130{
131 namespace opengl
132 {
133 bool blitFramebufferEGL (const CompRect &src,
134 const CompRect &dst,
135 GLbitfield mask,
136 GLenum filter);
137 }
138}
139
112#endif140#endif
113141
114class GLIcon142class GLIcon
@@ -120,6 +148,16 @@
120 GLTexture::List textures;148 GLTexture::List textures;
121};149};
122150
151class BindableBackbuffer :
152 public compiz::opengl::BindableFramebuffer
153{
154 public:
155
156 GLuint getResourceId () const;
157 bool setBindStatus (GLenum);
158 void updateAllocation (GLenum);
159};
160
123class PrivateGLScreen :161class PrivateGLScreen :
124 public ScreenInterface,162 public ScreenInterface,
125 public compiz::composite::PaintHandler,163 public compiz::composite::PaintHandler,
@@ -197,8 +235,9 @@
197 GLXDoubleBuffer doubleBuffer;235 GLXDoubleBuffer doubleBuffer;
198 #endif236 #endif
199237
200 GLFramebufferObject *scratchFbo;238 std::auto_ptr <compiz::opengl::DirectDrawObject> scratchFbo;
201 CompRegion outputRegion;239 compiz::opengl::BlitFramebufferFunc blitFramebuffer;
240 CompRegion outputRegion;
202241
203 XRectangle lastViewport;242 XRectangle lastViewport;
204 bool refreshSubBuffer;243 bool refreshSubBuffer;
@@ -222,6 +261,9 @@
222 Pixmap rootPixmapCopy;261 Pixmap rootPixmapCopy;
223 CompSize rootPixmapSize;262 CompSize rootPixmapSize;
224263
264 BindableBackbuffer backbuffer;
265 compiz::opengl::impl::FBOBindLocation drawFramebufferBinding;
266 compiz::opengl::impl::FBOBindLocation readFramebufferBinding;
225 const char *glVendor, *glRenderer, *glVersion;267 const char *glVendor, *glRenderer, *glVersion;
226268
227 mutable CompString prevRegex;269 mutable CompString prevRegex;
228270
=== modified file 'plugins/opengl/src/screen.cpp'
--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
+++ plugins/opengl/src/screen.cpp 2013-02-28 02:29:22 +0000
@@ -36,6 +36,7 @@
36#include <boost/make_shared.hpp>36#include <boost/make_shared.hpp>
3737
38#include "privates.h"38#include "privates.h"
39#include "framebuffer-direct-draw.h"
39#include "blacklist/blacklist.h"40#include "blacklist/blacklist.h"
4041
41#include <dlfcn.h>42#include <dlfcn.h>
@@ -67,6 +68,26 @@
6768
6869
69using namespace compiz::opengl;70using namespace compiz::opengl;
71namespace cglfb = compiz::opengl;
72namespace cgli = compiz::opengl::impl;
73
74namespace compiz
75{
76 namespace opengl
77 {
78#ifndef USE_GLES
79 bool blitFramebufferGLX (const CompRect &src,
80 const CompRect &dst,
81 GLbitfield mask,
82 GLenum filter);
83#else
84 bool blitFramebufferEGL (const CompRect &src,
85 const CompRect &dst,
86 GLbitfield mask,
87 GLenum filter);
88#endif
89 }
90}
7091
71namespace GL {92namespace GL {
72 #ifdef USE_GLES93 #ifdef USE_GLES
@@ -164,11 +185,12 @@
164 GLDisableVertexAttribArrayProc disableVertexAttribArray = NULL;185 GLDisableVertexAttribArrayProc disableVertexAttribArray = NULL;
165 GLVertexAttribPointerProc vertexAttribPointer = NULL;186 GLVertexAttribPointerProc vertexAttribPointer = NULL;
166187
167 GLGenRenderbuffersProc genRenderbuffers = NULL;188 GLGenRenderbuffersProc genRenderbuffers = NULL;
168 GLDeleteRenderbuffersProc deleteRenderbuffers = NULL;189 GLDeleteRenderbuffersProc deleteRenderbuffers = NULL;
169 GLFramebufferRenderbufferProc framebufferRenderbuffer = NULL;190 GLFramebufferRenderbufferProc framebufferRenderbuffer = NULL;
170 GLBindRenderbufferProc bindRenderbuffer = NULL;191 GLBindRenderbufferProc bindRenderbuffer = NULL;
171 GLRenderbufferStorageProc renderbufferStorage = NULL;192 GLRenderbufferStorageProc renderbufferStorage = NULL;
193 GLBlitFramebufferProc blitFramebuffer = NULL;
172194
173 bool textureFromPixmap = true;195 bool textureFromPixmap = true;
174 bool textureRectangle = false;196 bool textureRectangle = false;
@@ -299,6 +321,115 @@
299 GLScreen *gScreen;321 GLScreen *gScreen;
300};322};
301323
324namespace
325{
326bool defaultRectangularFramebufferDraw (GLVertexBuffer *vertexBuffer,
327 GLFramebufferObject *fbo,
328 const CompRect &src,
329 const CompRect &dst,
330 GLbitfield mask,
331 GLenum filter)
332{
333 GLTexture *texture = fbo->tex ();
334 GLMatrix sTransform;
335 const GLTexture::Matrix & texmatrix = texture->matrix ();
336 const GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, src.x1 ());
337 const GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, src.x2 ());
338 const GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, src.y1 ());
339 const GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, src.y2 ());
340
341 const GLfloat vx1 = src.x1 ();
342 const GLfloat vx2 = src.x2 ();
343 const GLfloat vy1 = src.y1 ();
344 const GLfloat vy2 = src.y2 ();
345
346 const GLTexture::Filter texFilter =
347 (filter == GL_LINEAR) ? GLTexture::Good :
348 GLTexture::Fast;
349
350 GLfloat vertexData[] = {
351 vx1, vy1, 0.0f,
352 vx1, vy2, 0.0f,
353 vx2, vy1, 0.0f,
354
355 vx1, vy2, 0.0f,
356 vx2, vy2, 0.0f,
357 vx2, vy1, 0.0f,
358 };
359
360 GLfloat textureData[] = {
361 tx1, ty1,
362 tx1, ty2,
363 tx2, ty1,
364 tx1, ty2,
365 tx2, ty2,
366 tx2, ty1,
367 };
368
369 vertexBuffer->begin (GL_TRIANGLES);
370 vertexBuffer->addVertices (6, vertexData);
371 vertexBuffer->addTexCoords (0, 6, textureData);
372
373 if (vertexBuffer->end ())
374 {
375 texture->enable (texFilter);
376 sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
377 vertexBuffer->render (sTransform);
378 texture->disable ();
379 }
380
381 return true;
382}
383
384void initDirectDraw (cgli::DirectDrawStrategies::Ptr &directDraw,
385 const compiz::opengl::RectangularDraw &blitFramebuffer,
386 const compiz::opengl::RectangularDraw &rectangularTextureDraw,
387 const cgli::BindReadBufferFunc &func,
388 compiz::opengl::BindableFramebuffer *bindable)
389{
390 cglfb::RectangularDraw blitFramebufferBound (
391 boost::bind (
392 cgli::rectangleDrawFromReadBuffer,
393 _1, _2, _3, _4,
394 bindable,
395 func,
396 blitFramebuffer));
397
398 /* Tries each of these from back to front */
399 cglfb::RectangularDrawList strategies;
400
401 strategies.push_back (rectangularTextureDraw);
402 strategies.push_back (blitFramebufferBound);
403 directDraw.reset (new cgli::DirectDrawStrategies (strategies));
404}
405}
406
407namespace compiz
408{
409namespace opengl
410{
411DirectDrawObject *
412createBlittableFramebufferObjectWithFallback (const CompSize &sz,
413 GLScreen *gScreen)
414{
415 boost::shared_ptr <cgli::DirectDrawStrategies> directDraw;
416 boost::shared_ptr <cgli::FramebufferObject> fbo (boost::make_shared <cgli::FramebufferObject> ());
417 cglfb::RectangularDraw rectangularTextureDraw (boost::bind (defaultRectangularFramebufferDraw,
418 GLVertexBuffer::streamingBuffer (),
419 fbo.get (),
420 _1, _2, _3, _4));
421 initDirectDraw (directDraw,
422 gScreen->blitFramebufferFunc (),
423 rectangularTextureDraw,
424 boost::bind (&GLScreen::bindFramebufferForReading, gScreen, _1),
425 fbo.get ());
426 DirectDrawObject *dd (new cgli::DirectDrawObject (directDraw, fbo, fbo));
427 dd->allocate (*screen, NULL, GL_BGRA);
428 return dd;
429}
430}
431}
432
302#ifndef USE_GLES433#ifndef USE_GLES
303434
304namespace compiz435namespace compiz
@@ -591,6 +722,7 @@
591 if (GL::textureFromPixmap)722 if (GL::textureFromPixmap)
592 registerBindPixmap (EglTexture::bindPixmapToTexture);723 registerBindPixmap (EglTexture::bindPixmapToTexture);
593724
725 priv->blitFramebuffer = boost::bind (compiz::opengl::blitFramebufferEGL, _1, _2, _3, _4);
594 priv->incorrectRefreshRate = false;726 priv->incorrectRefreshRate = false;
595727
596 #else728 #else
@@ -779,6 +911,10 @@
779 GL::fboSupported = true;911 GL::fboSupported = true;
780 }912 }
781913
914 if (GL::fboSupported &&
915 strstr (glExtensions, "GL_EXT_framebuffer_blit"))
916 GL::blitFramebuffer = (GL::GLBlitFramebufferProc) getProcAddress ("glBlitFramebufferEXT");
917
782 GL::fboStencilSupported = GL::fboSupported &&918 GL::fboStencilSupported = GL::fboSupported &&
783 strstr (glExtensions, "GL_EXT_packed_depth_stencil");919 strstr (glExtensions, "GL_EXT_packed_depth_stencil");
784920
@@ -895,13 +1031,13 @@
8951031
896 if (GL::textureFromPixmap)1032 if (GL::textureFromPixmap)
897 registerBindPixmap (TfpTexture::bindPixmapToTexture);1033 registerBindPixmap (TfpTexture::bindPixmapToTexture);
1034
1035 priv->blitFramebuffer = boost::bind (compiz::opengl::blitFramebufferGLX, _1, _2, _3, _4);
898#endif1036#endif
8991037
900 if (GL::fboSupported)1038 if (GL::fboSupported)
901 {1039 priv->scratchFbo.reset (compiz::opengl::createBlittableFramebufferObjectWithFallback (*screen,
902 priv->scratchFbo = new GLFramebufferObject;1040 this));
903 priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
904 }
9051041
906 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);1042 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
9071043
@@ -1209,9 +1345,6 @@
1209 glXDestroyContext (screen->dpy (), priv->ctx);1345 glXDestroyContext (screen->dpy (), priv->ctx);
1210 #endif1346 #endif
12111347
1212 if (priv->scratchFbo)
1213 delete priv->scratchFbo;
1214
1215 delete priv;1348 delete priv;
1216}1349}
12171350
@@ -1234,6 +1367,7 @@
1234 doubleBuffer (screen->dpy (), *screen, surface),1367 doubleBuffer (screen->dpy (), *screen, surface),
1235 #endif1368 #endif
1236 scratchFbo (NULL),1369 scratchFbo (NULL),
1370 blitFramebuffer (),
1237 outputRegion (),1371 outputRegion (),
1238 refreshSubBuffer (false),1372 refreshSubBuffer (false),
1239 lastMask (0),1373 lastMask (0),
@@ -1246,6 +1380,10 @@
1246 autoProgram (new GLScreenAutoProgram(gs)),1380 autoProgram (new GLScreenAutoProgram(gs)),
1247 rootPixmapCopy (None),1381 rootPixmapCopy (None),
1248 rootPixmapSize (),1382 rootPixmapSize (),
1383 drawFramebufferBinding (GL::DRAW_FRAMEBUFFER,
1384 &backbuffer),
1385 readFramebufferBinding (GL::READ_FRAMEBUFFER,
1386 &backbuffer),
1249 glVendor (NULL),1387 glVendor (NULL),
1250 glRenderer (NULL),1388 glRenderer (NULL),
1251 glVersion (NULL),1389 glVersion (NULL),
@@ -1441,11 +1579,19 @@
1441void1579void
1442PrivateGLScreen::outputChangeNotify ()1580PrivateGLScreen::outputChangeNotify ()
1443{1581{
1582 compiz::opengl::BindableFramebuffer *previousReadBuffer =
1583 readFramebufferBinding.bind (&backbuffer);
1584 compiz::opengl::BindableFramebuffer *previousDrawBuffer =
1585 drawFramebufferBinding.bind (&backbuffer);
1586
1444 screen->outputChangeNotify ();1587 screen->outputChangeNotify ();
14451588
1446 if (scratchFbo)1589 if (scratchFbo.get ())
1447 scratchFbo->allocate (*screen, NULL, GL_BGRA);1590 scratchFbo->allocate (*screen, NULL, GL_BGRA);
1448 updateView ();1591 updateView ();
1592
1593 readFramebufferBinding.bind (previousReadBuffer);
1594 drawFramebufferBinding.bind (previousDrawBuffer);
1449}1595}
14501596
1451#ifndef USE_GLES1597#ifndef USE_GLES
@@ -1670,9 +1816,9 @@
1670 WRAPABLE_DEF (projectionMatrix)1816 WRAPABLE_DEF (projectionMatrix)
16711817
1672void1818void
1673GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,1819GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
1674 GLFramebufferObject *fbo,1820 compiz::opengl::DirectDrawObject *fbo,
1675 unsigned int mask)1821 unsigned int mask)
1676 WRAPABLE_DEF (glPaintCompositedOutput, region, fbo, mask)1822 WRAPABLE_DEF (glPaintCompositedOutput, region, fbo, mask)
16771823
1678void1824void
@@ -1899,6 +2045,30 @@
18992045
1900}2046}
19012047
2048bool
2049cglfb::blitFramebufferGLX (const CompRect &src,
2050 const CompRect &dst,
2051 GLbitfield mask,
2052 GLenum filter)
2053{
2054 /* Must have GL_EXT_blit_framebuffer */
2055 if (!GL::blitFramebuffer)
2056 return false;
2057
2058 /* Be sure to invert y-coords too */
2059 (*GL::blitFramebuffer) (src.x1 (), // sx0
2060 screen->height () - src.y2 (), // sy0
2061 src.x2 (), // sx1
2062 screen->height () - src.y1 (), // sy1
2063 dst.x1 (), // dx0
2064 screen->height () - dst.y2 (), // dy0
2065 dst.x2 (), // dx1,
2066 screen->height () - dst.y1 (), // dy1
2067 GL_COLOR_BUFFER_BIT,
2068 GL_LINEAR);
2069 return true;
2070}
2071
1902#else2072#else
19032073
1904EGLDoubleBuffer::EGLDoubleBuffer (Display *d,2074EGLDoubleBuffer::EGLDoubleBuffer (Display *d,
@@ -1957,6 +2127,16 @@
1957{2127{
1958}2128}
19592129
2130bool
2131cglfb::blitFramebufferEGL (const CompRect &src,
2132 const CompRect &dst,
2133 GLbitfield mask,
2134 GLenum filter)
2135{
2136 /* Not supported on OpenGL|ES2 */
2137 return false;
2138}
2139
1960#endif2140#endif
19612141
1962void2142void
@@ -1977,17 +2157,11 @@
1977 glDepthMask (GL_FALSE);2157 glDepthMask (GL_FALSE);
1978 glStencilMask (0);2158 glStencilMask (0);
19792159
1980 GLFramebufferObject *oldFbo = NULL;2160 compiz::opengl::BindableFramebuffer *oldFbo = NULL;
1981 bool useFbo = false;
19822161
1983 /* Clear the color buffer where appropriate */2162 /* Clear the color buffer where appropriate */
1984 if (GL::fboEnabled && scratchFbo)2163 if (GL::fboEnabled && scratchFbo.get ())
1985 {2164 oldFbo = drawFramebufferBinding.bind (scratchFbo.get ());
1986 oldFbo = scratchFbo->bind ();
1987 useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
1988 if (!useFbo)
1989 GLFramebufferObject::rebind (oldFbo);
1990 }
19912165
1992#ifdef UNSAFE_ARM_SGX_FIXME2166#ifdef UNSAFE_ARM_SGX_FIXME
1993 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&2167 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
@@ -2080,13 +2254,10 @@
20802254
2081 glViewport (0, 0, screen->width (), screen->height ());2255 glViewport (0, 0, screen->width (), screen->height ());
20822256
2083 if (useFbo)2257 if (oldFbo)
2084 {2258 {
2085 GLFramebufferObject::rebind (oldFbo);2259 drawFramebufferBinding.bind (oldFbo);
20862260 gScreen->glPaintCompositedOutput (screen->region (), scratchFbo.get (), mask);
2087 // FIXME: does not work if screen dimensions exceed max texture size
2088 // We should try to use glBlitFramebuffer instead.
2089 gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);
2090 }2261 }
20912262
2092 if (cScreen->outputWindowChanged ())2263 if (cScreen->outputWindowChanged ())
@@ -2101,13 +2272,13 @@
2101 }2272 }
21022273
2103 bool alwaysSwap = optionGetAlwaysSwapBuffers ();2274 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2104 bool fullscreen = useFbo ||2275 bool fullscreen = oldFbo ||
2105 alwaysSwap ||2276 alwaysSwap ||
2106 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&2277 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2107 commonFrontbuffer);2278 commonFrontbuffer);
21082279
2109 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());2280 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2110 doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);2281 doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, oldFbo ? true : false);
2111 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);2282 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2112 doubleBuffer.render (tmpRegion, fullscreen);2283 doubleBuffer.render (tmpRegion, fullscreen);
21132284
@@ -2195,10 +2366,40 @@
2195 }2366 }
2196}2367}
21972368
2198GLFramebufferObject *2369compiz::opengl::FramebufferObject *
2199GLScreen::fbo ()2370GLScreen::fbo ()
2200{2371{
2201 return priv->scratchFbo;2372 return priv->scratchFbo.get ();
2373}
2374
2375compiz::opengl::BindableFramebuffer *
2376GLScreen::backbuffer ()
2377{
2378 return &priv->backbuffer;
2379}
2380
2381compiz::opengl::BindableFramebuffer *
2382GLScreen::drawFramebuffer ()
2383{
2384 return priv->drawFramebufferBinding.getCurrentlyBound ();
2385}
2386
2387compiz::opengl::BindableFramebuffer *
2388GLScreen::bindFramebufferForDrawing (compiz::opengl::BindableFramebuffer *next)
2389{
2390 return priv->drawFramebufferBinding.bind (next);
2391}
2392
2393compiz::opengl::BindableFramebuffer *
2394GLScreen::bindFramebufferForReading (compiz::opengl::BindableFramebuffer *next)
2395{
2396 return priv->readFramebufferBinding.bind (next);
2397}
2398
2399const cglfb::BlitFramebufferFunc &
2400GLScreen::blitFramebufferFunc ()
2401{
2402 return priv->blitFramebuffer;
2202}2403}
22032404
2204GLTexture *2405GLTexture *
@@ -2240,3 +2441,19 @@
2240 priv->rasterPos.setY (0);2441 priv->rasterPos.setY (0);
2241}2442}
22422443
2444GLuint
2445BindableBackbuffer::getResourceId () const
2446{
2447 return 0;
2448}
2449
2450bool
2451BindableBackbuffer::setBindStatus (GLenum)
2452{
2453 return true;
2454}
2455
2456void
2457BindableBackbuffer::updateAllocation (GLenum)
2458{
2459}
22432460
=== modified file 'plugins/water/src/water.cpp'
--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
+++ plugins/water/src/water.cpp 2013-02-28 02:29:22 +0000
@@ -62,7 +62,11 @@
62 if (!useFbo)62 if (!useFbo)
63 return false;63 return false;
6464
65 oldFbo = waterFbo[fIndex]->bind ();65 oldFbo = gScreen->bindFramebufferForDrawing (waterFbo[fIndex]);
66
67 if (!oldFbo)
68 return false;
69
66 glGetIntegerv(GL_VIEWPORT, &oldViewport[0]);70 glGetIntegerv(GL_VIEWPORT, &oldViewport[0]);
67 glViewport (0, 0, texWidth, texHeight);71 glViewport (0, 0, texWidth, texHeight);
6872
@@ -72,7 +76,7 @@
72void76void
73WaterScreen::fboEpilogue ()77WaterScreen::fboEpilogue ()
74{78{
75 GLFramebufferObject::rebind (oldFbo);79 gScreen->bindFramebufferForDrawing (oldFbo);
76 glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);80 glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
77}81}
7882
@@ -305,28 +309,32 @@
305 waterFbo[i]->allocate (size, (char *) t0,309 waterFbo[i]->allocate (size, (char *) t0,
306 GL_BGRA, GL_UNSIGNED_BYTE);310 GL_BGRA, GL_UNSIGNED_BYTE);
307 // check if FBOs are working. If not, fallback to software textures311 // check if FBOs are working. If not, fallback to software textures
308 oldFbo = waterFbo[i]->bind ();312 oldFbo = gScreen->bindFramebufferForDrawing (waterFbo[i]);
309 waterFbo[i]->rebind (oldFbo);313 if (!oldFbo)
310 if (!waterFbo[i]->checkStatus ())
311 {314 {
312 useFbo = false;315 useFbo = false;
313 delete waterFbo[i];316 delete waterFbo[i];
314 break;317 break;
315 }318 }
319 gScreen->bindFramebufferForDrawing (oldFbo);
316 }320 }
317 }321 }
318}322}
319323
320void324void
321WaterScreen::glPaintCompositedOutput (const CompRegion &region,325WaterScreen::glPaintCompositedOutput (const CompRegion &region,
322 GLFramebufferObject *fbo,326 compiz::opengl::DirectDrawObject *fbo,
323 unsigned int mask)327 unsigned int mask)
324{328{
325 if (count)329 if (count)
326 {330 {
327 if (GL::vboEnabled && GL::shaders)331 if (GL::vboEnabled && GL::shaders)
328 {332 {
329 GLFramebufferObject::rebind (oldFbo);333 /* This seems redundant to me */
334 gScreen->bindFramebufferForDrawing (oldFbo);
335
336 oldFbo = NULL;
337
330 glViewport (oldViewport[0], oldViewport[1],338 glViewport (oldViewport[0], oldViewport[1],
331 oldViewport[2], oldViewport[3]);339 oldViewport[2], oldViewport[3]);
332340
333341
=== modified file 'plugins/water/src/water.h'
--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
+++ plugins/water/src/water.h 2013-02-28 02:29:22 +0000
@@ -64,9 +64,9 @@
6464
65 void handleEvent (XEvent *);65 void handleEvent (XEvent *);
6666
67 void glPaintCompositedOutput (const CompRegion &region,67 void glPaintCompositedOutput (const CompRegion &region,
68 GLFramebufferObject *fbo,68 compiz::opengl::DirectDrawObject *fbo,
69 unsigned int mask);69 unsigned int mask);
70 void preparePaint (int);70 void preparePaint (int);
71 void donePaint ();71 void donePaint ();
7272
@@ -100,7 +100,7 @@
100100
101 GLFramebufferObject *waterFbo[TEXTURE_NUM];101 GLFramebufferObject *waterFbo[TEXTURE_NUM];
102102
103 GLFramebufferObject *oldFbo;103 compiz::opengl::BindableFramebuffer *oldFbo;
104 GLint oldViewport[4];104 GLint oldViewport[4];
105 int fboIndex;105 int fboIndex;
106 bool useFbo;106 bool useFbo;
107107
=== added file 'src/asyncserverwindow.h'
--- src/asyncserverwindow.h 1970-01-01 00:00:00 +0000
+++ src/asyncserverwindow.h 2013-02-28 02:29:22 +0000
@@ -0,0 +1,52 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H
26#define _COMPIZ_ASYNC_SERVER_WINDOW_H
27
28#include <X11/Xlib.h>
29
30namespace compiz
31{
32namespace window
33{
34class AsyncServerWindow
35{
36 public:
37
38 virtual ~AsyncServerWindow () {};
39
40 virtual int requestConfigureOnClient (const XWindowChanges &xwc,
41 unsigned int valueMask) = 0;
42 virtual int requestConfigureOnWrapper (const XWindowChanges &xwc,
43 unsigned int valueMask) = 0;
44 virtual int requestConfigureOnFrame (const XWindowChanges &xwc,
45 unsigned int valueMask) = 0;
46 virtual void sendSyntheticConfigureNotify () = 0;
47 virtual bool hasCustomShape () const = 0;
48};
49}
50}
51
52#endif
053
=== removed file 'src/asyncserverwindow.h'
--- src/asyncserverwindow.h 2012-12-13 11:12:32 +0000
+++ src/asyncserverwindow.h 1970-01-01 00:00:00 +0000
@@ -1,52 +0,0 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_ASYNC_SERVER_WINDOW_H
26#define _COMPIZ_ASYNC_SERVER_WINDOW_H
27
28#include <X11/Xlib.h>
29
30namespace compiz
31{
32namespace window
33{
34class AsyncServerWindow
35{
36 public:
37
38 virtual ~AsyncServerWindow () {};
39
40 virtual int requestConfigureOnClient (const XWindowChanges &xwc,
41 unsigned int valueMask) = 0;
42 virtual int requestConfigureOnWrapper (const XWindowChanges &xwc,
43 unsigned int valueMask) = 0;
44 virtual int requestConfigureOnFrame (const XWindowChanges &xwc,
45 unsigned int valueMask) = 0;
46 virtual void sendSyntheticConfigureNotify () = 0;
47 virtual bool hasCustomShape () const = 0;
48};
49}
50}
51
52#endif
530
=== added file 'src/configurerequestbuffer-impl.h'
--- src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000
+++ src/configurerequestbuffer-impl.h 2013-02-28 02:29:22 +0000
@@ -0,0 +1,145 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
26#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
27
28#include <memory>
29#include <vector>
30#include <boost/weak_ptr.hpp>
31#include <boost/shared_ptr.hpp>
32#include <boost/function.hpp>
33#include <X11/Xlib.h>
34
35#include <core/configurerequestbuffer.h>
36
37namespace compiz
38{
39namespace window
40{
41class AsyncServerWindow;
42namespace configure_buffers
43{
44
45class Lockable
46{
47 public:
48
49 typedef boost::shared_ptr <Lockable> Ptr;
50 typedef boost::weak_ptr <Lockable> Weak;
51
52 virtual ~Lockable () {}
53
54 virtual void lock () = 0;
55};
56
57class BufferLock :
58 public Lockable,
59 public Releasable
60{
61 public:
62 typedef boost::shared_ptr <BufferLock> Ptr;
63
64 virtual ~BufferLock () {}
65};
66
67class CountedFreeze
68{
69 public:
70
71 virtual ~CountedFreeze () {}
72
73 virtual void freeze () = 0;
74 virtual void release () = 0;
75
76 virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0;
77};
78
79class ConfigureRequestBuffer :
80 public CountedFreeze,
81 public Buffer
82{
83 public:
84
85 typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory;
86
87 void freeze ();
88 void release ();
89
90 void untrackLock (compiz::window::configure_buffers::BufferLock *lock);
91
92 void pushClientRequest (const XWindowChanges &xwc, unsigned int mask);
93 void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask);
94 void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask);
95 void pushSyntheticConfigureNotify ();
96 compiz::window::configure_buffers::Releasable::Ptr obtainLock ();
97
98 /* Implement getAttributes and require that
99 * the queue is released before calling through
100 * to the SyncServerWindow */
101 bool queryAttributes (XWindowAttributes &attrib);
102 bool queryFrameAttributes (XWindowAttributes &attrib);
103 XRectangle * queryShapeRectangles (int kind,
104 int *count,
105 int *ordering);
106
107 void forceRelease ();
108
109 static compiz::window::configure_buffers::Buffer::Ptr
110 Create (AsyncServerWindow *asyncServerWindow,
111 SyncServerWindow *syncServerWindow,
112 const LockFactory &factory);
113
114 private:
115
116 ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
117 SyncServerWindow *syncServerWindow,
118 const LockFactory &factory);
119
120 class Private;
121 std::auto_ptr <Private> priv;
122};
123
124class ConfigureBufferLock :
125 public compiz::window::configure_buffers::BufferLock
126{
127 public:
128
129 typedef boost::shared_ptr <ConfigureBufferLock> Ptr;
130
131 ConfigureBufferLock (CountedFreeze *);
132 ~ConfigureBufferLock ();
133
134 void lock ();
135 void release ();
136
137 private:
138
139 class Private;
140 std::auto_ptr <Private> priv;
141};
142}
143}
144}
145#endif
0146
=== removed file 'src/configurerequestbuffer-impl.h'
--- src/configurerequestbuffer-impl.h 2012-12-13 11:12:32 +0000
+++ src/configurerequestbuffer-impl.h 1970-01-01 00:00:00 +0000
@@ -1,145 +0,0 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
26#define _COMPIZ_GEOMETRY_UPDATE_QUEUE_H
27
28#include <memory>
29#include <vector>
30#include <boost/weak_ptr.hpp>
31#include <boost/shared_ptr.hpp>
32#include <boost/function.hpp>
33#include <X11/Xlib.h>
34
35#include <core/configurerequestbuffer.h>
36
37namespace compiz
38{
39namespace window
40{
41class AsyncServerWindow;
42namespace configure_buffers
43{
44
45class Lockable
46{
47 public:
48
49 typedef boost::shared_ptr <Lockable> Ptr;
50 typedef boost::weak_ptr <Lockable> Weak;
51
52 virtual ~Lockable () {}
53
54 virtual void lock () = 0;
55};
56
57class BufferLock :
58 public Lockable,
59 public Releasable
60{
61 public:
62 typedef boost::shared_ptr <BufferLock> Ptr;
63
64 virtual ~BufferLock () {}
65};
66
67class CountedFreeze
68{
69 public:
70
71 virtual ~CountedFreeze () {}
72
73 virtual void freeze () = 0;
74 virtual void release () = 0;
75
76 virtual void untrackLock (compiz::window::configure_buffers::BufferLock *lock) = 0;
77};
78
79class ConfigureRequestBuffer :
80 public CountedFreeze,
81 public Buffer
82{
83 public:
84
85 typedef boost::function <BufferLock::Ptr (CountedFreeze *)> LockFactory;
86
87 void freeze ();
88 void release ();
89
90 void untrackLock (compiz::window::configure_buffers::BufferLock *lock);
91
92 void pushClientRequest (const XWindowChanges &xwc, unsigned int mask);
93 void pushWrapperRequest (const XWindowChanges &xwc, unsigned int mask);
94 void pushFrameRequest (const XWindowChanges &xwc, unsigned int mask);
95 void pushSyntheticConfigureNotify ();
96 compiz::window::configure_buffers::Releasable::Ptr obtainLock ();
97
98 /* Implement getAttributes and require that
99 * the queue is released before calling through
100 * to the SyncServerWindow */
101 bool queryAttributes (XWindowAttributes &attrib);
102 bool queryFrameAttributes (XWindowAttributes &attrib);
103 XRectangle * queryShapeRectangles (int kind,
104 int *count,
105 int *ordering);
106
107 void forceRelease ();
108
109 static compiz::window::configure_buffers::Buffer::Ptr
110 Create (AsyncServerWindow *asyncServerWindow,
111 SyncServerWindow *syncServerWindow,
112 const LockFactory &factory);
113
114 private:
115
116 ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
117 SyncServerWindow *syncServerWindow,
118 const LockFactory &factory);
119
120 class Private;
121 std::auto_ptr <Private> priv;
122};
123
124class ConfigureBufferLock :
125 public compiz::window::configure_buffers::BufferLock
126{
127 public:
128
129 typedef boost::shared_ptr <ConfigureBufferLock> Ptr;
130
131 ConfigureBufferLock (CountedFreeze *);
132 ~ConfigureBufferLock ();
133
134 void lock ();
135 void release ();
136
137 private:
138
139 class Private;
140 std::auto_ptr <Private> priv;
141};
142}
143}
144}
145#endif
1460
=== added file 'src/configurerequestbuffer.cpp'
--- src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
+++ src/configurerequestbuffer.cpp 2013-02-28 02:29:22 +0000
@@ -0,0 +1,363 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#include <cstdio>
26#include <cassert>
27#include <boost/foreach.hpp>
28#include <boost/weak_ptr.hpp>
29#include <boost/bind.hpp>
30#include "asyncserverwindow.h"
31#include "configurerequestbuffer-impl.h"
32
33#ifndef foreach
34#define foreach BOOST_FOREACH
35#endif
36
37namespace crb = compiz::window::configure_buffers;
38namespace cw = compiz::window;
39
40class crb::ConfigureRequestBuffer::Private
41{
42 public:
43
44 typedef crb::Lockable::Weak LockObserver;
45
46 Private (cw::AsyncServerWindow *asyncServerWindow,
47 cw::SyncServerWindow *syncServerWindow,
48 const crb::ConfigureRequestBuffer::LockFactory &lockFactory) :
49 clientChangeMask (0),
50 wrapperChangeMask (0),
51 frameChangeMask (0),
52 sendSyntheticConfigure (false),
53 lockCount (0),
54 asyncServerWindow (asyncServerWindow),
55 syncServerWindow (syncServerWindow),
56 lockFactory (lockFactory)
57 {
58 }
59
60 void dispatchConfigure (bool force = false);
61
62 XWindowChanges clientChanges;
63 unsigned int clientChangeMask;
64
65 XWindowChanges wrapperChanges;
66 unsigned int wrapperChangeMask;
67
68 XWindowChanges frameChanges;
69 unsigned int frameChangeMask;
70
71 bool sendSyntheticConfigure;
72
73 unsigned int lockCount;
74
75 cw::AsyncServerWindow *asyncServerWindow;
76 cw::SyncServerWindow *syncServerWindow;
77
78 crb::ConfigureRequestBuffer::LockFactory lockFactory;
79 std::vector <LockObserver> locks;
80};
81
82void
83crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force)
84{
85 const unsigned int allEventMasks = 0x7f;
86 bool immediate = frameChangeMask & (CWStackMode | CWSibling);
87
88 /* This is a stop-gap solution for not having a plugin API to
89 * query the window shape. Once we have that, we can safely
90 * remove these and require the queue to be unlocked when that
91 * happens. Its a separate unit of work for improving resize
92 * performance anyways.
93 */
94 immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth));
95 immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
96 immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
97 immediate |= force;
98
99 bool clientDispatch = (clientChangeMask & allEventMasks);
100 bool wrapperDispatch = (wrapperChangeMask & allEventMasks);
101 bool frameDispatch = (frameChangeMask & allEventMasks);
102
103 bool dispatch = !lockCount && (clientDispatch ||
104 wrapperDispatch ||
105 frameDispatch ||
106 sendSyntheticConfigure);
107
108 if (dispatch || immediate)
109 {
110 if (frameDispatch)
111 {
112 asyncServerWindow->requestConfigureOnFrame (frameChanges,
113 frameChangeMask);
114 frameChangeMask = 0;
115 }
116
117 if (wrapperDispatch)
118 {
119 asyncServerWindow->requestConfigureOnWrapper (wrapperChanges,
120 wrapperChangeMask);
121 wrapperChangeMask = 0;
122 }
123
124 if (clientDispatch)
125 {
126 asyncServerWindow->requestConfigureOnClient (clientChanges,
127 clientChangeMask);
128 clientChangeMask = 0;
129 }
130
131 if (sendSyntheticConfigure)
132 {
133 asyncServerWindow->sendSyntheticConfigureNotify ();
134 sendSyntheticConfigure = false;
135 }
136
137 foreach (const LockObserver &lock, locks)
138 {
139 crb::Lockable::Ptr strongLock (lock.lock ());
140
141 /* We might be in a lock's destructor so check
142 * if this can really be re-locked, if not, its
143 * no big deal as the lock is going away anyways
144 */
145 if (strongLock)
146 strongLock->lock ();
147 }
148 }
149}
150
151void
152crb::ConfigureRequestBuffer::freeze ()
153{
154 priv->lockCount++;
155
156 assert (priv->lockCount <= priv->locks.size ());
157}
158
159void
160crb::ConfigureRequestBuffer::release ()
161{
162 assert (priv->lockCount);
163
164 priv->lockCount--;
165
166 priv->dispatchConfigure ();
167}
168
169namespace
170{
171void applyChangeToXWC (const XWindowChanges &from,
172 XWindowChanges &to,
173 unsigned int mask)
174{
175 if (mask & CWX)
176 to.x = from.x;
177
178 if (mask & CWY)
179 to.y = from.y;
180
181 if (mask & CWWidth)
182 to.width = from.width;
183
184 if (mask & CWHeight)
185 to.height = from.height;
186
187 if (mask & CWBorderWidth)
188 to.border_width = from.border_width;
189
190 if (mask & CWSibling)
191 to.sibling = from.sibling;
192
193 if (mask & CWStackMode)
194 to.stack_mode = from.stack_mode;
195}
196}
197
198void
199crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc,
200 unsigned int mask)
201{
202 applyChangeToXWC (xwc, priv->clientChanges, mask);
203 priv->clientChangeMask |= mask;
204
205 priv->dispatchConfigure ();
206}
207
208void
209crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc,
210 unsigned int mask)
211{
212 applyChangeToXWC (xwc, priv->wrapperChanges, mask);
213 priv->wrapperChangeMask |= mask;
214
215 priv->dispatchConfigure ();
216}
217
218void
219crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc,
220 unsigned int mask)
221{
222 applyChangeToXWC (xwc, priv->frameChanges, mask);
223 priv->frameChangeMask |= mask;
224
225 priv->dispatchConfigure ();
226}
227
228void
229crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify ()
230{
231 priv->sendSyntheticConfigure = true;
232
233 priv->dispatchConfigure ();
234}
235
236crb::Releasable::Ptr
237crb::ConfigureRequestBuffer::obtainLock ()
238{
239 crb::BufferLock::Ptr lock (priv->lockFactory (this));
240
241 priv->locks.push_back (crb::Lockable::Weak (lock));
242 lock->lock ();
243
244 return lock;
245}
246
247namespace
248{
249bool isLock (const crb::Lockable::Weak &lockable,
250 crb::BufferLock *lock)
251{
252 crb::Lockable::Ptr strongLockable (lockable.lock ());
253
254 /* Asserting that the lock did not go away without telling
255 * us first */
256 assert (strongLockable.get ());
257
258 if (strongLockable.get () == lock)
259 return true;
260
261 return false;
262}
263}
264
265void
266crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock)
267{
268 std::remove_if (priv->locks.begin (),
269 priv->locks.end (),
270 boost::bind (isLock, _1, lock));
271}
272
273bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib)
274{
275 priv->dispatchConfigure (true);
276 return priv->syncServerWindow->queryAttributes (attrib);
277}
278
279bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib)
280{
281 priv->dispatchConfigure (true);
282 return priv->syncServerWindow->queryFrameAttributes (attrib);
283}
284
285/* This is more or less of a stop-gap for the fact that
286 * when resizing window we re-query the window shape
287 * and apply that to the frame. That's a separate unit of
288 * work and should be dealt with separately. For now, force
289 * a release of the queue whenever we do that so that
290 * XShapeGetRectangles doesn't return an unexpected value
291 */
292XRectangle *
293crb::ConfigureRequestBuffer::queryShapeRectangles (int kind,
294 int *count,
295 int *ordering)
296{
297 priv->dispatchConfigure (true);
298 return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering);
299}
300
301void crb::ConfigureRequestBuffer::forceRelease ()
302{
303 priv->dispatchConfigure (true);
304}
305
306crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
307 SyncServerWindow *syncServerWindow,
308 const crb::ConfigureRequestBuffer::LockFactory &factory) :
309 priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory))
310{
311}
312
313compiz::window::configure_buffers::Buffer::Ptr
314crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow,
315 SyncServerWindow *syncServerWindow,
316 const LockFactory &factory)
317{
318 return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow,
319 syncServerWindow,
320 factory));
321}
322
323class crb::ConfigureBufferLock::Private
324{
325 public:
326
327 Private (crb::CountedFreeze *freezable) :
328 freezable (freezable),
329 armed (false)
330 {
331 }
332
333 crb::CountedFreeze *freezable;
334 bool armed;
335};
336
337crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) :
338 priv (new crb::ConfigureBufferLock::Private (freezable))
339{
340}
341
342crb::ConfigureBufferLock::~ConfigureBufferLock ()
343{
344 release ();
345}
346
347void
348crb::ConfigureBufferLock::lock ()
349{
350 if (!priv->armed)
351 priv->freezable->freeze ();
352
353 priv->armed = true;
354}
355
356void
357crb::ConfigureBufferLock::release ()
358{
359 if (priv->armed)
360 priv->freezable->release ();
361
362 priv->armed = false;
363}
0364
=== removed file 'src/configurerequestbuffer.cpp'
--- src/configurerequestbuffer.cpp 2013-02-14 12:12:53 +0000
+++ src/configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
@@ -1,363 +0,0 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#include <cstdio>
26#include <cassert>
27#include <boost/foreach.hpp>
28#include <boost/weak_ptr.hpp>
29#include <boost/bind.hpp>
30#include "asyncserverwindow.h"
31#include "configurerequestbuffer-impl.h"
32
33#ifndef foreach
34#define foreach BOOST_FOREACH
35#endif
36
37namespace crb = compiz::window::configure_buffers;
38namespace cw = compiz::window;
39
40class crb::ConfigureRequestBuffer::Private
41{
42 public:
43
44 typedef crb::Lockable::Weak LockObserver;
45
46 Private (cw::AsyncServerWindow *asyncServerWindow,
47 cw::SyncServerWindow *syncServerWindow,
48 const crb::ConfigureRequestBuffer::LockFactory &lockFactory) :
49 clientChangeMask (0),
50 wrapperChangeMask (0),
51 frameChangeMask (0),
52 sendSyntheticConfigure (false),
53 lockCount (0),
54 asyncServerWindow (asyncServerWindow),
55 syncServerWindow (syncServerWindow),
56 lockFactory (lockFactory)
57 {
58 }
59
60 void dispatchConfigure (bool force = false);
61
62 XWindowChanges clientChanges;
63 unsigned int clientChangeMask;
64
65 XWindowChanges wrapperChanges;
66 unsigned int wrapperChangeMask;
67
68 XWindowChanges frameChanges;
69 unsigned int frameChangeMask;
70
71 bool sendSyntheticConfigure;
72
73 unsigned int lockCount;
74
75 cw::AsyncServerWindow *asyncServerWindow;
76 cw::SyncServerWindow *syncServerWindow;
77
78 crb::ConfigureRequestBuffer::LockFactory lockFactory;
79 std::vector <LockObserver> locks;
80};
81
82void
83crb::ConfigureRequestBuffer::Private::dispatchConfigure (bool force)
84{
85 const unsigned int allEventMasks = 0x7f;
86 bool immediate = frameChangeMask & (CWStackMode | CWSibling);
87
88 /* This is a stop-gap solution for not having a plugin API to
89 * query the window shape. Once we have that, we can safely
90 * remove these and require the queue to be unlocked when that
91 * happens. Its a separate unit of work for improving resize
92 * performance anyways.
93 */
94 immediate |= (frameChangeMask & (CWWidth | CWHeight | CWBorderWidth));
95 immediate |= (wrapperChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
96 immediate |= (clientChangeMask & (CWWidth | CWHeight | CWBorderWidth | CWX | CWY));
97 immediate |= force;
98
99 bool clientDispatch = (clientChangeMask & allEventMasks);
100 bool wrapperDispatch = (wrapperChangeMask & allEventMasks);
101 bool frameDispatch = (frameChangeMask & allEventMasks);
102
103 bool dispatch = !lockCount && (clientDispatch ||
104 wrapperDispatch ||
105 frameDispatch ||
106 sendSyntheticConfigure);
107
108 if (dispatch || immediate)
109 {
110 if (frameDispatch)
111 {
112 asyncServerWindow->requestConfigureOnFrame (frameChanges,
113 frameChangeMask);
114 frameChangeMask = 0;
115 }
116
117 if (wrapperDispatch)
118 {
119 asyncServerWindow->requestConfigureOnWrapper (wrapperChanges,
120 wrapperChangeMask);
121 wrapperChangeMask = 0;
122 }
123
124 if (clientDispatch)
125 {
126 asyncServerWindow->requestConfigureOnClient (clientChanges,
127 clientChangeMask);
128 clientChangeMask = 0;
129 }
130
131 if (sendSyntheticConfigure)
132 {
133 asyncServerWindow->sendSyntheticConfigureNotify ();
134 sendSyntheticConfigure = false;
135 }
136
137 foreach (const LockObserver &lock, locks)
138 {
139 crb::Lockable::Ptr strongLock (lock.lock ());
140
141 /* We might be in a lock's destructor so check
142 * if this can really be re-locked, if not, its
143 * no big deal as the lock is going away anyways
144 */
145 if (strongLock)
146 strongLock->lock ();
147 }
148 }
149}
150
151void
152crb::ConfigureRequestBuffer::freeze ()
153{
154 priv->lockCount++;
155
156 assert (priv->lockCount <= priv->locks.size ());
157}
158
159void
160crb::ConfigureRequestBuffer::release ()
161{
162 assert (priv->lockCount);
163
164 priv->lockCount--;
165
166 priv->dispatchConfigure ();
167}
168
169namespace
170{
171void applyChangeToXWC (const XWindowChanges &from,
172 XWindowChanges &to,
173 unsigned int mask)
174{
175 if (mask & CWX)
176 to.x = from.x;
177
178 if (mask & CWY)
179 to.y = from.y;
180
181 if (mask & CWWidth)
182 to.width = from.width;
183
184 if (mask & CWHeight)
185 to.height = from.height;
186
187 if (mask & CWBorderWidth)
188 to.border_width = from.border_width;
189
190 if (mask & CWSibling)
191 to.sibling = from.sibling;
192
193 if (mask & CWStackMode)
194 to.stack_mode = from.stack_mode;
195}
196}
197
198void
199crb::ConfigureRequestBuffer::pushClientRequest (const XWindowChanges &xwc,
200 unsigned int mask)
201{
202 applyChangeToXWC (xwc, priv->clientChanges, mask);
203 priv->clientChangeMask |= mask;
204
205 priv->dispatchConfigure ();
206}
207
208void
209crb::ConfigureRequestBuffer::pushWrapperRequest (const XWindowChanges &xwc,
210 unsigned int mask)
211{
212 applyChangeToXWC (xwc, priv->wrapperChanges, mask);
213 priv->wrapperChangeMask |= mask;
214
215 priv->dispatchConfigure ();
216}
217
218void
219crb::ConfigureRequestBuffer::pushFrameRequest (const XWindowChanges &xwc,
220 unsigned int mask)
221{
222 applyChangeToXWC (xwc, priv->frameChanges, mask);
223 priv->frameChangeMask |= mask;
224
225 priv->dispatchConfigure ();
226}
227
228void
229crb::ConfigureRequestBuffer::pushSyntheticConfigureNotify ()
230{
231 priv->sendSyntheticConfigure = true;
232
233 priv->dispatchConfigure ();
234}
235
236crb::Releasable::Ptr
237crb::ConfigureRequestBuffer::obtainLock ()
238{
239 crb::BufferLock::Ptr lock (priv->lockFactory (this));
240
241 priv->locks.push_back (crb::Lockable::Weak (lock));
242 lock->lock ();
243
244 return lock;
245}
246
247namespace
248{
249bool isLock (const crb::Lockable::Weak &lockable,
250 crb::BufferLock *lock)
251{
252 crb::Lockable::Ptr strongLockable (lockable.lock ());
253
254 /* Asserting that the lock did not go away without telling
255 * us first */
256 assert (strongLockable.get ());
257
258 if (strongLockable.get () == lock)
259 return true;
260
261 return false;
262}
263}
264
265void
266crb::ConfigureRequestBuffer::untrackLock (crb::BufferLock *lock)
267{
268 std::remove_if (priv->locks.begin (),
269 priv->locks.end (),
270 boost::bind (isLock, _1, lock));
271}
272
273bool crb::ConfigureRequestBuffer::queryAttributes (XWindowAttributes &attrib)
274{
275 priv->dispatchConfigure (true);
276 return priv->syncServerWindow->queryAttributes (attrib);
277}
278
279bool crb::ConfigureRequestBuffer::queryFrameAttributes (XWindowAttributes &attrib)
280{
281 priv->dispatchConfigure (true);
282 return priv->syncServerWindow->queryFrameAttributes (attrib);
283}
284
285/* This is more or less of a stop-gap for the fact that
286 * when resizing window we re-query the window shape
287 * and apply that to the frame. That's a separate unit of
288 * work and should be dealt with separately. For now, force
289 * a release of the queue whenever we do that so that
290 * XShapeGetRectangles doesn't return an unexpected value
291 */
292XRectangle *
293crb::ConfigureRequestBuffer::queryShapeRectangles (int kind,
294 int *count,
295 int *ordering)
296{
297 priv->dispatchConfigure (true);
298 return priv->syncServerWindow->queryShapeRectangles (kind, count, ordering);
299}
300
301void crb::ConfigureRequestBuffer::forceRelease ()
302{
303 priv->dispatchConfigure (true);
304}
305
306crb::ConfigureRequestBuffer::ConfigureRequestBuffer (AsyncServerWindow *asyncServerWindow,
307 SyncServerWindow *syncServerWindow,
308 const crb::ConfigureRequestBuffer::LockFactory &factory) :
309 priv (new crb::ConfigureRequestBuffer::Private (asyncServerWindow, syncServerWindow, factory))
310{
311}
312
313compiz::window::configure_buffers::Buffer::Ptr
314crb::ConfigureRequestBuffer::Create (AsyncServerWindow *asyncServerWindow,
315 SyncServerWindow *syncServerWindow,
316 const LockFactory &factory)
317{
318 return crb::Buffer::Ptr (new crb::ConfigureRequestBuffer (asyncServerWindow,
319 syncServerWindow,
320 factory));
321}
322
323class crb::ConfigureBufferLock::Private
324{
325 public:
326
327 Private (crb::CountedFreeze *freezable) :
328 freezable (freezable),
329 armed (false)
330 {
331 }
332
333 crb::CountedFreeze *freezable;
334 bool armed;
335};
336
337crb::ConfigureBufferLock::ConfigureBufferLock (crb::CountedFreeze *freezable) :
338 priv (new crb::ConfigureBufferLock::Private (freezable))
339{
340}
341
342crb::ConfigureBufferLock::~ConfigureBufferLock ()
343{
344 release ();
345}
346
347void
348crb::ConfigureBufferLock::lock ()
349{
350 if (!priv->armed)
351 priv->freezable->freeze ();
352
353 priv->armed = true;
354}
355
356void
357crb::ConfigureBufferLock::release ()
358{
359 if (priv->armed)
360 priv->freezable->release ();
361
362 priv->armed = false;
363}
3640
=== removed file 'src/serverwindow.h'
=== added file 'src/syncserverwindow.h'
--- src/syncserverwindow.h 1970-01-01 00:00:00 +0000
+++ src/syncserverwindow.h 2013-02-28 02:29:22 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H
26#define _COMPIZ_SYNC_SERVER_WINDOW_H
27
28#include <X11/Xlib.h>
29
30namespace compiz
31{
32namespace window
33{
34class SyncServerWindow
35{
36 public:
37
38 virtual ~SyncServerWindow () {}
39
40 virtual bool queryAttributes (XWindowAttributes &attrib) = 0;
41 virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0;
42 virtual XRectangle * queryShapeRectangles (int kind,
43 int *count,
44 int *ordering) = 0;
45};
46}
47}
48
49#endif
050
=== removed file 'src/syncserverwindow.h'
--- src/syncserverwindow.h 2012-12-13 11:12:32 +0000
+++ src/syncserverwindow.h 1970-01-01 00:00:00 +0000
@@ -1,49 +0,0 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#ifndef _COMPIZ_SYNC_SERVER_WINDOW_H
26#define _COMPIZ_SYNC_SERVER_WINDOW_H
27
28#include <X11/Xlib.h>
29
30namespace compiz
31{
32namespace window
33{
34class SyncServerWindow
35{
36 public:
37
38 virtual ~SyncServerWindow () {}
39
40 virtual bool queryAttributes (XWindowAttributes &attrib) = 0;
41 virtual bool queryFrameAttributes (XWindowAttributes &attrib) = 0;
42 virtual XRectangle * queryShapeRectangles (int kind,
43 int *count,
44 int *ordering) = 0;
45};
46}
47}
48
49#endif
500
=== added file 'src/tests/test_configurerequestbuffer.cpp'
--- src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
+++ src/tests/test_configurerequestbuffer.cpp 2013-02-28 02:29:22 +0000
@@ -0,0 +1,667 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#include <deque>
26#include <boost/shared_ptr.hpp>
27#include <boost/make_shared.hpp>
28#include <boost/bind.hpp>
29#include <gmock/gmock.h>
30#include <gtest/gtest.h>
31#include <X11/Xlib.h>
32
33#include "configurerequestbuffer-impl.h"
34#include "asyncserverwindow.h"
35
36namespace crb = compiz::window::configure_buffers;
37namespace cw = compiz::window;
38
39using testing::_;
40using testing::NiceMock;
41using testing::Return;
42using testing::Invoke;
43using testing::WithArgs;
44using testing::SetArgReferee;
45using testing::DoAll;
46using testing::InSequence;
47using testing::ReturnNull;
48using testing::IsNull;
49
50class MockAsyncServerWindow :
51 public cw::AsyncServerWindow
52{
53 public:
54
55 MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int));
56 MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int));
57 MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int));
58 MOCK_METHOD0 (sendSyntheticConfigureNotify, void ());
59 MOCK_CONST_METHOD0 (hasCustomShape, bool ());
60};
61
62class MockSyncServerWindow :
63 public cw::SyncServerWindow
64{
65 public:
66
67 MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &));
68 MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &));
69 MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *));
70};
71
72namespace
73{
74int REQUEST_X = 1;
75int REQUEST_Y = 2;
76int REQUEST_WIDTH = 3;
77int REQUEST_HEIGHT = 4;
78int REQUEST_BORDER = 5;
79
80Window REQUEST_ABOVE = 6;
81unsigned int REQUEST_MODE = 7;
82
83crb::BufferLock::Ptr
84CreateNormalLock (crb::CountedFreeze *cf)
85{
86 return boost::make_shared <crb::ConfigureBufferLock> (cf);
87}
88
89}
90
91MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges")
92{
93 if (vm & CWX)
94 if (xwc.x != arg.x)
95 return false;
96
97 if (vm & CWY)
98 if (xwc.y != arg.y)
99 return false;
100
101 if (vm & CWWidth)
102 if (xwc.width != arg.width)
103 return false;
104
105 if (vm & CWHeight)
106 if (xwc.height != arg.height)
107 return false;
108
109 if (vm & CWBorderWidth)
110 if (xwc.border_width != arg.border_width)
111 return false;
112
113 if (vm & CWStackMode)
114 if (xwc.stack_mode != arg.stack_mode)
115 return false;
116
117 if (vm & CWSibling)
118 if (xwc.sibling != arg.sibling)
119 return false;
120
121 return true;
122}
123
124class ConfigureRequestBuffer :
125 public testing::Test
126{
127 public:
128
129 ConfigureRequestBuffer ()
130 {
131 /* Initialize xwc, we control it
132 * through the value masks */
133 xwc.x = REQUEST_X;
134 xwc.y = REQUEST_Y;
135 xwc.width = REQUEST_WIDTH;
136 xwc.height = REQUEST_HEIGHT;
137 xwc.border_width = REQUEST_BORDER;
138 xwc.sibling = REQUEST_ABOVE;
139 xwc.stack_mode = REQUEST_MODE;
140 }
141
142 protected:
143
144 XWindowChanges xwc;
145 MockAsyncServerWindow asyncServerWindow;
146 MockSyncServerWindow syncServerWindow;
147};
148
149class ConfigureRequestBufferDispatch :
150 public ConfigureRequestBuffer
151{
152 protected:
153
154 ConfigureRequestBufferDispatch () :
155 ConfigureRequestBuffer (),
156 factory (boost::bind (CreateNormalLock, _1)),
157 buffer (
158 crb::ConfigureRequestBuffer::Create (&asyncServerWindow,
159 &syncServerWindow,
160 factory))
161 {
162 }
163
164 crb::ConfigureRequestBuffer::LockFactory factory;
165 crb::Buffer::Ptr buffer;
166};
167
168TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify)
169{
170 EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ());
171
172 buffer->pushSyntheticConfigureNotify ();
173}
174
175TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate)
176{
177 unsigned int valueMask = CWX | CWY | CWBorderWidth |
178 CWSibling | CWStackMode;
179
180 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
181 valueMask));
182
183 buffer->pushClientRequest (xwc, valueMask);
184}
185
186TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate)
187{
188 unsigned int valueMask = CWX | CWY | CWBorderWidth |
189 CWSibling | CWStackMode;
190
191 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
192 valueMask));
193
194 buffer->pushWrapperRequest (xwc, valueMask);
195}
196
197TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate)
198{
199 unsigned int valueMask = CWX | CWY | CWBorderWidth |
200 CWSibling | CWStackMode;
201
202 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
203 valueMask));
204
205 buffer->pushFrameRequest (xwc, valueMask);
206}
207
208TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked)
209{
210 crb::Releasable::Ptr lock (buffer->obtainLock ());
211
212 unsigned int valueMask = 0;
213
214 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
215
216 buffer->pushFrameRequest (xwc, valueMask);
217}
218
219TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked)
220{
221 crb::Releasable::Ptr lock (buffer->obtainLock ());
222
223 unsigned int valueMask = CWX;
224
225 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
226
227 buffer->pushFrameRequest (xwc, valueMask);
228
229 valueMask |= CWY;
230
231 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
232
233 buffer->pushFrameRequest (xwc, valueMask);
234
235 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
236 valueMask));
237
238 lock->release ();
239}
240
241/*
242 * This test is disabled until we can expose the QueryShapeRectangles API
243 * to plugins
244 */
245TEST_F (ConfigureRequestBufferDispatch, DISABLED_PushUpdateLockedReleaseInOrder)
246{
247 crb::Releasable::Ptr lock (buffer->obtainLock ());
248
249 unsigned int valueMask = CWX | CWY;
250
251 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
252 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0);
253 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0);
254
255 buffer->pushClientRequest (xwc, valueMask);
256 buffer->pushWrapperRequest (xwc, 0);
257 buffer->pushFrameRequest (xwc, 0);
258
259 InSequence s;
260
261 /* Always frame -> wrapper -> client */
262 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
263 valueMask));
264 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
265 valueMask));
266 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
267 valueMask));
268
269 lock->release ();
270}
271
272TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer)
273{
274 crb::Releasable::Ptr lock (buffer->obtainLock ());
275
276 unsigned int valueMask = CWX | CWY;
277
278 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
279
280 buffer->pushFrameRequest (xwc, valueMask);
281
282 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
283 valueMask));
284
285 lock->release ();
286}
287
288TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer)
289{
290 crb::Releasable::Ptr lock (buffer->obtainLock ());
291
292 unsigned int valueMask = CWX | CWY;
293
294 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
295
296 buffer->pushFrameRequest (xwc, valueMask);
297
298 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
299 valueMask));
300}
301
302TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack)
303{
304 crb::Releasable::Ptr lock (buffer->obtainLock ());
305
306 unsigned int valueMask = CWStackMode | CWSibling;
307
308 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
309 valueMask));
310
311 buffer->pushFrameRequest (xwc, valueMask);
312}
313
314TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWindowSizeChange)
315{
316 crb::Releasable::Ptr lock (buffer->obtainLock ());
317
318 unsigned int valueMask = CWWidth | CWHeight | CWBorderWidth;
319
320 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
321 valueMask));
322
323 buffer->pushFrameRequest (xwc, valueMask);
324}
325
326TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnClientReposition)
327{
328 crb::Releasable::Ptr lock (buffer->obtainLock ());
329
330 unsigned int valueMask = CWX | CWY;
331
332 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
333 valueMask));
334
335 buffer->pushClientRequest (xwc, valueMask);
336}
337
338TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWrapperReposition)
339{
340 crb::Releasable::Ptr lock (buffer->obtainLock ());
341
342 unsigned int valueMask = CWX | CWY;
343
344 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
345 valueMask));
346
347 buffer->pushWrapperRequest (xwc, valueMask);
348}
349
350namespace
351{
352class MockLock :
353 public crb::BufferLock
354{
355 public:
356
357 /* We're currently importing the locks statefulness and coupling
358 * the caller with that */
359 MockLock () :
360 armed (false)
361 {
362 ON_CALL (*this, lock ()).WillByDefault (
363 Invoke (this, &MockLock::FreezeIfUnarmed));
364 ON_CALL (*this, release ()).WillByDefault (
365 Invoke (this, &MockLock::ReleaseIfArmed));
366 }
367
368 void OperateOver (crb::CountedFreeze *cf)
369 {
370 countedFreeze = cf;
371 }
372
373 void FreezeIfUnarmed ()
374 {
375 if (!armed)
376 {
377 countedFreeze->freeze ();
378 armed = true;
379 }
380 }
381
382 void ReleaseIfArmed ()
383 {
384 if (armed)
385 {
386 countedFreeze->release ();
387 armed = false;
388 }
389 }
390
391 typedef boost::shared_ptr <MockLock> Ptr;
392
393 MOCK_METHOD0 (lock, void ());
394 MOCK_METHOD0 (release, void ());
395
396 private:
397
398 crb::CountedFreeze *countedFreeze;
399 bool armed;
400};
401
402class MockLockFactory
403{
404 public:
405
406 crb::BufferLock::Ptr
407 CreateMockLock (crb::CountedFreeze *cf)
408 {
409 MockLock::Ptr mockLock (locks.front ());
410 mockLock->OperateOver (cf);
411
412 locks.pop_front ();
413
414 return mockLock;
415 }
416
417 void
418 QueueLockForCreation (const MockLock::Ptr &lock)
419 {
420 locks.push_back (lock);
421 }
422
423 private:
424
425 std::deque <MockLock::Ptr> locks;
426};
427}
428
429class ConfigureRequestBufferLockBehaviour :
430 public ConfigureRequestBuffer
431{
432 public:
433
434 ConfigureRequestBufferLockBehaviour () :
435 ConfigureRequestBuffer (),
436 lock (boost::make_shared <MockLock> ()),
437 factory (
438 boost::bind (&MockLockFactory::CreateMockLock,
439 &mockLockFactory,
440 _1)),
441 buffer (
442 crb::ConfigureRequestBuffer::Create (
443 &asyncServerWindow,
444 &syncServerWindow,
445 factory))
446
447 {
448 mockLockFactory.QueueLockForCreation (lock);
449 }
450
451 protected:
452
453 typedef NiceMock <MockAsyncServerWindow> NiceServerWindow;
454 typedef crb::ConfigureRequestBuffer::LockFactory LockFactory;
455
456 MockLock::Ptr lock;
457 MockLockFactory mockLockFactory;
458
459 LockFactory factory;
460 crb::Buffer::Ptr buffer;
461};
462
463TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease)
464{
465 EXPECT_CALL (*lock, lock ());
466 crb::Releasable::Ptr releasable (buffer->obtainLock ());
467
468 unsigned int valueMask = CWX | CWY;
469
470 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
471
472 buffer->pushFrameRequest (xwc, valueMask);
473
474 /* We are releasing this lock */
475 EXPECT_CALL (*lock, release ());
476
477 /* Now the buffer will dispatch is configure request */
478 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
479
480 /* Rearm locks on release */
481 EXPECT_CALL (*lock, lock ());
482
483 /* Directly release the queue */
484 releasable->release ();
485}
486
487TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired)
488{
489 /* Locks get armed on construction */
490 EXPECT_CALL (*lock, lock ());
491 crb::Releasable::Ptr releasable (buffer->obtainLock ());
492
493 /* No call to requestConfigureOnFrame if there's nothing to be configured */
494 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
495
496 /* We are releasing this lock */
497 EXPECT_CALL (*lock, release ());
498
499 /* No rearm - we haven't released the whole buffer */
500 EXPECT_CALL (*lock, lock ()).Times (0);
501
502 /* Directly release the queue */
503 releasable->release ();
504}
505
506TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady)
507{
508 /* Locks get armed on construction */
509 EXPECT_CALL (*lock, lock ());
510 crb::Releasable::Ptr releasable (buffer->obtainLock ());
511
512 /* We are releasing this lock */
513 EXPECT_CALL (*lock, release ());
514
515 /* No call to requestConfigureOnFrame if there's nothing to be configured */
516 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
517
518 /* No rearm - we haven't released it */
519 EXPECT_CALL (*lock, lock ()).Times (0);
520
521 /* Directly release the queue */
522 releasable->release ();
523
524 /* Since we're now going to push something to a queue
525 * that's effectively not locked, the locks should now
526 * be released */
527 unsigned int valueMask = CWX | CWY;
528
529 /* Now rearm it */
530 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
531 EXPECT_CALL (*lock, lock ());
532
533 buffer->pushFrameRequest (xwc, valueMask);
534}
535
536TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease)
537{
538 MockLock::Ptr second (boost::make_shared <MockLock> ());
539 mockLockFactory.QueueLockForCreation (second);
540
541 /* Locks get armed on construction */
542 EXPECT_CALL (*lock, lock ());
543 EXPECT_CALL (*second, lock ());
544
545 crb::Releasable::Ptr releasable (buffer->obtainLock ());
546 crb::Releasable::Ptr otherReleasable (buffer->obtainLock ());
547
548 /* We are releasing this lock */
549 EXPECT_CALL (*lock, release ());
550
551 /* No call to requestConfigureOnFrame if there's nothing to be configured */
552 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
553
554 /* No rearm - we haven't released it */
555 EXPECT_CALL (*lock, lock ()).Times (0);
556
557 releasable->release ();
558}
559
560TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm)
561{
562 /* Locks get armed on construction */
563 EXPECT_CALL (*lock, lock ());
564
565 crb::Releasable::Ptr releasable (buffer->obtainLock ());
566
567 unsigned int valueMask = CWX | CWY;
568
569 /* Queue locked */
570 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
571
572 buffer->pushFrameRequest (xwc, valueMask);
573
574 /* Queue forceably unlocked, locks rearmed */
575 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
576 EXPECT_CALL (*lock, lock ());
577
578 /* Expect a call to XGetWindowAttributes */
579 EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _))
580 .WillOnce (
581 ReturnNull ());
582
583 int a, b;
584
585 EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ());
586}
587
588TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm)
589{
590 /* Locks get armed on construction */
591 EXPECT_CALL (*lock, lock ());
592
593 crb::Releasable::Ptr releasable (buffer->obtainLock ());
594
595 unsigned int valueMask = CWX | CWY;
596
597 /* Queue locked */
598 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
599
600 buffer->pushFrameRequest (xwc, valueMask);
601
602 /* Queue forceably unlocked, locks rearmed */
603 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
604 EXPECT_CALL (*lock, lock ());
605
606 /* Expect a call to XGetWindowAttributes */
607 XWindowAttributes xwa;
608 EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
609 .WillOnce (
610 DoAll (
611 SetArgReferee <0> (xwa),
612 Return (true)));
613
614 buffer->queryFrameAttributes (xwa);
615}
616
617TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm)
618{
619 /* Locks get armed on construction */
620 EXPECT_CALL (*lock, lock ());
621
622 crb::Releasable::Ptr releasable (buffer->obtainLock ());
623
624 unsigned int valueMask = CWX | CWY;
625
626 /* Queue locked */
627 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
628
629 buffer->pushFrameRequest (xwc, valueMask);
630
631 /* Queue forceably unlocked, locks rearmed */
632 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
633 EXPECT_CALL (*lock, lock ());
634
635 /* Expect a call to XGetWindowAttributes */
636 XWindowAttributes xwa;
637 EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
638 .WillOnce (
639 DoAll (
640 SetArgReferee <0> (xwa),
641 Return (true)));
642
643 buffer->queryFrameAttributes (xwa);
644}
645
646TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm)
647{
648 /* Locks get armed on construction */
649 EXPECT_CALL (*lock, lock ());
650
651 crb::Releasable::Ptr releasable (buffer->obtainLock ());
652
653 unsigned int valueMask = CWX | CWY;
654
655 /* Queue locked */
656 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
657
658 buffer->pushFrameRequest (xwc, valueMask);
659
660 /* Queue forceably unlocked, locks rearmed */
661 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
662 EXPECT_CALL (*lock, lock ());
663
664 /* Force release */
665 buffer->forceRelease ();
666}
667
0668
=== removed file 'src/tests/test_configurerequestbuffer.cpp'
--- src/tests/test_configurerequestbuffer.cpp 2012-12-13 14:07:01 +0000
+++ src/tests/test_configurerequestbuffer.cpp 1970-01-01 00:00:00 +0000
@@ -1,667 +0,0 @@
1/*
2 * Copyright © 2012 Sam Spilsbury
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Canonical Ltd. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Canonical Ltd. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authored by: Sam Spilsbury <smspillaz@gmail.com>
24 */
25#include <deque>
26#include <boost/shared_ptr.hpp>
27#include <boost/make_shared.hpp>
28#include <boost/bind.hpp>
29#include <gmock/gmock.h>
30#include <gtest/gtest.h>
31#include <X11/Xlib.h>
32
33#include "configurerequestbuffer-impl.h"
34#include "asyncserverwindow.h"
35
36namespace crb = compiz::window::configure_buffers;
37namespace cw = compiz::window;
38
39using testing::_;
40using testing::NiceMock;
41using testing::Return;
42using testing::Invoke;
43using testing::WithArgs;
44using testing::SetArgReferee;
45using testing::DoAll;
46using testing::InSequence;
47using testing::ReturnNull;
48using testing::IsNull;
49
50class MockAsyncServerWindow :
51 public cw::AsyncServerWindow
52{
53 public:
54
55 MOCK_METHOD2 (requestConfigureOnClient, int (const XWindowChanges &, unsigned int));
56 MOCK_METHOD2 (requestConfigureOnFrame, int (const XWindowChanges &, unsigned int));
57 MOCK_METHOD2 (requestConfigureOnWrapper, int (const XWindowChanges &, unsigned int));
58 MOCK_METHOD0 (sendSyntheticConfigureNotify, void ());
59 MOCK_CONST_METHOD0 (hasCustomShape, bool ());
60};
61
62class MockSyncServerWindow :
63 public cw::SyncServerWindow
64{
65 public:
66
67 MOCK_METHOD1 (queryAttributes, bool (XWindowAttributes &));
68 MOCK_METHOD1 (queryFrameAttributes, bool (XWindowAttributes &));
69 MOCK_METHOD3 (queryShapeRectangles, XRectangle * (int, int *, int *));
70};
71
72namespace
73{
74int REQUEST_X = 1;
75int REQUEST_Y = 2;
76int REQUEST_WIDTH = 3;
77int REQUEST_HEIGHT = 4;
78int REQUEST_BORDER = 5;
79
80Window REQUEST_ABOVE = 6;
81unsigned int REQUEST_MODE = 7;
82
83crb::BufferLock::Ptr
84CreateNormalLock (crb::CountedFreeze *cf)
85{
86 return boost::make_shared <crb::ConfigureBufferLock> (cf);
87}
88
89}
90
91MATCHER_P2 (MaskXWC, xwc, vm, "Matches XWindowChanges")
92{
93 if (vm & CWX)
94 if (xwc.x != arg.x)
95 return false;
96
97 if (vm & CWY)
98 if (xwc.y != arg.y)
99 return false;
100
101 if (vm & CWWidth)
102 if (xwc.width != arg.width)
103 return false;
104
105 if (vm & CWHeight)
106 if (xwc.height != arg.height)
107 return false;
108
109 if (vm & CWBorderWidth)
110 if (xwc.border_width != arg.border_width)
111 return false;
112
113 if (vm & CWStackMode)
114 if (xwc.stack_mode != arg.stack_mode)
115 return false;
116
117 if (vm & CWSibling)
118 if (xwc.sibling != arg.sibling)
119 return false;
120
121 return true;
122}
123
124class ConfigureRequestBuffer :
125 public testing::Test
126{
127 public:
128
129 ConfigureRequestBuffer ()
130 {
131 /* Initialize xwc, we control it
132 * through the value masks */
133 xwc.x = REQUEST_X;
134 xwc.y = REQUEST_Y;
135 xwc.width = REQUEST_WIDTH;
136 xwc.height = REQUEST_HEIGHT;
137 xwc.border_width = REQUEST_BORDER;
138 xwc.sibling = REQUEST_ABOVE;
139 xwc.stack_mode = REQUEST_MODE;
140 }
141
142 protected:
143
144 XWindowChanges xwc;
145 MockAsyncServerWindow asyncServerWindow;
146 MockSyncServerWindow syncServerWindow;
147};
148
149class ConfigureRequestBufferDispatch :
150 public ConfigureRequestBuffer
151{
152 protected:
153
154 ConfigureRequestBufferDispatch () :
155 ConfigureRequestBuffer (),
156 factory (boost::bind (CreateNormalLock, _1)),
157 buffer (
158 crb::ConfigureRequestBuffer::Create (&asyncServerWindow,
159 &syncServerWindow,
160 factory))
161 {
162 }
163
164 crb::ConfigureRequestBuffer::LockFactory factory;
165 crb::Buffer::Ptr buffer;
166};
167
168TEST_F (ConfigureRequestBufferDispatch, PushDirectSyntheticConfigureNotify)
169{
170 EXPECT_CALL (asyncServerWindow, sendSyntheticConfigureNotify ());
171
172 buffer->pushSyntheticConfigureNotify ();
173}
174
175TEST_F (ConfigureRequestBufferDispatch, PushDirectClientUpdate)
176{
177 unsigned int valueMask = CWX | CWY | CWBorderWidth |
178 CWSibling | CWStackMode;
179
180 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
181 valueMask));
182
183 buffer->pushClientRequest (xwc, valueMask);
184}
185
186TEST_F (ConfigureRequestBufferDispatch, PushDirectWrapperUpdate)
187{
188 unsigned int valueMask = CWX | CWY | CWBorderWidth |
189 CWSibling | CWStackMode;
190
191 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
192 valueMask));
193
194 buffer->pushWrapperRequest (xwc, valueMask);
195}
196
197TEST_F (ConfigureRequestBufferDispatch, PushDirectFrameUpdate)
198{
199 unsigned int valueMask = CWX | CWY | CWBorderWidth |
200 CWSibling | CWStackMode;
201
202 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
203 valueMask));
204
205 buffer->pushFrameRequest (xwc, valueMask);
206}
207
208TEST_F (ConfigureRequestBufferDispatch, PushUpdateLocked)
209{
210 crb::Releasable::Ptr lock (buffer->obtainLock ());
211
212 unsigned int valueMask = 0;
213
214 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
215
216 buffer->pushFrameRequest (xwc, valueMask);
217}
218
219TEST_F (ConfigureRequestBufferDispatch, PushCombinedUpdateLocked)
220{
221 crb::Releasable::Ptr lock (buffer->obtainLock ());
222
223 unsigned int valueMask = CWX;
224
225 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
226
227 buffer->pushFrameRequest (xwc, valueMask);
228
229 valueMask |= CWY;
230
231 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
232
233 buffer->pushFrameRequest (xwc, valueMask);
234
235 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
236 valueMask));
237
238 lock->release ();
239}
240
241/*
242 * This test is disabled until we can expose the QueryShapeRectangles API
243 * to plugins
244 */
245TEST_F (ConfigureRequestBufferDispatch, DISABLED_PushUpdateLockedReleaseInOrder)
246{
247 crb::Releasable::Ptr lock (buffer->obtainLock ());
248
249 unsigned int valueMask = CWX | CWY;
250
251 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
252 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (_, _)).Times (0);
253 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (_, _)).Times (0);
254
255 buffer->pushClientRequest (xwc, valueMask);
256 buffer->pushWrapperRequest (xwc, 0);
257 buffer->pushFrameRequest (xwc, 0);
258
259 InSequence s;
260
261 /* Always frame -> wrapper -> client */
262 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
263 valueMask));
264 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
265 valueMask));
266 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
267 valueMask));
268
269 lock->release ();
270}
271
272TEST_F (ConfigureRequestBufferDispatch, UnlockBuffer)
273{
274 crb::Releasable::Ptr lock (buffer->obtainLock ());
275
276 unsigned int valueMask = CWX | CWY;
277
278 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
279
280 buffer->pushFrameRequest (xwc, valueMask);
281
282 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
283 valueMask));
284
285 lock->release ();
286}
287
288TEST_F (ConfigureRequestBufferDispatch, ImplicitUnlockBuffer)
289{
290 crb::Releasable::Ptr lock (buffer->obtainLock ());
291
292 unsigned int valueMask = CWX | CWY;
293
294 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
295
296 buffer->pushFrameRequest (xwc, valueMask);
297
298 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
299 valueMask));
300}
301
302TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnRestack)
303{
304 crb::Releasable::Ptr lock (buffer->obtainLock ());
305
306 unsigned int valueMask = CWStackMode | CWSibling;
307
308 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
309 valueMask));
310
311 buffer->pushFrameRequest (xwc, valueMask);
312}
313
314TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWindowSizeChange)
315{
316 crb::Releasable::Ptr lock (buffer->obtainLock ());
317
318 unsigned int valueMask = CWWidth | CWHeight | CWBorderWidth;
319
320 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (MaskXWC (xwc, valueMask),
321 valueMask));
322
323 buffer->pushFrameRequest (xwc, valueMask);
324}
325
326TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnClientReposition)
327{
328 crb::Releasable::Ptr lock (buffer->obtainLock ());
329
330 unsigned int valueMask = CWX | CWY;
331
332 EXPECT_CALL (asyncServerWindow, requestConfigureOnClient (MaskXWC (xwc, valueMask),
333 valueMask));
334
335 buffer->pushClientRequest (xwc, valueMask);
336}
337
338TEST_F (ConfigureRequestBufferDispatch, ForceImmediateConfigureOnWrapperReposition)
339{
340 crb::Releasable::Ptr lock (buffer->obtainLock ());
341
342 unsigned int valueMask = CWX | CWY;
343
344 EXPECT_CALL (asyncServerWindow, requestConfigureOnWrapper (MaskXWC (xwc, valueMask),
345 valueMask));
346
347 buffer->pushWrapperRequest (xwc, valueMask);
348}
349
350namespace
351{
352class MockLock :
353 public crb::BufferLock
354{
355 public:
356
357 /* We're currently importing the locks statefulness and coupling
358 * the caller with that */
359 MockLock () :
360 armed (false)
361 {
362 ON_CALL (*this, lock ()).WillByDefault (
363 Invoke (this, &MockLock::FreezeIfUnarmed));
364 ON_CALL (*this, release ()).WillByDefault (
365 Invoke (this, &MockLock::ReleaseIfArmed));
366 }
367
368 void OperateOver (crb::CountedFreeze *cf)
369 {
370 countedFreeze = cf;
371 }
372
373 void FreezeIfUnarmed ()
374 {
375 if (!armed)
376 {
377 countedFreeze->freeze ();
378 armed = true;
379 }
380 }
381
382 void ReleaseIfArmed ()
383 {
384 if (armed)
385 {
386 countedFreeze->release ();
387 armed = false;
388 }
389 }
390
391 typedef boost::shared_ptr <MockLock> Ptr;
392
393 MOCK_METHOD0 (lock, void ());
394 MOCK_METHOD0 (release, void ());
395
396 private:
397
398 crb::CountedFreeze *countedFreeze;
399 bool armed;
400};
401
402class MockLockFactory
403{
404 public:
405
406 crb::BufferLock::Ptr
407 CreateMockLock (crb::CountedFreeze *cf)
408 {
409 MockLock::Ptr mockLock (locks.front ());
410 mockLock->OperateOver (cf);
411
412 locks.pop_front ();
413
414 return mockLock;
415 }
416
417 void
418 QueueLockForCreation (const MockLock::Ptr &lock)
419 {
420 locks.push_back (lock);
421 }
422
423 private:
424
425 std::deque <MockLock::Ptr> locks;
426};
427}
428
429class ConfigureRequestBufferLockBehaviour :
430 public ConfigureRequestBuffer
431{
432 public:
433
434 ConfigureRequestBufferLockBehaviour () :
435 ConfigureRequestBuffer (),
436 lock (boost::make_shared <MockLock> ()),
437 factory (
438 boost::bind (&MockLockFactory::CreateMockLock,
439 &mockLockFactory,
440 _1)),
441 buffer (
442 crb::ConfigureRequestBuffer::Create (
443 &asyncServerWindow,
444 &syncServerWindow,
445 factory))
446
447 {
448 mockLockFactory.QueueLockForCreation (lock);
449 }
450
451 protected:
452
453 typedef NiceMock <MockAsyncServerWindow> NiceServerWindow;
454 typedef crb::ConfigureRequestBuffer::LockFactory LockFactory;
455
456 MockLock::Ptr lock;
457 MockLockFactory mockLockFactory;
458
459 LockFactory factory;
460 crb::Buffer::Ptr buffer;
461};
462
463TEST_F (ConfigureRequestBufferLockBehaviour, RearmBufferLockOnRelease)
464{
465 EXPECT_CALL (*lock, lock ());
466 crb::Releasable::Ptr releasable (buffer->obtainLock ());
467
468 unsigned int valueMask = CWX | CWY;
469
470 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
471
472 buffer->pushFrameRequest (xwc, valueMask);
473
474 /* We are releasing this lock */
475 EXPECT_CALL (*lock, release ());
476
477 /* Now the buffer will dispatch is configure request */
478 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
479
480 /* Rearm locks on release */
481 EXPECT_CALL (*lock, lock ());
482
483 /* Directly release the queue */
484 releasable->release ();
485}
486
487TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockNoReleaseRequired)
488{
489 /* Locks get armed on construction */
490 EXPECT_CALL (*lock, lock ());
491 crb::Releasable::Ptr releasable (buffer->obtainLock ());
492
493 /* No call to requestConfigureOnFrame if there's nothing to be configured */
494 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
495
496 /* We are releasing this lock */
497 EXPECT_CALL (*lock, release ());
498
499 /* No rearm - we haven't released the whole buffer */
500 EXPECT_CALL (*lock, lock ()).Times (0);
501
502 /* Directly release the queue */
503 releasable->release ();
504}
505
506TEST_F (ConfigureRequestBufferLockBehaviour, RearmWhenPushReady)
507{
508 /* Locks get armed on construction */
509 EXPECT_CALL (*lock, lock ());
510 crb::Releasable::Ptr releasable (buffer->obtainLock ());
511
512 /* We are releasing this lock */
513 EXPECT_CALL (*lock, release ());
514
515 /* No call to requestConfigureOnFrame if there's nothing to be configured */
516 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
517
518 /* No rearm - we haven't released it */
519 EXPECT_CALL (*lock, lock ()).Times (0);
520
521 /* Directly release the queue */
522 releasable->release ();
523
524 /* Since we're now going to push something to a queue
525 * that's effectively not locked, the locks should now
526 * be released */
527 unsigned int valueMask = CWX | CWY;
528
529 /* Now rearm it */
530 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
531 EXPECT_CALL (*lock, lock ());
532
533 buffer->pushFrameRequest (xwc, valueMask);
534}
535
536TEST_F (ConfigureRequestBufferLockBehaviour, NoRearmBufferLockOnNoRelease)
537{
538 MockLock::Ptr second (boost::make_shared <MockLock> ());
539 mockLockFactory.QueueLockForCreation (second);
540
541 /* Locks get armed on construction */
542 EXPECT_CALL (*lock, lock ());
543 EXPECT_CALL (*second, lock ());
544
545 crb::Releasable::Ptr releasable (buffer->obtainLock ());
546 crb::Releasable::Ptr otherReleasable (buffer->obtainLock ());
547
548 /* We are releasing this lock */
549 EXPECT_CALL (*lock, release ());
550
551 /* No call to requestConfigureOnFrame if there's nothing to be configured */
552 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
553
554 /* No rearm - we haven't released it */
555 EXPECT_CALL (*lock, lock ()).Times (0);
556
557 releasable->release ();
558}
559
560TEST_F (ConfigureRequestBufferLockBehaviour, QueryAttributesDispatchAndRearm)
561{
562 /* Locks get armed on construction */
563 EXPECT_CALL (*lock, lock ());
564
565 crb::Releasable::Ptr releasable (buffer->obtainLock ());
566
567 unsigned int valueMask = CWX | CWY;
568
569 /* Queue locked */
570 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
571
572 buffer->pushFrameRequest (xwc, valueMask);
573
574 /* Queue forceably unlocked, locks rearmed */
575 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
576 EXPECT_CALL (*lock, lock ());
577
578 /* Expect a call to XGetWindowAttributes */
579 EXPECT_CALL (syncServerWindow, queryShapeRectangles (_, _, _))
580 .WillOnce (
581 ReturnNull ());
582
583 int a, b;
584
585 EXPECT_THAT (buffer->queryShapeRectangles (0, &a, &b), IsNull ());
586}
587
588TEST_F (ConfigureRequestBufferLockBehaviour, QueryFrameAttributesDispatchAndRearm)
589{
590 /* Locks get armed on construction */
591 EXPECT_CALL (*lock, lock ());
592
593 crb::Releasable::Ptr releasable (buffer->obtainLock ());
594
595 unsigned int valueMask = CWX | CWY;
596
597 /* Queue locked */
598 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
599
600 buffer->pushFrameRequest (xwc, valueMask);
601
602 /* Queue forceably unlocked, locks rearmed */
603 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
604 EXPECT_CALL (*lock, lock ());
605
606 /* Expect a call to XGetWindowAttributes */
607 XWindowAttributes xwa;
608 EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
609 .WillOnce (
610 DoAll (
611 SetArgReferee <0> (xwa),
612 Return (true)));
613
614 buffer->queryFrameAttributes (xwa);
615}
616
617TEST_F (ConfigureRequestBufferLockBehaviour, QueryShapeRectanglesDispatchAndRearm)
618{
619 /* Locks get armed on construction */
620 EXPECT_CALL (*lock, lock ());
621
622 crb::Releasable::Ptr releasable (buffer->obtainLock ());
623
624 unsigned int valueMask = CWX | CWY;
625
626 /* Queue locked */
627 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
628
629 buffer->pushFrameRequest (xwc, valueMask);
630
631 /* Queue forceably unlocked, locks rearmed */
632 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
633 EXPECT_CALL (*lock, lock ());
634
635 /* Expect a call to XGetWindowAttributes */
636 XWindowAttributes xwa;
637 EXPECT_CALL (syncServerWindow, queryFrameAttributes (_))
638 .WillOnce (
639 DoAll (
640 SetArgReferee <0> (xwa),
641 Return (true)));
642
643 buffer->queryFrameAttributes (xwa);
644}
645
646TEST_F (ConfigureRequestBufferLockBehaviour, ForceReleaseDispatchAndRearm)
647{
648 /* Locks get armed on construction */
649 EXPECT_CALL (*lock, lock ());
650
651 crb::Releasable::Ptr releasable (buffer->obtainLock ());
652
653 unsigned int valueMask = CWX | CWY;
654
655 /* Queue locked */
656 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _)).Times (0);
657
658 buffer->pushFrameRequest (xwc, valueMask);
659
660 /* Queue forceably unlocked, locks rearmed */
661 EXPECT_CALL (asyncServerWindow, requestConfigureOnFrame (_, _));
662 EXPECT_CALL (*lock, lock ());
663
664 /* Force release */
665 buffer->forceRelease ();
666}
667

Subscribers

People subscribed via source and target branches