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: 2162 lines (+1313/-302)
16 files modified
debian/changelog (+1/-1)
plugins/opengl/CMakeLists.txt (+6/-0)
plugins/opengl/include/opengl/framebufferobject.h (+180/-41)
plugins/opengl/include/opengl/opengl-api.h (+42/-0)
plugins/opengl/include/opengl/opengl.h (+76/-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 (+236/-0)
plugins/opengl/src/framebufferobject.cpp (+105/-104)
plugins/opengl/src/paint.cpp (+8/-80)
plugins/opengl/src/privates.h (+49/-7)
plugins/opengl/src/screen.cpp (+245/-34)
plugins/water/src/water.cpp (+17/-9)
plugins/water/src/water.h (+4/-4)
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 Approve
Sam Spilsbury Pending
jenkins continuous-integration Pending
Review via email: mp+147541@code.launchpad.net

This proposal supersedes a proposal from 2012-12-07.

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

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 :

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 :

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 :

>
> 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 :

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

Merge lp:compiz

3407. By Sam Spilsbury

Remove referenes to configure buffers

3408. By Sam Spilsbury

Revert trunk merge as it was broken

3409. By Sam Spilsbury

Merge lp:compiz

3410. By Sam Spilsbury

Unrevert changes which shouldn't have been reverted

3411. By Sam Spilsbury

Another botched merge

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

Merge lp:compiz

3413. By Sam Spilsbury

Fix merge errors

3414. By Sam Spilsbury

Merge lp:compiz

3415. By Sam Spilsbury

Revert more changes which should not have happened

3416. By Sam Spilsbury

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

3417. By Sam Spilsbury

Merge lp:compiz

3418. By Sam Spilsbury

Merge lp:compiz

3419. By Sam Spilsbury

Unrevert changes reverted by a merge

Unmerged revisions

3419. By Sam Spilsbury

Unrevert changes reverted by a merge

3418. By Sam Spilsbury

Merge lp:compiz

3417. By Sam Spilsbury

Merge lp:compiz

3416. By Sam Spilsbury

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

3415. By Sam Spilsbury

Revert more changes which should not have happened

3414. By Sam Spilsbury

Merge lp:compiz

3413. By Sam Spilsbury

Fix merge errors

3412. By Sam Spilsbury

Merge lp:compiz

3411. By Sam Spilsbury

Another botched merge

3410. By Sam Spilsbury

Unrevert changes which shouldn't have been reverted

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2013-02-08 04:01:48 +0000
3+++ debian/changelog 2013-02-12 04:56:22 +0000
4@@ -30,7 +30,7 @@
5
6 compiz (1:0.9.9~daily13.02.04-0ubuntu1) raring; urgency=low
7
8- [ Marco Trevisan (Treviño) ]
9+ [ Marco Trevisan (Treviño) ]
10 * Spread - Window glow is incorrectly painted in the screen when
11 switching spreaded application (LP: #1109805)
12
13
14=== modified file 'plugins/opengl/CMakeLists.txt'
15--- plugins/opengl/CMakeLists.txt 2012-12-12 07:33:12 +0000
16+++ plugins/opengl/CMakeLists.txt 2013-02-12 04:56:22 +0000
17@@ -5,15 +5,21 @@
18 set (INTERNAL_LIBRARIES
19 compiz_opengl_double_buffer
20 compiz_opengl_fsregion
21+ compiz_opengl_framebuffer_direct_draw
22 compiz_opengl_blacklist
23 compiz_opengl_glx_tfp_bind
24 )
25
26+set (COMPIZ_OPENGL_PLUGIN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
27+set (COMPIZ_OPENGL_PLUGIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
28+
29 add_subdirectory (src/doublebuffer)
30 add_subdirectory (src/fsregion)
31+add_subdirectory (src/fbdirectdraw)
32 add_subdirectory (src/blacklist)
33 add_subdirectory (src/glxtfpbind)
34
35+include_directories (src/fbdirectdraw/include)
36 include_directories (src/glxtfpbind/include)
37
38 if (USE_GLES)
39
40=== modified file 'plugins/opengl/include/opengl/framebufferobject.h'
41--- plugins/opengl/include/opengl/framebufferobject.h 2012-08-09 02:19:26 +0000
42+++ plugins/opengl/include/opengl/framebufferobject.h 2013-02-12 04:56:22 +0000
43@@ -26,29 +26,175 @@
44 #ifndef _COMPIZ_GLFRAMEBUFFEROBJECT_H
45 #define _COMPIZ_GLFRAMEBUFFEROBJECT_H
46
47-#include <opengl/opengl.h>
48+#include <list>
49+#include <boost/function.hpp>
50+#include <opengl/opengl-api.h>
51+#include <core/size.h>
52+#include <core/rect.h>
53+
54+class GLVertexBuffer;
55+class GLTexture;
56+
57+namespace compiz
58+{
59+namespace opengl
60+{
61+typedef enum _BlitMask
62+{
63+ ColorData = (1 << 0),
64+ StencilData = (1 << 1)
65+} BlitMask;
66+
67+typedef enum _Filter
68+{
69+ Fast = 0,
70+ Good = 1,
71+} Filter;
72+
73+typedef enum _BindPoint
74+{
75+ Read = 0,
76+ Draw = 1
77+} BindPoint;
78+
79+class BindableFramebuffer
80+{
81+ public:
82+
83+ virtual ~BindableFramebuffer () {}
84+
85+ virtual GLuint getResourceId () const = 0;
86+ virtual bool setBindStatus (GLenum) = 0;
87+ virtual void updateAllocation (GLenum) = 0;
88+};
89+
90+class BindLocation
91+{
92+ public:
93+
94+ virtual ~BindLocation () {}
95+
96+ /**
97+ * Bind the specified BindableFramebuffer to this bind location
98+ * usually either as the read target or the draw target
99+ *
100+ * The previous FBO is no longer bound. If it was bound to the
101+ * draw target, it will be safe to use its texture.
102+ *
103+ * This returns the last-bound BindableFramebuffer object on
104+ * success and NULL on failure (no change). Call this again
105+ * in order to restore that framebuffer
106+ */
107+ virtual BindableFramebuffer * bind (BindableFramebuffer *) = 0;
108+};
109+
110+typedef boost::function <bool (const CompRect &src,
111+ const CompRect &dst,
112+ GLbitfield mask,
113+ GLenum filter)> RectangularDraw;
114+typedef std::list <RectangularDraw> RectangularDrawList;
115+
116+class DirectDrawStrategies
117+{
118+ public:
119+
120+ typedef boost::shared_ptr <DirectDrawStrategies> Ptr;
121+
122+ virtual ~DirectDrawStrategies () {}
123+ virtual void draw (const CompRect &src,
124+ const CompRect &dst,
125+ BlitMask mask,
126+ Filter filter) = 0;
127+};
128+
129+class FramebufferObject
130+{
131+ public:
132+
133+ virtual ~FramebufferObject () {}
134+
135+ /**
136+ * Ensure the texture is of the given size, recreating it if needed,
137+ * and replace the FBO color attachment with it. The texture contents
138+ * become undefined, unless specified in the 'image' argument.
139+ * When specifying 'image', it's also possible to pass-in the
140+ * desired image's 'format' and 'type'.
141+ *
142+ * Returns true on success, and false on texture allocation failure.
143+ */
144+ virtual bool allocate (const CompSize &size,
145+ const char *image = NULL,
146+ GLenum format = GL_RGBA,
147+ GLenum type = GL_UNSIGNED_BYTE) = 0;
148+
149+ /**
150+ * Check the FBO completeness. Returns true on complete.
151+ * Otherwise returns false and reports the error to log.
152+ */
153+ virtual bool checkStatus () = 0;
154+
155+ /**
156+ * Return a pointer to the texture that is the color attachment.
157+ * This will return NULL, if allocate () has not been called, or
158+ * the last allocate () call failed.
159+ */
160+ virtual GLTexture * tex () = 0;
161+};
162+
163+class DirectDrawObject :
164+ virtual public compiz::opengl::FramebufferObject,
165+ virtual public compiz::opengl::BindableFramebuffer
166+{
167+ public:
168+
169+ virtual ~DirectDrawObject () {};
170+
171+ /**
172+ * Draws a region of the framebuffer object as specified in
173+ * framebuffer-specified co-ordinates as @src co-ordinates in
174+ * the buffer currently bound co-ordinates @dst . @mask indicates
175+ * what kind of data should be propogated downwards. @filter indicates
176+ * what kind of filter should be used when drawing this buffer
177+ *
178+ * This since this code only draws a rectangular region from one
179+ * framebuffer to another, it will try and use the fastest codepath
180+ * possible, falling back to a simple textured draw if
181+ * glBlitFramebuffer is not available
182+ *
183+ */
184+ virtual void directDraw (const CompRect &src,
185+ const CompRect &dst,
186+ compiz::opengl::BlitMask mask,
187+ compiz::opengl::Filter filter) = 0;
188+};
189+
190+namespace impl
191+{
192+namespace cgl = compiz::opengl;
193
194 struct PrivateGLFramebufferObject;
195
196-/**
197- * Class representing a framebuffer object in GL, supporting only one
198- * color attachment as per GLES 2 spec. The color attachment is referred
199- * to as the texture (of the FBO).
200- *
201- * Usage:
202- * 1. create a GLFramebufferObject (requires a GL context)
203- * 2. call allocate (size), and check status ()
204- * 3. old = bind ()
205- * 4. do your rendering
206- * 5. rebind (old)
207- * 6. use the rendered texture via tex ()
208- * 7. go to 2 or 3, or delete to quit (requires a GL context)
209- */
210-class GLFramebufferObject
211-{
212- public:
213- GLFramebufferObject ();
214- ~GLFramebufferObject ();
215+class FBOBindLocation :
216+ public cgl::BindLocation
217+{
218+ public:
219+
220+ FBOBindLocation (GLenum binding, BindableFramebuffer *back);
221+ BindableFramebuffer * bind (BindableFramebuffer *);
222+
223+ private:
224+
225+ class Private;
226+ std::auto_ptr <Private> priv;
227+};
228+
229+class FramebufferObject :
230+ public cgl::FramebufferObject,
231+ public cgl::BindableFramebuffer
232+{
233+ public:
234+ FramebufferObject ();
235+ ~FramebufferObject ();
236
237 /**
238 * Ensure the texture is of the given size, recreating it if needed,
239@@ -65,26 +211,6 @@
240 GLenum type = GL_UNSIGNED_BYTE);
241
242 /**
243- * Bind this as the current FBO, previous binding in GL context is
244- * undone. GL rendering is now targeted to this FBO.
245- * Returns a pointer to the previously bound FBO, or NULL if
246- * the previous binding was zero (the window system provided
247- * framebuffer).
248- *
249- * The previous FBO is no longer bound, so you can use its
250- * texture. To restore the previous FBO, call rebind (FBO) with
251- * the returned pointer as the argument.
252- */
253- GLFramebufferObject *bind ();
254-
255- /**
256- * Bind the given FBO as the current FBO, without looking up the
257- * previous binding. The argument can be NULL, in which case the
258- * window system provided framebuffer gets bound (FBO is unbound).
259- */
260- static void rebind (GLFramebufferObject *fbo);
261-
262- /**
263 * Check the FBO completeness. Returns true on complete.
264 * Otherwise returns false and reports the error to log.
265 */
266@@ -95,10 +221,23 @@
267 * This will return NULL, if allocate () has not been called, or
268 * the last allocate () call failed.
269 */
270- GLTexture *tex ();
271+ GLTexture * tex ();
272
273 private:
274+
275+ /**
276+ * Returns the framebuffer identifier
277+ */
278+ GLuint getResourceId () const;
279+ bool setBindStatus (GLenum);
280+ void updateAllocation (GLenum bindingLocation);
281+
282 PrivateGLFramebufferObject *priv;
283 };
284+}
285+}
286+}
287+
288+typedef compiz::opengl::impl::FramebufferObject GLFramebufferObject;
289
290 #endif // _COMPIZ_GLFRAMEBUFFEROBJECT_H
291
292=== added file 'plugins/opengl/include/opengl/opengl-api.h'
293--- plugins/opengl/include/opengl/opengl-api.h 1970-01-01 00:00:00 +0000
294+++ plugins/opengl/include/opengl/opengl-api.h 2013-02-12 04:56:22 +0000
295@@ -0,0 +1,42 @@
296+/*
297+ * Copyright © 2008 Dennis Kasprzyk
298+ * Copyright © 2007 Novell, Inc.
299+ *
300+ * Permission to use, copy, modify, distribute, and sell this software
301+ * and its documentation for any purpose is hereby granted without
302+ * fee, provided that the above copyright notice appear in all copies
303+ * and that both that copyright notice and this permission notice
304+ * appear in supporting documentation, and that the name of
305+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
306+ * distribution of the software without specific, written prior permission.
307+ * Dennis Kasprzyk makes no representations about the suitability of this
308+ * software for any purpose. It is provided "as is" without express or
309+ * implied warranty.
310+ *
311+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
312+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
313+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
314+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
315+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
316+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
317+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
318+ *
319+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
320+ * David Reveman <davidr@novell.com>
321+ */
322+
323+#ifndef _COMPIZ_OPENGL_API_H
324+#define _COMPIZ_OPENGL_API_H
325+
326+#ifdef USE_GLES
327+#define SUPPORT_X11
328+#include <GLES2/gl2.h>
329+#include <GLES2/gl2ext.h>
330+#include <EGL/egl.h>
331+#include <EGL/eglext.h>
332+#else
333+#include <GL/gl.h>
334+#include <GL/glx.h>
335+#endif
336+
337+#endif
338
339=== modified file 'plugins/opengl/include/opengl/opengl.h'
340--- plugins/opengl/include/opengl/opengl.h 2013-01-10 09:23:24 +0000
341+++ plugins/opengl/include/opengl/opengl.h 2013-02-12 04:56:22 +0000
342@@ -28,29 +28,19 @@
343 #ifndef _COMPIZ_OPENGL_H
344 #define _COMPIZ_OPENGL_H
345
346-#ifdef USE_GLES
347-#define SUPPORT_X11
348-#include <GLES2/gl2.h>
349-#include <GLES2/gl2ext.h>
350-#include <EGL/egl.h>
351-#include <EGL/eglext.h>
352-#else
353-#include <GL/gl.h>
354-#include <GL/glx.h>
355-#endif
356+#include <opengl/opengl-api.h>
357
358 #include <core/size.h>
359 #include <core/pluginclasshandler.h>
360
361 #include <opengl/matrix.h>
362 #include <opengl/texture.h>
363-#include <opengl/framebufferobject.h>
364 #include <opengl/vertexbuffer.h>
365 #include <opengl/program.h>
366 #include <opengl/programcache.h>
367 #include <opengl/shadercache.h>
368
369-#define COMPIZ_OPENGL_ABI 6
370+#define COMPIZ_OPENGL_ABI 7
371
372 /*
373 * Some plugins check for #ifdef USE_MODERN_COMPIZ_GL. Support it for now, but
374@@ -84,9 +74,38 @@
375 extern const float GREEN_SATURATION_WEIGHT;
376 extern const float BLUE_SATURATION_WEIGHT;
377
378+class GLScreen;
379 class PrivateGLScreen;
380 class PrivateGLWindow;
381
382+namespace compiz
383+{
384+namespace opengl
385+{
386+typedef boost::function <bool (const CompRect &src,
387+ const CompRect &dst,
388+ GLbitfield mask,
389+ GLenum filter)> BlitFramebufferFunc;
390+
391+class DirectDrawObject;
392+class FramebufferObject;
393+class BindableFramebuffer;
394+
395+/**
396+ * Convenience method to construct a framebuffer object that
397+ * supports GLX_EXT_blit_framebuffer and a fallback path
398+ */
399+DirectDrawObject *createBlittableFramebufferObjectWithFallback(const CompSize &sz, GLScreen *gScreen);
400+
401+namespace impl
402+{
403+class FramebufferObject;
404+}
405+}
406+}
407+
408+typedef compiz::opengl::impl::FramebufferObject GLFramebufferObject;
409+
410 extern GLushort defaultColor[4];
411
412 #ifndef GLX_EXT_texture_from_pixmap
413@@ -313,6 +332,18 @@
414 GLsizei width,
415 GLsizei height);
416
417+ /* GLX_EXT_blit_framebuffer */
418+ typedef void (*GLBlitFramebufferProc) (GLint srcX0,
419+ GLint srcY0,
420+ GLint srcX1,
421+ GLint srcY1,
422+ GLint dstX0,
423+ GLint dstY0,
424+ GLint dstX1,
425+ GLint dstY1,
426+ GLbitfield mask,
427+ GLenum filter);
428+
429
430 /* GL_ARB_shader_objects */
431 #ifndef USE_GLES
432@@ -413,11 +444,12 @@
433 extern GLDisableVertexAttribArrayProc disableVertexAttribArray;
434 extern GLVertexAttribPointerProc vertexAttribPointer;
435
436- extern GLGenRenderbuffersProc genRenderbuffers;
437- extern GLDeleteRenderbuffersProc deleteRenderbuffers;
438- extern GLBindRenderbufferProc bindRenderbuffer;
439+ extern GLGenRenderbuffersProc genRenderbuffers;
440+ extern GLDeleteRenderbuffersProc deleteRenderbuffers;
441+ extern GLBindRenderbufferProc bindRenderbuffer;
442 extern GLFramebufferRenderbufferProc framebufferRenderbuffer;
443- extern GLRenderbufferStorageProc renderbufferStorage;
444+ extern GLRenderbufferStorageProc renderbufferStorage;
445+ extern GLBlitFramebufferProc blitFramebuffer;
446
447 #ifndef USE_GLES
448 extern GLCreateShaderObjectARBProc createShaderObjectARB;
449@@ -579,7 +611,6 @@
450 extern GLScreenPaintAttrib defaultScreenPaintAttrib;
451
452 class GLScreen;
453-class GLFramebufferObject;
454 class GLScreenInterface;
455 extern template class WrapableInterface<GLScreen, GLScreenInterface>;
456
457@@ -658,9 +689,9 @@
458 * @param scratchFbo Describes the final composited FBO that is
459 * to be rendered.
460 */
461- virtual void glPaintCompositedOutput (const CompRegion &region,
462- GLFramebufferObject *fbo,
463- unsigned int mask);
464+ virtual void glPaintCompositedOutput (const CompRegion &region,
465+ compiz::opengl::DirectDrawObject *fbo,
466+ unsigned int mask);
467
468 /**
469 * Hookable function used by plugins to determine stenciling mask
470@@ -759,13 +790,36 @@
471 /**
472 * Returns the FBO compiz is using for the screen
473 */
474- GLFramebufferObject *fbo ();
475+ compiz::opengl::FramebufferObject * fbo ();
476+
477+ /**
478+ * Binds a framebuffer for drawing, returns the old bindable
479+ */
480+ compiz::opengl::BindableFramebuffer *
481+ bindFramebufferForDrawing (compiz::opengl::BindableFramebuffer *);
482+
483+ /**
484+ * Binds a framebuffer for reading, returns the old reading
485+ */
486+ compiz::opengl::BindableFramebuffer *
487+ bindFramebufferForReading (compiz::opengl::BindableFramebuffer *);
488+
489+ /**
490+ * Gets the backbuffer as a BindableFramebuffer
491+ */
492+ compiz::opengl::BindableFramebuffer *
493+ backbuffer ();
494
495 /**
496 * Returns a default icon texture
497 */
498 GLTexture *defaultIcon ();
499
500+ /**
501+ * Returns the current framebuffer function for blitting the framebuffer
502+ */
503+ const compiz::opengl::BlitFramebufferFunc & blitFramebufferFunc ();
504+
505 void resetRasterPos ();
506
507 bool glInitContext (XVisualInfo *);
508@@ -786,7 +840,7 @@
509
510 WRAPABLE_HND (5, GLScreenInterface, GLMatrix *, projectionMatrix);
511 WRAPABLE_HND (6, GLScreenInterface, void, glPaintCompositedOutput,
512- const CompRegion &, GLFramebufferObject *, unsigned int);
513+ const CompRegion &, compiz::opengl::DirectDrawObject *, unsigned int);
514
515 WRAPABLE_HND (7, GLScreenInterface, void, glBufferStencil, const GLMatrix &,
516 GLVertexBuffer &,
517
518=== added directory 'plugins/opengl/src/fbdirectdraw'
519=== added file 'plugins/opengl/src/fbdirectdraw/CMakeLists.txt'
520--- plugins/opengl/src/fbdirectdraw/CMakeLists.txt 1970-01-01 00:00:00 +0000
521+++ plugins/opengl/src/fbdirectdraw/CMakeLists.txt 2013-02-12 04:56:22 +0000
522@@ -0,0 +1,32 @@
523+INCLUDE_DIRECTORIES (
524+ ${COMPIZ_OPENGL_PLUGIN_SOURCE_DIR}
525+ ${COMPIZ_OPENGL_PLUGIN_INCLUDE_DIR}
526+ ${CMAKE_CURRENT_SOURCE_DIR}/include
527+ ${CMAKE_CURRENT_SOURCE_DIR}/src
528+
529+ ${Boost_INCLUDE_DIRS}
530+)
531+
532+LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
533+
534+SET(
535+ SRCS
536+ ${CMAKE_CURRENT_SOURCE_DIR}/src/framebuffer-direct-draw.cpp
537+)
538+
539+ADD_LIBRARY(
540+ compiz_opengl_framebuffer_direct_draw STATIC
541+
542+ ${SRCS}
543+)
544+
545+if (COMPIZ_BUILD_TESTING)
546+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
547+endif (COMPIZ_BUILD_TESTING)
548+
549+TARGET_LINK_LIBRARIES(
550+ compiz_opengl_framebuffer_direct_draw
551+
552+ compiz_region
553+ compiz_logmessage
554+)
555
556=== added directory 'plugins/opengl/src/fbdirectdraw/include'
557=== added file 'plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h'
558--- plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h 1970-01-01 00:00:00 +0000
559+++ plugins/opengl/src/fbdirectdraw/include/framebuffer-direct-draw.h 2013-02-12 04:56:22 +0000
560@@ -0,0 +1,111 @@
561+/*
562+ * Compiz, opengl plugin, FramebufferDirectDraw class
563+ *
564+ * Copyright (c) 2012 Canonical Ltd.
565+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
566+ *
567+ * Permission is hereby granted, free of charge, to any person obtaining a
568+ * copy of this software and associated documentation files (the "Software"),
569+ * to deal in the Software without restriction, including without limitation
570+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
571+ * and/or sell copies of the Software, and to permit persons to whom the
572+ * Software is furnished to do so, subject to the following conditions:
573+ *
574+ * The above copyright notice and this permission notice shall be included in
575+ * all copies or substantial portions of the Software.
576+ *
577+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
578+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
579+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
580+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
581+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
582+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
583+ * DEALINGS IN THE SOFTWARE.
584+ */
585+#ifndef _COMPIZ_OPENGL_FRAMEBUFFER_DIRECT_DRAW_H
586+#define _COMPIZ_OPENGL_FRAMEBUFFER_DIRECT_DRAW_H
587+
588+#include <memory>
589+#include <boost/shared_ptr.hpp>
590+#include <core/rect.h>
591+#include <opengl/framebufferobject.h>
592+
593+class GLVertexBuffer;
594+
595+namespace compiz
596+{
597+namespace opengl
598+{
599+namespace impl
600+{
601+namespace cglfb = compiz::opengl;
602+
603+class PrivateDirectDrawStrategies;
604+
605+class DirectDrawStrategies :
606+ public cglfb::DirectDrawStrategies
607+{
608+ public:
609+
610+ typedef boost::shared_ptr <DirectDrawStrategies> Ptr;
611+
612+ DirectDrawStrategies (const RectangularDrawList &strategies);
613+
614+ void draw (const CompRect &src,
615+ const CompRect &dst,
616+ BlitMask mask,
617+ Filter filter);
618+
619+ private:
620+
621+ std::auto_ptr <PrivateDirectDrawStrategies> priv;
622+};
623+
624+class PrivateDirectDrawObject;
625+
626+class DirectDrawObject :
627+ virtual public cglfb::FramebufferObject,
628+ public cglfb::DirectDrawObject
629+{
630+ public:
631+
632+ DirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &,
633+ const boost::shared_ptr <cglfb::FramebufferObject> &,
634+ const boost::shared_ptr <cglfb::BindableFramebuffer> &);
635+
636+ bool allocate (const CompSize &size,
637+ const char *image = NULL,
638+ GLenum format = GL_RGBA,
639+ GLenum type = GL_UNSIGNED_BYTE);
640+ bool checkStatus ();
641+ GLTexture * tex ();
642+
643+ void directDraw (const CompRect &src,
644+ const CompRect &dst,
645+ cglfb::BlitMask mask,
646+ cglfb::Filter filter);
647+
648+ private:
649+
650+ GLuint getResourceId () const;
651+ bool setBindStatus (GLenum);
652+ void updateAllocation (GLenum);
653+
654+ PrivateDirectDrawObject *priv;
655+};
656+
657+typedef boost::function <cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *)>
658+ BindReadBufferFunc;
659+
660+bool rectangleDrawFromReadBuffer (const CompRect &src,
661+ const CompRect &dst,
662+ GLbitfield mask,
663+ GLenum filter,
664+ cglfb::BindableFramebuffer *bindable,
665+ const BindReadBufferFunc &func,
666+ cglfb::RectangularDraw strategy);
667+}
668+}
669+}
670+
671+#endif
672
673=== added directory 'plugins/opengl/src/fbdirectdraw/src'
674=== added file 'plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp'
675--- plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp 1970-01-01 00:00:00 +0000
676+++ plugins/opengl/src/fbdirectdraw/src/framebuffer-direct-draw.cpp 2013-02-12 04:56:22 +0000
677@@ -0,0 +1,177 @@
678+/*
679+ * Compiz, opengl plugin, DirectDrawFramebufferStrategies class
680+ *
681+ * Copyright (c) 2012 Canonical Ltd.
682+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
683+ *
684+ * Permission is hereby granted, free of charge, to any person obtaining a
685+ * copy of this software and associated documentation files (the "Software"),
686+ * to deal in the Software without restriction, including without limitation
687+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
688+ * and/or sell copies of the Software, and to permit persons to whom the
689+ * Software is furnished to do so, subject to the following conditions:
690+ *
691+ * The above copyright notice and this permission notice shall be included in
692+ * all copies or substantial portions of the Software.
693+ *
694+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
695+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
696+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
697+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
698+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
699+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
700+ * DEALINGS IN THE SOFTWARE.
701+ */
702+#include "framebuffer-direct-draw.h"
703+
704+namespace cglfb = compiz::opengl;
705+namespace cglfbi = compiz::opengl::impl;
706+
707+class GLTexture;
708+class GLVertexBuffer;
709+
710+namespace compiz
711+{
712+namespace opengl
713+{
714+namespace impl
715+{
716+class PrivateDirectDrawStrategies
717+{
718+ public:
719+
720+ PrivateDirectDrawStrategies (const cglfb::RectangularDrawList &strategies) :
721+ rectDrawList (strategies)
722+ {
723+ }
724+
725+ cglfb::RectangularDrawList rectDrawList;
726+};
727+
728+class PrivateDirectDrawObject
729+{
730+ public:
731+
732+ PrivateDirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &strategies,
733+ const boost::shared_ptr <cglfb::FramebufferObject> &object,
734+ const boost::shared_ptr <cglfb::BindableFramebuffer> &bindable) :
735+ directDrawStrategies (strategies),
736+ framebufferObject (object),
737+ bindableFramebuffer (bindable)
738+ {
739+ };
740+
741+ boost::shared_ptr <cglfb::DirectDrawStrategies> directDrawStrategies;
742+ boost::shared_ptr <cglfb::FramebufferObject> framebufferObject;
743+ boost::shared_ptr <cglfb::BindableFramebuffer> bindableFramebuffer;
744+};
745+}
746+}
747+}
748+
749+cglfbi::DirectDrawObject::DirectDrawObject (const boost::shared_ptr <cglfb::DirectDrawStrategies> &strategies,
750+ const boost::shared_ptr <cglfb::FramebufferObject> &object,
751+ const boost::shared_ptr <cglfb::BindableFramebuffer> &bindable) :
752+ priv (new cglfbi::PrivateDirectDrawObject (strategies, object, bindable))
753+{
754+}
755+
756+bool
757+cglfbi::DirectDrawObject::allocate (const CompSize &size, const char *image,
758+ GLenum format, GLenum type)
759+{
760+ return priv->framebufferObject->allocate (size, image, format, type);
761+}
762+
763+bool
764+cglfbi::DirectDrawObject::checkStatus ()
765+{
766+ return priv->framebufferObject->checkStatus ();
767+}
768+
769+GLTexture *
770+cglfbi::DirectDrawObject::tex ()
771+{
772+ return priv->framebufferObject->tex ();
773+}
774+
775+GLuint
776+cglfbi::DirectDrawObject::getResourceId () const
777+{
778+ return priv->bindableFramebuffer->getResourceId ();
779+}
780+
781+bool
782+cglfbi::DirectDrawObject::setBindStatus (GLenum status)
783+{
784+ return priv->bindableFramebuffer->setBindStatus (status);
785+}
786+
787+void
788+cglfbi::DirectDrawObject::updateAllocation (GLenum bindPoint)
789+{
790+ return priv->bindableFramebuffer->updateAllocation (bindPoint);
791+}
792+
793+void
794+cglfbi::DirectDrawObject::directDraw (const CompRect &src,
795+ const CompRect &dst,
796+ cglfb::BlitMask mask,
797+ cglfb::Filter filter)
798+{
799+ if (!checkStatus ())
800+ return;
801+
802+ priv->directDrawStrategies->draw (src, dst, mask, filter);
803+}
804+
805+bool
806+cglfbi::rectangleDrawFromReadBuffer (const CompRect &src,
807+ const CompRect &dst,
808+ GLbitfield mask,
809+ GLenum filter,
810+ cglfb::BindableFramebuffer *bindable,
811+ const cglfbi::BindReadBufferFunc &bindReadBuffer,
812+ cglfb::RectangularDraw strategy)
813+{
814+ bool status = false;
815+ /* Bind to the read framebuffer first */
816+ cglfb::BindableFramebuffer *old = bindReadBuffer (bindable);
817+
818+ if (old)
819+ status = strategy (src, dst, mask, filter);
820+
821+ /* Intentionally not rebinding the old one */
822+
823+ return status;
824+}
825+
826+cglfbi::DirectDrawStrategies::DirectDrawStrategies (const cglfb::RectangularDrawList &strategies) :
827+ priv (new cglfbi::PrivateDirectDrawStrategies (strategies))
828+{
829+}
830+
831+void
832+cglfbi::DirectDrawStrategies::draw (const CompRect &src,
833+ const CompRect &dst,
834+ cglfb::BlitMask mask,
835+ cglfb::Filter filter)
836+{
837+ if (!mask)
838+ return;
839+
840+ const GLbitfield glMask = (mask & cglfb::ColorData ? GL_COLOR_BUFFER_BIT : 0) |
841+ (mask & cglfb::StencilData ? GL_STENCIL_BUFFER_BIT : 0);
842+ const GLenum glFilter = (filter == cglfb::Fast ? GL_NEAREST : GL_LINEAR);
843+
844+ while (!priv->rectDrawList.empty ())
845+ {
846+ const cglfb::RectangularDraw &strategy = priv->rectDrawList.back ();
847+
848+ /* If one method fails, try the next */
849+ if (!strategy (src, dst, glMask, glFilter))
850+ priv->rectDrawList.pop_back ();
851+ else
852+ break;
853+ }
854+}
855
856=== added directory 'plugins/opengl/src/fbdirectdraw/tests'
857=== added file 'plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt'
858--- plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
859+++ plugins/opengl/src/fbdirectdraw/tests/CMakeLists.txt 2013-02-12 04:56:22 +0000
860@@ -0,0 +1,24 @@
861+find_library (GMOCK_LIBRARY gmock)
862+find_library (GMOCK_MAIN_LIBRARY gmock_main)
863+
864+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
865+ message ("Google Mock and Google Test not found - cannot build tests!")
866+ set (COMPIZ_BUILD_TESTING OFF)
867+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
868+
869+include_directories (${GTEST_INCLUDE_DIRS})
870+
871+link_directories (${COMPIZ_LIBRARY_DIRS})
872+
873+add_executable (compiz_test_opengl_framebuffer_direct_draw
874+ ${CMAKE_CURRENT_SOURCE_DIR}/test-opengl-framebuffer-direct-draw.cpp)
875+
876+target_link_libraries (compiz_test_opengl_framebuffer_direct_draw
877+ compiz_opengl_framebuffer_direct_draw
878+ ${GTEST_BOTH_LIBRARIES}
879+ ${GMOCK_LIBRARY}
880+ ${GMOCK_MAIN_LIBRARY}
881+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
882+ )
883+
884+compiz_discover_tests (compiz_test_opengl_framebuffer_direct_draw COVERAGE compiz_opengl_framebuffer_direct_draw)
885
886=== added file 'plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp'
887--- plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp 1970-01-01 00:00:00 +0000
888+++ plugins/opengl/src/fbdirectdraw/tests/test-opengl-framebuffer-direct-draw.cpp 2013-02-12 04:56:22 +0000
889@@ -0,0 +1,236 @@
890+/*
891+ * Compiz, opengl plugin, DirectDrawFramebufferStrategies class
892+ *
893+ * Copyright (c) 2012 Canonical Ltd.
894+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
895+ *
896+ * Permission is hereby granted, free of charge, to any person obtaining a
897+ * copy of this software and associated documentation files (the "Software"),
898+ * to deal in the Software without restriction, including without limitation
899+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
900+ * and/or sell copies of the Software, and to permit persons to whom the
901+ * Software is furnished to do so, subject to the following conditions:
902+ *
903+ * The above copyright notice and this permission notice shall be included in
904+ * all copies or substantial portions of the Software.
905+ *
906+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
907+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
908+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
909+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
910+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
911+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
912+ * DEALINGS IN THE SOFTWARE.
913+ */
914+#include <memory>
915+#include <boost/function.hpp>
916+#include <boost/bind.hpp>
917+#include <gtest/gtest.h>
918+#include <gmock/gmock.h>
919+#include <opengl/opengl-api.h>
920+#include <opengl/framebufferobject.h>
921+#include "framebuffer-direct-draw.h"
922+
923+using ::testing::Return;
924+using ::testing::_;
925+using ::testing::Expectation;
926+using ::testing::StrictMock;
927+using ::testing::NiceMock;
928+using ::testing::ReturnNull;
929+
930+namespace cglfb = compiz::opengl;
931+namespace cglfbi = compiz::opengl::impl;
932+
933+namespace
934+{
935+class MockDrawStrategy
936+{
937+ public:
938+
939+ MOCK_METHOD4 (draw, bool (const CompRect &,
940+ const CompRect &,
941+ GLbitfield,
942+ GLenum));
943+};
944+
945+class MockBindLocation :
946+ public cglfb::BindLocation
947+{
948+ public:
949+
950+ MOCK_METHOD1 (bind, cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *));
951+};
952+
953+class MockBindable :
954+ public cglfb::BindableFramebuffer
955+{
956+ public:
957+
958+ MOCK_METHOD1 (updateAllocation, void (GLenum));
959+ MOCK_METHOD1 (setBindStatus, bool (GLenum));
960+ MOCK_CONST_METHOD0 (getResourceId, GLuint ());
961+};
962+
963+}
964+
965+class FBDirectDrawStrategies :
966+ public ::testing::Test
967+{
968+ public:
969+
970+ FBDirectDrawStrategies () :
971+ blitFramebuffer (boost::bind (&MockDrawStrategy::draw, &mpfb, _1, _2, _3, _4)),
972+ rtdraw (boost::bind (&MockDrawStrategy::draw, &mdr,
973+ _1, _2, _3, _4))
974+ {
975+ }
976+
977+ void SetUpStrategyList (const cglfb::RectangularDraw &blit,
978+ const cglfb::RectangularDraw &draw)
979+ {
980+ strategyList.clear ();
981+ strategyList.push_back (draw);
982+ strategyList.push_back (blit);
983+ }
984+
985+ virtual void SetUp ()
986+ {
987+ boost::function <cglfb::BindableFramebuffer * (cglfb::BindableFramebuffer *)> readBind
988+ (boost::bind (&MockBindLocation::bind, &mockBindLocation, _1));
989+ blitFramebufferWithReadPushed = boost::bind (&cglfbi::rectangleDrawFromReadBuffer,
990+ _1, _2, _3, _4,
991+ &mockBindable,
992+ readBind,
993+ blitFramebuffer);
994+
995+ SetUpStrategyList (blitFramebuffer, rtdraw);
996+ directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
997+ }
998+
999+ std::auto_ptr <cglfbi::DirectDrawStrategies> directDraw;
1000+ MockDrawStrategy mpfb;
1001+ cglfb::RectangularDraw blitFramebuffer;
1002+ cglfb::RectangularDraw blitFramebufferWithReadPushed;
1003+ MockDrawStrategy mdr;
1004+ StrictMock <MockBindable> mockBindable;
1005+ StrictMock <MockBindLocation> mockBindLocation;
1006+ cglfb::RectangularDraw rtdraw;
1007+ cglfb::RectangularDrawList strategyList;
1008+
1009+};
1010+
1011+TEST_F (FBDirectDrawStrategies, BufferBitsSet)
1012+{
1013+ CompRect srcAndDst (0, 0, 0, 0);
1014+
1015+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, GL_COLOR_BUFFER_BIT |
1016+ GL_STENCIL_BUFFER_BIT,
1017+ _)).WillOnce (Return (true));
1018+
1019+ directDraw->draw (srcAndDst,
1020+ srcAndDst,
1021+ static_cast <cglfb::BlitMask> (cglfb::ColorData |
1022+ cglfb::StencilData),
1023+ cglfb::Good);
1024+}
1025+
1026+TEST_F (FBDirectDrawStrategies, BufferNoBitsSet)
1027+{
1028+ CompRect srcAndDst (0, 0, 0, 0);
1029+
1030+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, 0,
1031+ _)).Times (0);
1032+
1033+ directDraw->draw (srcAndDst,
1034+ srcAndDst,
1035+ static_cast <cglfb::BlitMask> (0),
1036+ cglfb::Good);
1037+}
1038+
1039+TEST_F (FBDirectDrawStrategies, GoodToLinear)
1040+{
1041+ CompRect srcAndDst (0, 0, 0, 0);
1042+
1043+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
1044+ GL_LINEAR)).WillOnce (Return (true));
1045+
1046+ directDraw->draw (srcAndDst,
1047+ srcAndDst,
1048+ cglfb::ColorData,
1049+ cglfb::Good);
1050+}
1051+
1052+TEST_F (FBDirectDrawStrategies, FastToNearest)
1053+{
1054+ CompRect srcAndDst (0, 0, 0, 0);
1055+
1056+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
1057+ GL_NEAREST)).WillOnce (Return (true));
1058+
1059+ directDraw->draw (srcAndDst,
1060+ srcAndDst,
1061+ cglfb::ColorData,
1062+ cglfb::Fast);
1063+}
1064+
1065+TEST_F (FBDirectDrawStrategies, RevertToPaintWhenBlitUnavailable)
1066+{
1067+ CompRect srcAndDst (0, 0, 0, 0);
1068+
1069+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _,
1070+ _)).WillOnce (Return (false));
1071+ EXPECT_CALL (mdr, draw (srcAndDst, srcAndDst, _, _));
1072+
1073+ directDraw->draw (srcAndDst,
1074+ srcAndDst,
1075+ cglfb::ColorData,
1076+ cglfb::Fast);
1077+}
1078+
1079+TEST_F (FBDirectDrawStrategies, RevertOnBlitUnavailablePermanent)
1080+{
1081+ StrictMock <MockDrawStrategy> strictMdr;
1082+ CompRect srcAndDst (0, 0, 0, 0);
1083+
1084+ rtdraw = boost::bind (&MockDrawStrategy::draw, &strictMdr, _1, _2, _3, _4);
1085+
1086+ SetUpStrategyList (blitFramebuffer, rtdraw);
1087+ directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
1088+
1089+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _, _)).WillOnce (Return (false));
1090+ ON_CALL (strictMdr, draw (_, _, _, _)).WillByDefault (Return (true));
1091+ EXPECT_CALL (strictMdr, draw (srcAndDst, srcAndDst, _, _)).Times (2);
1092+
1093+ directDraw->draw (srcAndDst,
1094+ srcAndDst,
1095+ cglfb::ColorData,
1096+ cglfb::Fast);
1097+ directDraw->draw (srcAndDst,
1098+ srcAndDst,
1099+ cglfb::ColorData,
1100+ cglfb::Fast);
1101+}
1102+
1103+TEST_F (FBDirectDrawStrategies, BindReadFramebufferOnBlit)
1104+{
1105+ CompRect srcAndDst (0, 0, 0, 0);
1106+
1107+ SetUpStrategyList (blitFramebufferWithReadPushed, rtdraw);
1108+ directDraw.reset (new cglfbi::DirectDrawStrategies (strategyList));
1109+
1110+ MockBindable backBuffer;
1111+
1112+ EXPECT_CALL (mockBindLocation, bind (&mockBindable)).WillOnce (Return (&backBuffer));
1113+ EXPECT_CALL (mpfb, draw (srcAndDst, srcAndDst, _, _)).WillOnce (Return (false));
1114+ ON_CALL (mdr, draw (_, _, _, _)).WillByDefault (Return (true));
1115+ EXPECT_CALL (mdr, draw (srcAndDst, srcAndDst, _, _)).Times (2);
1116+
1117+ directDraw->draw (srcAndDst,
1118+ srcAndDst,
1119+ cglfb::ColorData,
1120+ cglfb::Fast);
1121+ directDraw->draw (srcAndDst,
1122+ srcAndDst,
1123+ cglfb::ColorData,
1124+ cglfb::Fast);
1125+}
1126
1127=== modified file 'plugins/opengl/src/framebufferobject.cpp'
1128--- plugins/opengl/src/framebufferobject.cpp 2012-08-06 09:44:49 +0000
1129+++ plugins/opengl/src/framebufferobject.cpp 2013-02-12 04:56:22 +0000
1130@@ -22,88 +22,96 @@
1131 *
1132 * Authors: Pekka Paalanen <ppaalanen@gmail.com>
1133 */
1134-
1135+#include <memory>
1136 #include <map>
1137+#include <opengl/opengl.h>
1138 #include <opengl/framebufferobject.h>
1139 #include <opengl/texture.h>
1140
1141+#include "framebuffer-direct-draw.h"
1142+
1143+namespace cglfb = compiz::opengl;
1144+namespace cglfbi = compiz::opengl::impl;
1145+
1146+namespace compiz
1147+{
1148+namespace opengl
1149+{
1150+namespace impl
1151+{
1152 struct PrivateGLFramebufferObject
1153 {
1154 PrivateGLFramebufferObject () :
1155 fboId (0),
1156- pushedId (0),
1157 glTex (NULL),
1158 status (-1)
1159 {
1160 }
1161
1162- void pushFBO ();
1163- void popFBO ();
1164-
1165 GLuint fboId;
1166- GLuint pushedId;
1167 GLuint rbStencilId;
1168 GLTexture *glTex;
1169
1170 GLint status;
1171
1172- static GLuint boundId;
1173- static std::map<GLuint, GLFramebufferObject *> idMap;
1174+ std::auto_ptr <cglfb::DirectDrawStrategies> mDirectDraw;
1175+ GLVertexBuffer *vertexBuffer;
1176 };
1177
1178-GLuint PrivateGLFramebufferObject::boundId = 0;
1179-std::map<GLuint, GLFramebufferObject *> PrivateGLFramebufferObject::idMap;
1180-
1181-void
1182-PrivateGLFramebufferObject::pushFBO ()
1183-{
1184- pushedId = boundId;
1185- if (boundId != fboId)
1186- {
1187- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, fboId);
1188- boundId = fboId;
1189- }
1190-}
1191-
1192-void
1193-PrivateGLFramebufferObject::popFBO ()
1194-{
1195- if (boundId != pushedId)
1196- {
1197- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, pushedId);
1198- boundId = pushedId;
1199- }
1200-}
1201-
1202-GLFramebufferObject::GLFramebufferObject () :
1203- priv (new PrivateGLFramebufferObject)
1204+}
1205+}
1206+}
1207+
1208+GLuint
1209+cglfbi::FramebufferObject::getResourceId () const
1210+{
1211+ return priv->fboId;
1212+}
1213+
1214+bool
1215+cglfbi::FramebufferObject::setBindStatus (GLenum status)
1216+{
1217+ priv->status = status;
1218+ return checkStatus ();
1219+}
1220+
1221+void
1222+cglfbi::FramebufferObject::updateAllocation (GLenum bindingLocation)
1223+{
1224+ if (priv->status == -1)
1225+ {
1226+ (*GL::framebufferTexture2D) (bindingLocation, GL::COLOR_ATTACHMENT0,
1227+ priv->glTex->target (),
1228+ priv->glTex->name (), 0);
1229+ (*GL::framebufferRenderbuffer) (bindingLocation, GL::DEPTH_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1230+ (*GL::framebufferRenderbuffer) (bindingLocation, GL::STENCIL_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1231+ }
1232+
1233+}
1234+
1235+cglfbi::FramebufferObject::FramebufferObject () :
1236+ priv (new cglfbi::PrivateGLFramebufferObject ())
1237 {
1238 (*GL::genFramebuffers) (1, &priv->fboId);
1239 (*GL::genRenderbuffers) (1, &priv->rbStencilId);
1240-
1241- if (priv->fboId != 0)
1242- PrivateGLFramebufferObject::idMap[priv->fboId] = this;
1243 }
1244
1245-GLFramebufferObject::~GLFramebufferObject ()
1246+cglfbi::FramebufferObject::~FramebufferObject ()
1247 {
1248 if (priv->glTex)
1249 GLTexture::decRef (priv->glTex);
1250
1251- PrivateGLFramebufferObject::idMap.erase (priv->fboId);
1252 (*GL::deleteFramebuffers) (1, &priv->fboId);
1253 (*GL::deleteRenderbuffers) (1, &priv->rbStencilId);
1254
1255-
1256 delete priv;
1257 }
1258
1259 bool
1260-GLFramebufferObject::allocate (const CompSize &size, const char *image,
1261- GLenum format, GLenum type)
1262+cglfbi::FramebufferObject::allocate (const CompSize &size,
1263+ const char *image,
1264+ GLenum format, GLenum type)
1265 {
1266- priv->status = -1;
1267-
1268 if (!priv->glTex ||
1269 size.width () != priv->glTex->width () ||
1270 size.height () != priv->glTex->height ())
1271@@ -125,86 +133,39 @@
1272 (*GL::bindRenderbuffer) (GL::RENDERBUFFER, priv->rbStencilId);
1273 (*GL::renderbufferStorage) (GL::RENDERBUFFER, GL::DEPTH24_STENCIL8, size.width (), size.height ());
1274 }
1275+
1276+ priv->status = -1;
1277 }
1278
1279- priv->pushFBO ();
1280-
1281- (*GL::framebufferTexture2D) (GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0,
1282- priv->glTex->target (),
1283- priv->glTex->name (), 0);
1284-
1285- priv->status = (*GL::checkFramebufferStatus) (GL::DRAW_FRAMEBUFFER);
1286-
1287- priv->popFBO ();
1288 return true;
1289 }
1290
1291-GLFramebufferObject *
1292-GLFramebufferObject::bind ()
1293-{
1294- GLFramebufferObject *old = NULL;
1295-
1296- if (priv->boundId != 0)
1297- {
1298- std::map<GLuint, GLFramebufferObject *>::iterator it;
1299- it = PrivateGLFramebufferObject::idMap.find (priv->boundId);
1300-
1301- if (it != PrivateGLFramebufferObject::idMap.end ())
1302- old = it->second;
1303- else
1304- compLogMessage ("opengl", CompLogLevelError,
1305- "An FBO without GLFramebufferObject cannot be restored");
1306- }
1307-
1308- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, priv->fboId);
1309- priv->boundId = priv->fboId;
1310-
1311- (*GL::framebufferRenderbuffer) (GL::FRAMEBUFFER, GL::DEPTH_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1312- (*GL::framebufferRenderbuffer) (GL::FRAMEBUFFER, GL::STENCIL_ATTACHMENT, GL::RENDERBUFFER, priv->rbStencilId);
1313-
1314- return old;
1315-}
1316-
1317-// static
1318-void
1319-GLFramebufferObject::rebind (GLFramebufferObject *fbo)
1320-{
1321- GLuint id = fbo ? fbo->priv->fboId : 0;
1322-
1323- if (id != fbo->priv->boundId)
1324- {
1325- (*GL::bindFramebuffer) (GL::FRAMEBUFFER, id);
1326- fbo->priv->boundId = id;
1327- }
1328-}
1329-
1330-static const char *
1331+namespace
1332+{
1333+const char *
1334 getFboErrorString (GLint status)
1335 {
1336 switch (status)
1337 {
1338- case GL::FRAMEBUFFER_COMPLETE:
1339+ case GL::FRAMEBUFFER_COMPLETE:
1340 return "GL::FRAMEBUFFER_COMPLETE";
1341- case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1342+ case GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1343 return "GL::FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
1344- case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1345+ case GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1346 return "GL::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
1347- case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1348+ case GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1349 return "GL::FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
1350- case GL::FRAMEBUFFER_UNSUPPORTED:
1351+ case GL::FRAMEBUFFER_UNSUPPORTED:
1352 return "GL::FRAMEBUFFER_UNSUPPORTED";
1353 default:
1354 return "unexpected status";
1355 }
1356 }
1357+}
1358
1359 bool
1360-GLFramebufferObject::checkStatus ()
1361+cglfbi::FramebufferObject::checkStatus ()
1362 {
1363- priv->pushFBO ();
1364- priv-> status = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER);
1365- priv->popFBO ();
1366-
1367 if (priv->status == static_cast <GLint> (GL::FRAMEBUFFER_COMPLETE))
1368 return true;
1369
1370@@ -215,7 +176,47 @@
1371 }
1372
1373 GLTexture *
1374-GLFramebufferObject::tex ()
1375+cglfbi::FramebufferObject::tex ()
1376 {
1377 return priv->glTex;
1378 }
1379+
1380+class cglfbi::FBOBindLocation::Private
1381+{
1382+ public:
1383+
1384+ Private (GLenum binding,
1385+ cglfb::BindableFramebuffer *back) :
1386+ mCurrentlyBound (back),
1387+ mBindPoint (binding)
1388+ {
1389+ }
1390+
1391+ cglfb::BindableFramebuffer *mCurrentlyBound;
1392+ GLenum mBindPoint;
1393+};
1394+
1395+cglfbi::FBOBindLocation::FBOBindLocation (GLenum binding,
1396+ cglfb::BindableFramebuffer *back) :
1397+ priv (new cglfbi::FBOBindLocation::Private (binding, back))
1398+{
1399+}
1400+
1401+cglfb::BindableFramebuffer *
1402+cglfbi::FBOBindLocation::bind (cglfb::BindableFramebuffer *next)
1403+{
1404+ if (priv->mCurrentlyBound == next)
1405+ return next;
1406+
1407+ (*GL::bindFramebuffer) (priv->mBindPoint, next->getResourceId ());
1408+ next->updateAllocation (priv->mBindPoint);
1409+ if (!next->setBindStatus ((*GL::checkFramebufferStatus) (priv->mBindPoint)))
1410+ {
1411+ (*GL::bindFramebuffer) (priv->mBindPoint, priv->mCurrentlyBound->getResourceId ());
1412+ return NULL;
1413+ }
1414+
1415+ cglfb::BindableFramebuffer *last = priv->mCurrentlyBound;
1416+ priv->mCurrentlyBound = next;
1417+ return last;
1418+}
1419
1420=== modified file 'plugins/opengl/src/paint.cpp'
1421--- plugins/opengl/src/paint.cpp 2013-01-01 10:04:50 +0000
1422+++ plugins/opengl/src/paint.cpp 2013-02-12 04:56:22 +0000
1423@@ -44,6 +44,7 @@
1424 #define DEG2RAD (M_PI / 180.0f)
1425
1426 using namespace compiz::opengl;
1427+namespace cglfb = compiz::opengl;
1428
1429 GLScreenPaintAttrib defaultScreenPaintAttrib = {
1430 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA
1431@@ -669,89 +670,16 @@
1432 }
1433
1434 void
1435-GLScreen::glPaintCompositedOutput (const CompRegion &region,
1436- GLFramebufferObject *fbo,
1437- unsigned int mask)
1438+GLScreen::glPaintCompositedOutput (const CompRegion &region,
1439+ compiz::opengl::DirectDrawObject *fbo,
1440+ unsigned int mask)
1441 {
1442 WRAPABLE_HND_FUNCTN (glPaintCompositedOutput, region, fbo, mask)
1443
1444- GLMatrix sTransform;
1445- const GLTexture::Matrix & texmatrix = fbo->tex ()->matrix ();
1446- GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
1447-
1448- streamingBuffer->begin (GL_TRIANGLES);
1449-
1450- if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
1451- {
1452- GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, 0.0f);
1453- GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, screen->width ());
1454- GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, 0.0f);
1455- GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, screen->height ());
1456-
1457- const GLfloat vertexData[] = {
1458- 0.0f, 0.0f, 0.0f,
1459- 0.0f, (float)screen->height (), 0.0f,
1460- (float)screen->width (), 0.0f, 0.0f,
1461-
1462- 0.0f, (float)screen->height (), 0.0f,
1463- (float)screen->width (), (float)screen->height (), 0.0f,
1464- (float)screen->width (), 0.0f, 0.0f,
1465- };
1466-
1467- const GLfloat textureData[] = {
1468- tx1, ty1,
1469- tx1, ty2,
1470- tx2, ty1,
1471- tx1, ty2,
1472- tx2, ty2,
1473- tx2, ty1,
1474- };
1475-
1476- streamingBuffer->addVertices (6, &vertexData[0]);
1477- streamingBuffer->addTexCoords (0, 6, &textureData[0]);
1478- }
1479- else
1480- {
1481- BoxPtr pBox = const_cast <Region> (region.handle ())->rects;
1482- int nBox = const_cast <Region> (region.handle ())->numRects;
1483-
1484- while (nBox--)
1485- {
1486- GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, pBox->x1);
1487- GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, pBox->x2);
1488- GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y1);
1489- GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y2);
1490-
1491- const GLfloat vertexData[] = {
1492- (float)pBox->x1, (float)pBox->y1, 0.0f,
1493- (float)pBox->x1, (float)pBox->y2, 0.0f,
1494- (float)pBox->x2, (float)pBox->y1, 0.0f,
1495-
1496- (float)pBox->x1, (float)pBox->y2, 0.0f,
1497- (float)pBox->x2, (float)pBox->y2, 0.0f,
1498- (float)pBox->x2, (float)pBox->y1, 0.0f,
1499- };
1500-
1501- const GLfloat textureData[] = {
1502- tx1, ty1,
1503- tx1, ty2,
1504- tx2, ty1,
1505- tx1, ty2,
1506- tx2, ty2,
1507- tx2, ty1,
1508- };
1509-
1510- streamingBuffer->addVertices (6, &vertexData[0]);
1511- streamingBuffer->addTexCoords (0, 6, &textureData[0]);
1512- pBox++;
1513- }
1514- }
1515-
1516- streamingBuffer->end ();
1517- fbo->tex ()->enable (GLTexture::Fast);
1518- sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
1519- streamingBuffer->render (sTransform);
1520- fbo->tex ()->disable ();
1521+ /* Draw every rect individually, this could be a little slow
1522+ * for lots of rects, but the general usecase isn't that */
1523+ foreach (const CompRect &r, region.rects ())
1524+ fbo->directDraw (r, r, cglfb::ColorData, cglfb::Fast);
1525 }
1526
1527 static void
1528
1529=== modified file 'plugins/opengl/src/privates.h'
1530--- plugins/opengl/src/privates.h 2013-01-01 09:41:41 +0000
1531+++ plugins/opengl/src/privates.h 2013-02-12 04:56:22 +0000
1532@@ -29,21 +29,27 @@
1533 #define _OPENGL_PRIVATES_H
1534
1535 #include <memory>
1536-
1537 #include <composite/composite.h>
1538 #include <opengl/opengl.h>
1539 #include <core/atoms.h>
1540-
1541-#ifdef USE_GLES
1542 #include <opengl/framebufferobject.h>
1543-#endif
1544-
1545 #include <opengl/doublebuffer.h>
1546
1547 #include "privatetexture.h"
1548 #include "privatevertexbuffer.h"
1549 #include "opengl_options.h"
1550
1551+namespace compiz
1552+{
1553+ namespace opengl
1554+ {
1555+ namespace impl
1556+ {
1557+ class DirectDrawObject;
1558+ }
1559+ }
1560+}
1561+
1562 extern CompOutput *targetOutput;
1563
1564 class GLDoubleBuffer :
1565@@ -85,6 +91,17 @@
1566 Window mOutput;
1567 };
1568
1569+namespace compiz
1570+{
1571+ namespace opengl
1572+ {
1573+ bool blitFramebufferGLX (const CompRect &src,
1574+ const CompRect &dst,
1575+ GLbitfield mask,
1576+ GLenum filter);
1577+ }
1578+}
1579+
1580 #else
1581
1582 class EGLDoubleBuffer :
1583@@ -108,6 +125,17 @@
1584 EGLSurface const & mSurface;
1585 };
1586
1587+namespace compiz
1588+{
1589+ namespace opengl
1590+ {
1591+ bool blitFramebufferEGL (const CompRect &src,
1592+ const CompRect &dst,
1593+ GLbitfield mask,
1594+ GLenum filter);
1595+ }
1596+}
1597+
1598 #endif
1599
1600 class GLIcon
1601@@ -119,6 +147,16 @@
1602 GLTexture::List textures;
1603 };
1604
1605+class BindableBackbuffer :
1606+ public compiz::opengl::BindableFramebuffer
1607+{
1608+ public:
1609+
1610+ GLuint getResourceId () const;
1611+ bool setBindStatus (GLenum);
1612+ void updateAllocation (GLenum);
1613+};
1614+
1615 class PrivateGLScreen :
1616 public ScreenInterface,
1617 public compiz::composite::PaintHandler,
1618@@ -196,8 +234,9 @@
1619 GLXDoubleBuffer doubleBuffer;
1620 #endif
1621
1622- GLFramebufferObject *scratchFbo;
1623- CompRegion outputRegion;
1624+ std::auto_ptr <compiz::opengl::DirectDrawObject> scratchFbo;
1625+ compiz::opengl::BlitFramebufferFunc blitFramebuffer;
1626+ CompRegion outputRegion;
1627
1628 XRectangle lastViewport;
1629 bool refreshSubBuffer;
1630@@ -221,6 +260,9 @@
1631 Pixmap rootPixmapCopy;
1632 CompSize rootPixmapSize;
1633
1634+ BindableBackbuffer backbuffer;
1635+ compiz::opengl::impl::FBOBindLocation drawFramebufferBinding;
1636+ compiz::opengl::impl::FBOBindLocation readFramebufferBinding;
1637 const char *glVendor, *glRenderer, *glVersion;
1638
1639 mutable CompString prevRegex;
1640
1641=== modified file 'plugins/opengl/src/screen.cpp'
1642--- plugins/opengl/src/screen.cpp 2013-01-09 10:57:03 +0000
1643+++ plugins/opengl/src/screen.cpp 2013-02-12 04:56:22 +0000
1644@@ -36,6 +36,7 @@
1645 #include <boost/make_shared.hpp>
1646
1647 #include "privates.h"
1648+#include "framebuffer-direct-draw.h"
1649 #include "blacklist/blacklist.h"
1650
1651 #include <dlfcn.h>
1652@@ -67,6 +68,26 @@
1653
1654
1655 using namespace compiz::opengl;
1656+namespace cglfb = compiz::opengl;
1657+namespace cgli = compiz::opengl::impl;
1658+
1659+namespace compiz
1660+{
1661+ namespace opengl
1662+ {
1663+#ifndef USE_GLES
1664+ bool blitFramebufferGLX (const CompRect &src,
1665+ const CompRect &dst,
1666+ GLbitfield mask,
1667+ GLenum filter);
1668+#else
1669+ bool blitFramebufferEGL (const CompRect &src,
1670+ const CompRect &dst,
1671+ GLbitfield mask,
1672+ GLenum filter);
1673+#endif
1674+ }
1675+}
1676
1677 namespace GL {
1678 #ifdef USE_GLES
1679@@ -164,11 +185,12 @@
1680 GLDisableVertexAttribArrayProc disableVertexAttribArray = NULL;
1681 GLVertexAttribPointerProc vertexAttribPointer = NULL;
1682
1683- GLGenRenderbuffersProc genRenderbuffers = NULL;
1684- GLDeleteRenderbuffersProc deleteRenderbuffers = NULL;
1685+ GLGenRenderbuffersProc genRenderbuffers = NULL;
1686+ GLDeleteRenderbuffersProc deleteRenderbuffers = NULL;
1687 GLFramebufferRenderbufferProc framebufferRenderbuffer = NULL;
1688- GLBindRenderbufferProc bindRenderbuffer = NULL;
1689- GLRenderbufferStorageProc renderbufferStorage = NULL;
1690+ GLBindRenderbufferProc bindRenderbuffer = NULL;
1691+ GLRenderbufferStorageProc renderbufferStorage = NULL;
1692+ GLBlitFramebufferProc blitFramebuffer = NULL;
1693
1694 bool textureFromPixmap = true;
1695 bool textureRectangle = false;
1696@@ -299,6 +321,115 @@
1697 GLScreen *gScreen;
1698 };
1699
1700+namespace
1701+{
1702+bool defaultRectangularFramebufferDraw (GLVertexBuffer *vertexBuffer,
1703+ GLFramebufferObject *fbo,
1704+ const CompRect &src,
1705+ const CompRect &dst,
1706+ GLbitfield mask,
1707+ GLenum filter)
1708+{
1709+ GLTexture *texture = fbo->tex ();
1710+ GLMatrix sTransform;
1711+ const GLTexture::Matrix & texmatrix = texture->matrix ();
1712+ const GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, src.x1 ());
1713+ const GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, src.x2 ());
1714+ const GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, src.y1 ());
1715+ const GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, src.y2 ());
1716+
1717+ const GLfloat vx1 = src.x1 ();
1718+ const GLfloat vx2 = src.x2 ();
1719+ const GLfloat vy1 = src.y1 ();
1720+ const GLfloat vy2 = src.y2 ();
1721+
1722+ const GLTexture::Filter texFilter =
1723+ (filter == GL_LINEAR) ? GLTexture::Good :
1724+ GLTexture::Fast;
1725+
1726+ GLfloat vertexData[] = {
1727+ vx1, vy1, 0.0f,
1728+ vx1, vy2, 0.0f,
1729+ vx2, vy1, 0.0f,
1730+
1731+ vx1, vy2, 0.0f,
1732+ vx2, vy2, 0.0f,
1733+ vx2, vy1, 0.0f,
1734+ };
1735+
1736+ GLfloat textureData[] = {
1737+ tx1, ty1,
1738+ tx1, ty2,
1739+ tx2, ty1,
1740+ tx1, ty2,
1741+ tx2, ty2,
1742+ tx2, ty1,
1743+ };
1744+
1745+ vertexBuffer->begin (GL_TRIANGLES);
1746+ vertexBuffer->addVertices (6, vertexData);
1747+ vertexBuffer->addTexCoords (0, 6, textureData);
1748+
1749+ if (vertexBuffer->end ())
1750+ {
1751+ texture->enable (texFilter);
1752+ sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
1753+ vertexBuffer->render (sTransform);
1754+ texture->disable ();
1755+ }
1756+
1757+ return true;
1758+}
1759+
1760+void initDirectDraw (cgli::DirectDrawStrategies::Ptr &directDraw,
1761+ const compiz::opengl::RectangularDraw &blitFramebuffer,
1762+ const compiz::opengl::RectangularDraw &rectangularTextureDraw,
1763+ const cgli::BindReadBufferFunc &func,
1764+ compiz::opengl::BindableFramebuffer *bindable)
1765+{
1766+ cglfb::RectangularDraw blitFramebufferBound (
1767+ boost::bind (
1768+ cgli::rectangleDrawFromReadBuffer,
1769+ _1, _2, _3, _4,
1770+ bindable,
1771+ func,
1772+ blitFramebuffer));
1773+
1774+ /* Tries each of these from back to front */
1775+ cglfb::RectangularDrawList strategies;
1776+
1777+ strategies.push_back (rectangularTextureDraw);
1778+ strategies.push_back (blitFramebufferBound);
1779+ directDraw.reset (new cgli::DirectDrawStrategies (strategies));
1780+}
1781+}
1782+
1783+namespace compiz
1784+{
1785+namespace opengl
1786+{
1787+DirectDrawObject *
1788+createBlittableFramebufferObjectWithFallback (const CompSize &sz,
1789+ GLScreen *gScreen)
1790+{
1791+ boost::shared_ptr <cgli::DirectDrawStrategies> directDraw;
1792+ boost::shared_ptr <cgli::FramebufferObject> fbo (boost::make_shared <cgli::FramebufferObject> ());
1793+ cglfb::RectangularDraw rectangularTextureDraw (boost::bind (defaultRectangularFramebufferDraw,
1794+ GLVertexBuffer::streamingBuffer (),
1795+ fbo.get (),
1796+ _1, _2, _3, _4));
1797+ initDirectDraw (directDraw,
1798+ gScreen->blitFramebufferFunc (),
1799+ rectangularTextureDraw,
1800+ boost::bind (&GLScreen::bindFramebufferForReading, gScreen, _1),
1801+ fbo.get ());
1802+ DirectDrawObject *dd (new cgli::DirectDrawObject (directDraw, fbo, fbo));
1803+ dd->allocate (*screen, NULL, GL_BGRA);
1804+ return dd;
1805+}
1806+}
1807+}
1808+
1809 #ifndef USE_GLES
1810
1811 namespace compiz
1812@@ -591,6 +722,7 @@
1813 if (GL::textureFromPixmap)
1814 registerBindPixmap (EglTexture::bindPixmapToTexture);
1815
1816+ priv->blitFramebuffer = boost::bind (compiz::opengl::blitFramebufferEGL, _1, _2, _3, _4);
1817 priv->incorrectRefreshRate = false;
1818
1819 #else
1820@@ -779,6 +911,10 @@
1821 GL::fboSupported = true;
1822 }
1823
1824+ if (GL::fboSupported &&
1825+ strstr (glExtensions, "GL_EXT_framebuffer_blit"))
1826+ GL::blitFramebuffer = (GL::GLBlitFramebufferProc) getProcAddress ("glBlitFramebufferEXT");
1827+
1828 GL::fboStencilSupported = GL::fboSupported &&
1829 strstr (glExtensions, "GL_EXT_packed_depth_stencil");
1830
1831@@ -895,13 +1031,13 @@
1832
1833 if (GL::textureFromPixmap)
1834 registerBindPixmap (TfpTexture::bindPixmapToTexture);
1835+
1836+ priv->blitFramebuffer = boost::bind (compiz::opengl::blitFramebufferGLX, _1, _2, _3, _4);
1837 #endif
1838
1839 if (GL::fboSupported)
1840- {
1841- priv->scratchFbo = new GLFramebufferObject;
1842- priv->scratchFbo->allocate (*screen, NULL, GL_BGRA);
1843- }
1844+ priv->scratchFbo.reset (compiz::opengl::createBlittableFramebufferObjectWithFallback (*screen,
1845+ this));
1846
1847 GLVertexBuffer::streamingBuffer ()->setAutoProgram (priv->autoProgram);
1848
1849@@ -1209,9 +1345,6 @@
1850 glXDestroyContext (screen->dpy (), priv->ctx);
1851 #endif
1852
1853- if (priv->scratchFbo)
1854- delete priv->scratchFbo;
1855-
1856 delete priv;
1857 }
1858
1859@@ -1234,6 +1367,7 @@
1860 doubleBuffer (screen->dpy (), *screen, surface),
1861 #endif
1862 scratchFbo (NULL),
1863+ blitFramebuffer (),
1864 outputRegion (),
1865 refreshSubBuffer (false),
1866 lastMask (0),
1867@@ -1246,6 +1380,10 @@
1868 autoProgram (new GLScreenAutoProgram(gs)),
1869 rootPixmapCopy (None),
1870 rootPixmapSize (),
1871+ drawFramebufferBinding (GL::DRAW_FRAMEBUFFER,
1872+ &backbuffer),
1873+ readFramebufferBinding (GL::READ_FRAMEBUFFER,
1874+ &backbuffer),
1875 glVendor (NULL),
1876 glRenderer (NULL),
1877 glVersion (NULL),
1878@@ -1441,11 +1579,19 @@
1879 void
1880 PrivateGLScreen::outputChangeNotify ()
1881 {
1882+ compiz::opengl::BindableFramebuffer *previousReadBuffer =
1883+ readFramebufferBinding.bind (&backbuffer);
1884+ compiz::opengl::BindableFramebuffer *previousDrawBuffer =
1885+ drawFramebufferBinding.bind (&backbuffer);
1886+
1887 screen->outputChangeNotify ();
1888
1889- if (scratchFbo)
1890+ if (scratchFbo.get ())
1891 scratchFbo->allocate (*screen, NULL, GL_BGRA);
1892 updateView ();
1893+
1894+ readFramebufferBinding.bind (previousReadBuffer);
1895+ drawFramebufferBinding.bind (previousDrawBuffer);
1896 }
1897
1898 #ifndef USE_GLES
1899@@ -1670,9 +1816,9 @@
1900 WRAPABLE_DEF (projectionMatrix)
1901
1902 void
1903-GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
1904- GLFramebufferObject *fbo,
1905- unsigned int mask)
1906+GLScreenInterface::glPaintCompositedOutput (const CompRegion &region,
1907+ compiz::opengl::DirectDrawObject *fbo,
1908+ unsigned int mask)
1909 WRAPABLE_DEF (glPaintCompositedOutput, region, fbo, mask)
1910
1911 void
1912@@ -1899,6 +2045,30 @@
1913
1914 }
1915
1916+bool
1917+cglfb::blitFramebufferGLX (const CompRect &src,
1918+ const CompRect &dst,
1919+ GLbitfield mask,
1920+ GLenum filter)
1921+{
1922+ /* Must have GL_EXT_blit_framebuffer */
1923+ if (!GL::blitFramebuffer)
1924+ return false;
1925+
1926+ /* Be sure to invert y-coords too */
1927+ (*GL::blitFramebuffer) (src.x1 (), // sx0
1928+ screen->height () - src.y2 (), // sy0
1929+ src.x2 (), // sx1
1930+ screen->height () - src.y1 (), // sy1
1931+ dst.x1 (), // dx0
1932+ screen->height () - dst.y2 (), // dy0
1933+ dst.x2 (), // dx1,
1934+ screen->height () - dst.y1 (), // dy1
1935+ GL_COLOR_BUFFER_BIT,
1936+ GL_LINEAR);
1937+ return true;
1938+}
1939+
1940 #else
1941
1942 EGLDoubleBuffer::EGLDoubleBuffer (Display *d,
1943@@ -1957,6 +2127,16 @@
1944 {
1945 }
1946
1947+bool
1948+cglfb::blitFramebufferEGL (const CompRect &src,
1949+ const CompRect &dst,
1950+ GLbitfield mask,
1951+ GLenum filter)
1952+{
1953+ /* Not supported on OpenGL|ES2 */
1954+ return false;
1955+}
1956+
1957 #endif
1958
1959 void
1960@@ -1977,17 +2157,11 @@
1961 glDepthMask (GL_FALSE);
1962 glStencilMask (0);
1963
1964- GLFramebufferObject *oldFbo = NULL;
1965- bool useFbo = false;
1966+ compiz::opengl::BindableFramebuffer *oldFbo = NULL;
1967
1968 /* Clear the color buffer where appropriate */
1969- if (GL::fboEnabled && scratchFbo)
1970- {
1971- oldFbo = scratchFbo->bind ();
1972- useFbo = scratchFbo->checkStatus () && scratchFbo->tex ();
1973- if (!useFbo)
1974- GLFramebufferObject::rebind (oldFbo);
1975- }
1976+ if (GL::fboEnabled && scratchFbo.get ())
1977+ oldFbo = drawFramebufferBinding.bind (scratchFbo.get ());
1978
1979 #ifdef UNSAFE_ARM_SGX_FIXME
1980 refreshSubBuffer = ((lastMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
1981@@ -2080,13 +2254,10 @@
1982
1983 glViewport (0, 0, screen->width (), screen->height ());
1984
1985- if (useFbo)
1986+ if (oldFbo)
1987 {
1988- GLFramebufferObject::rebind (oldFbo);
1989-
1990- // FIXME: does not work if screen dimensions exceed max texture size
1991- // We should try to use glBlitFramebuffer instead.
1992- gScreen->glPaintCompositedOutput (screen->region (), scratchFbo, mask);
1993+ drawFramebufferBinding.bind (oldFbo);
1994+ gScreen->glPaintCompositedOutput (screen->region (), scratchFbo.get (), mask);
1995 }
1996
1997 if (cScreen->outputWindowChanged ())
1998@@ -2101,13 +2272,13 @@
1999 }
2000
2001 bool alwaysSwap = optionGetAlwaysSwapBuffers ();
2002- bool fullscreen = useFbo ||
2003+ bool fullscreen = oldFbo ||
2004 alwaysSwap ||
2005 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2006 commonFrontbuffer);
2007
2008 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2009- doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
2010+ doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, oldFbo ? true : false);
2011 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2012 doubleBuffer.render (tmpRegion, fullscreen);
2013
2014@@ -2195,10 +2366,34 @@
2015 }
2016 }
2017
2018-GLFramebufferObject *
2019+compiz::opengl::FramebufferObject *
2020 GLScreen::fbo ()
2021 {
2022- return priv->scratchFbo;
2023+ return priv->scratchFbo.get ();
2024+}
2025+
2026+compiz::opengl::BindableFramebuffer *
2027+GLScreen::backbuffer ()
2028+{
2029+ return &priv->backbuffer;
2030+}
2031+
2032+compiz::opengl::BindableFramebuffer *
2033+GLScreen::bindFramebufferForDrawing (compiz::opengl::BindableFramebuffer *next)
2034+{
2035+ return priv->drawFramebufferBinding.bind (next);
2036+}
2037+
2038+compiz::opengl::BindableFramebuffer *
2039+GLScreen::bindFramebufferForReading (compiz::opengl::BindableFramebuffer *next)
2040+{
2041+ return priv->readFramebufferBinding.bind (next);
2042+}
2043+
2044+const cglfb::BlitFramebufferFunc &
2045+GLScreen::blitFramebufferFunc ()
2046+{
2047+ return priv->blitFramebuffer;
2048 }
2049
2050 GLTexture *
2051@@ -2240,3 +2435,19 @@
2052 priv->rasterPos.setY (0);
2053 }
2054
2055+GLuint
2056+BindableBackbuffer::getResourceId () const
2057+{
2058+ return 0;
2059+}
2060+
2061+bool
2062+BindableBackbuffer::setBindStatus (GLenum)
2063+{
2064+ return true;
2065+}
2066+
2067+void
2068+BindableBackbuffer::updateAllocation (GLenum)
2069+{
2070+}
2071
2072=== modified file 'plugins/water/src/water.cpp'
2073--- plugins/water/src/water.cpp 2013-01-28 19:45:04 +0000
2074+++ plugins/water/src/water.cpp 2013-02-12 04:56:22 +0000
2075@@ -62,7 +62,11 @@
2076 if (!useFbo)
2077 return false;
2078
2079- oldFbo = waterFbo[fIndex]->bind ();
2080+ oldFbo = gScreen->bindFramebufferForDrawing (waterFbo[fIndex]);
2081+
2082+ if (!oldFbo)
2083+ return false;
2084+
2085 glGetIntegerv(GL_VIEWPORT, &oldViewport[0]);
2086 glViewport (0, 0, texWidth, texHeight);
2087
2088@@ -72,7 +76,7 @@
2089 void
2090 WaterScreen::fboEpilogue ()
2091 {
2092- GLFramebufferObject::rebind (oldFbo);
2093+ gScreen->bindFramebufferForDrawing (oldFbo);
2094 glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
2095 }
2096
2097@@ -305,28 +309,32 @@
2098 waterFbo[i]->allocate (size, (char *) t0,
2099 GL_BGRA, GL_UNSIGNED_BYTE);
2100 // check if FBOs are working. If not, fallback to software textures
2101- oldFbo = waterFbo[i]->bind ();
2102- waterFbo[i]->rebind (oldFbo);
2103- if (!waterFbo[i]->checkStatus ())
2104+ oldFbo = gScreen->bindFramebufferForDrawing (waterFbo[i]);
2105+ if (!oldFbo)
2106 {
2107 useFbo = false;
2108 delete waterFbo[i];
2109 break;
2110 }
2111+ gScreen->bindFramebufferForDrawing (oldFbo);
2112 }
2113 }
2114 }
2115
2116 void
2117-WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2118- GLFramebufferObject *fbo,
2119- unsigned int mask)
2120+WaterScreen::glPaintCompositedOutput (const CompRegion &region,
2121+ compiz::opengl::DirectDrawObject *fbo,
2122+ unsigned int mask)
2123 {
2124 if (count)
2125 {
2126 if (GL::vboEnabled && GL::shaders)
2127 {
2128- GLFramebufferObject::rebind (oldFbo);
2129+ /* This seems redundant to me */
2130+ gScreen->bindFramebufferForDrawing (oldFbo);
2131+
2132+ oldFbo = NULL;
2133+
2134 glViewport (oldViewport[0], oldViewport[1],
2135 oldViewport[2], oldViewport[3]);
2136
2137
2138=== modified file 'plugins/water/src/water.h'
2139--- plugins/water/src/water.h 2012-09-07 23:56:21 +0000
2140+++ plugins/water/src/water.h 2013-02-12 04:56:22 +0000
2141@@ -64,9 +64,9 @@
2142
2143 void handleEvent (XEvent *);
2144
2145- void glPaintCompositedOutput (const CompRegion &region,
2146- GLFramebufferObject *fbo,
2147- unsigned int mask);
2148+ void glPaintCompositedOutput (const CompRegion &region,
2149+ compiz::opengl::DirectDrawObject *fbo,
2150+ unsigned int mask);
2151 void preparePaint (int);
2152 void donePaint ();
2153
2154@@ -100,7 +100,7 @@
2155
2156 GLFramebufferObject *waterFbo[TEXTURE_NUM];
2157
2158- GLFramebufferObject *oldFbo;
2159+ compiz::opengl::BindableFramebuffer *oldFbo;
2160 GLint oldViewport[4];
2161 int fboIndex;
2162 bool useFbo;

Subscribers

People subscribed via source and target branches