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

Proposed by Sam Spilsbury on 2012-12-07
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.performance_1040478
Merge into: lp:compiz/0.9.9
Diff against target: 2150 lines (+1312/-302)
15 files modified
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/-8)
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
Sam Spilsbury Resubmit on 2012-12-12
PS Jenkins bot (community) continuous-integration Approve on 2012-12-07
jenkins continuous-integration 2012-12-07 Pending
Review via email: mp+138806@code.launchpad.net

This proposal supersedes a proposal from 2012-09-28.

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

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 :
review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Sam Spilsbury (smspillaz) wrote :

Lets look into this again post 0.9.9.0

review: Resubmit
3406. By Sam Spilsbury on 2013-02-12

Merge lp:compiz

3407. By Sam Spilsbury on 2013-02-12

Remove referenes to configure buffers

3408. By Sam Spilsbury on 2013-02-12

Revert trunk merge as it was broken

3409. By Sam Spilsbury on 2013-02-12

Merge lp:compiz

3410. By Sam Spilsbury on 2013-02-12

Unrevert changes which shouldn't have been reverted

3411. By Sam Spilsbury on 2013-02-12

Another botched merge

3412. By Sam Spilsbury on 2013-02-13

Merge lp:compiz

3413. By Sam Spilsbury on 2013-02-13

Fix merge errors

3414. By Sam Spilsbury on 2013-02-15

Merge lp:compiz

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

Subscribers

People subscribed via source and target branches