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

Proposed by Sam Spilsbury on 2013-02-15
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.performance_1040478
Merge into: lp:compiz/0.9.9
Diff against target: 2171 lines (+1334/-301)
15 files modified
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 (+8/-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)
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 2013-02-15 Needs Fixing on 2013-02-25
jenkins continuous-integration 2013-02-15 Pending
Sam Spilsbury Pending
Review via email: mp+148841@code.launchpad.net

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

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

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.
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
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: Resubmit
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
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
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Probably a good idea. Lets do that.

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)

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

OK, then. Bug 1051287 needs fixing here.

review: Needs Fixing
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Lets look into this again post 0.9.9.0

review: Resubmit
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 }

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

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.

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.

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.

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.

3415. By Sam Spilsbury on 2013-02-18

Revert more changes which should not have happened

3416. By Sam Spilsbury on 2013-02-18

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

3417. By Sam Spilsbury on 2013-02-25

Merge lp:compiz

3418. By Sam Spilsbury on 2013-02-27

Merge lp:compiz

3419. By Sam Spilsbury on 2013-02-28

Unrevert changes reverted by a merge

Unmerged revisions

3419. By Sam Spilsbury on 2013-02-28

Unrevert changes reverted by a merge

3418. By Sam Spilsbury on 2013-02-27

Merge lp:compiz

3417. By Sam Spilsbury on 2013-02-25

Merge lp:compiz

3416. By Sam Spilsbury on 2013-02-18

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

3415. By Sam Spilsbury on 2013-02-18

Revert more changes which should not have happened

3414. By Sam Spilsbury on 2013-02-15

Merge lp:compiz

3413. By Sam Spilsbury on 2013-02-13

Fix merge errors

3412. By Sam Spilsbury on 2013-02-13

Merge lp:compiz

3411. By Sam Spilsbury on 2013-02-12

Another botched merge

3410. By Sam Spilsbury on 2013-02-12

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

Subscribers

People subscribed via source and target branches