Merge lp:~smspillaz/compiz/compiz.static_vertex_buffers into lp:compiz/0.9.8

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/compiz/compiz.static_vertex_buffers
Merge into: lp:compiz/0.9.8
Diff against target: 1088 lines (+759/-23)
13 files modified
plugins/decor/src/decor.cpp (+8/-1)
plugins/decor/src/decor.h (+2/-0)
plugins/opengl/CMakeLists.txt (+7/-0)
plugins/opengl/include/opengl/opengl.h (+30/-0)
plugins/opengl/include/opengl/vertexbufferstack.h (+69/-0)
plugins/opengl/src/paint.cpp (+47/-13)
plugins/opengl/src/privates.h (+20/-2)
plugins/opengl/src/vertexbufferstack/CMakeLists.txt (+25/-0)
plugins/opengl/src/vertexbufferstack/include/vertexbufferstack-internal.h (+67/-0)
plugins/opengl/src/vertexbufferstack/src/vertex-buffer-stack.cpp (+145/-0)
plugins/opengl/src/vertexbufferstack/tests/CMakeLists.txt (+24/-0)
plugins/opengl/src/vertexbufferstack/tests/test-opengl-vertex-buffer-stack.cpp (+256/-0)
plugins/opengl/src/window.cpp (+59/-7)
To merge this branch: bzr merge lp:~smspillaz/compiz/compiz.static_vertex_buffers
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Resubmitting
jenkins (community) continuous-integration Approve
Review via email: mp+123447@code.launchpad.net

This proposal has been superseded by a proposal from 2012-09-28.

Commit message

Avoid doing so many vertex buffer object binds.

At the moment, all of the vertex buffer objects for windows are marked GL_STATIC_DRAW. However according to http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html , this is a bad idea because doing glBindBuffer and glBufferData on those buffers can cause GPU to copy vertex data from system memory to the GPU on for that vertex buffer every time the command queue is processed. If that's an expensive operation, then it could result in a fairly large slowdown on some platforms. Because the content of our vertex buffers can change a fair bit, I've changed the default usage hint to GL_DYNAMIC_DRAW, which appears to mean "dma data into the gpu, cache it where necessary"

In compiz, we do region updates by clipping vertex data to a clip region (and, eg, generating new vertex and tex-coord data where it makes sense to do so) and then paint only the primitives specified by those vertices. This is easier on GPUs where fill rate is a concern. However, it means that we can't have static data in our vertex buffer objects, and they effectively need to be re-uploaded every time they change.

There were two factors causing them to be changed all the time, which meant that they had to be re-uploaded all the time
 1) Plugins "share" the vertex buffer object with opengl, and clear the vertex data to add their own. This means that both sets have to be re-uploaded, and the opengl one has to be re-populated every time a plugin uses it "temporarily"
 2) A typical usage trend appears to be just calling ::begin (), adding vertex data and then calling ::end (), even if the vertex data is unchanged.

As for 2) I've added a simple check to determine if we need to re-add vertex data at all, and if we don't, not to call glAddGeometry again, but to re-use the vertex buffer (where it makes sense to do). This code is untested, as it involves setting and checking flags and manipulating lots of internal state. Its also not the preferred solution either as per my comments above, which is why I haven't designed the code to be testable around this case.

The result is that for playing a simple video, in the old usecase, we called:
  * glAddGeometry 497 times
  * GLVertexBuffer::end () (eg, vertex data upload if there is vertex data, which there will be for every frame) 745 times

Description of the change

Avoid doing so many vertex buffer object binds. This is more of an RFC than an actual merge proposal as I don't see it going in this cycle.

At the moment, all of the vertex buffer objects for windows are marked GL_STATIC_DRAW. However according to http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html , this is a bad idea because doing glBindBuffer and glBufferData on those buffers can cause GPU to copy vertex data from system memory to the GPU on for that vertex buffer every time the command queue is processed. If that's an expensive operation, then it could result in a fairly large slowdown on some platforms. Because the content of our vertex buffers can change a fair bit, I've changed the default usage hint to GL_DYNAMIC_DRAW, which appears to mean "dma data into the gpu, cache it where necessary"

In compiz, we do region updates by clipping vertex data to a clip region (and, eg, generating new vertex and tex-coord data where it makes sense to do so) and then paint only the primitives specified by those vertices. This is easier on GPUs where fill rate is a concern. However, it means that we can't have static data in our vertex buffer objects, and they effectively need to be re-uploaded every time they change.

There were two factors causing them to be changed all the time, which meant that they had to be re-uploaded all the time
 1) Plugins "share" the vertex buffer object with opengl, and clear the vertex data to add their own. This means that both sets have to be re-uploaded, and the opengl one has to be re-populated every time a plugin uses it "temporarily"
 2) A typical usage trend appears to be just calling ::begin (), adding vertex data and then calling ::end (), even if the vertex data is unchanged.

As for 1) This would best be served by breaking the API and making a GLVertexBuffer * a mandatory part of glAddGeometry and glDrawTexture, so that plugins can provide their own vertex buffers without clobbering the opengl one. Since we can't do that, I've added an API to manipulate which GLVertexBuffer the opengl plugin is using internally. This code is a separate module and covered by unit tests

As for 2) I've added a simple check to determine if we need to re-add vertex data at all, and if we don't, not to call glAddGeometry again, but to re-use the vertex buffer (where it makes sense to do). This code is untested, as it involves setting and checking flags and manipulating lots of internal state. Its also not the preferred solution either as per my comments above, which is why I haven't designed the code to be testable around this case.

The result is that for playing a simple video, in the old usecase, we called:
  * glAddGeometry 497 times
  * GLVertexBuffer::end () (eg, vertex data upload if there is vertex data, which there will be for every frame) 745 times

And for the new code:
 * glAddGeometry 13 times
 * GLVertexBuffer::end () 262 times

I'm not sure what kind of impact this has on framerates. In both cases I maxed out at 60fps.

Where to go with this?
 * The next place that is calling GLVertexBuffer::end () a lot is PrivateGLScreen::paintOutputs when drawing the fbo to the screen. This can be resolved by actually treating that like a static buffer as well (it really should be), or moving to glBlitFramebuffer (preferred
 * We need to make the decor plugin implement the same logic in 2)
 * Make the other plugins provide their own vertex buffers where they need to "attach" textures to windows rather than piggybacking the one internal to opengl.

tl;dr; This might make compiz faster at watching youtube videos. Need feedback as to whether to continue in this direction.

To post a comment you must log in.
Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Argh, so many words.

Initial observation: If a class is called "VertexBufferStack" then its method names should not contain the redundant text "VertexBuffer".

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

This doesn't need review right away. Just seeking feedback as to whether or not this is the right direction to go

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Awesome speedup on intel. This is 15-25% faster than trunk there. And it matches the max performance levels I have ever seen on my my desktop.

I honestly never thought I would see the FBO+VBO codepath perform this well... I'd like to make this enhancement a priority.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Linked to bug 1024304, because I suspect this might be the answer. It certainly is for Intel Sandy Bridge.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

This is weird. Suddenly trunk is as fast. Maybe I got prematurely excited but it's still interesting.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The speedup I thought I got from this was a false alarm. My whole system is suddenly faster with all branches. It wasn't anything to do with this one.

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

review: Needs Resubmitting

Unmerged revisions

3363. By Sam Spilsbury

Don't call glAddGeometry if the geometry is
going to be exactly the same. Saves a vertex
buffer bind

3362. By Sam Spilsbury

Only remove the last vertex buffer when using the stack

3361. By Sam Spilsbury

Use GL_DYNAMIC_DRAW for the vertex buffer objects

3360. By Sam Spilsbury

Use a foreign vertex buffer to draw the decorations

3359. By Sam Spilsbury

Implement the interface publicly

3358. By Sam Spilsbury

Implement the internal vertex buffer in terms of the vertex buffer stack

3357. By Sam Spilsbury

Added a simple RAII class to manage that

3356. By Sam Spilsbury

Added a new class, VertexBufferStack.

A VertexBufferStack is a stack of saved GLVertexBufferObjects, which can have
items pushed to the back, removed and popped off the top. activeVertexBuffer
always represents the top most vertex buffer on the stack, popVertexBufferOffTop
will restore the last one.

3355. By Sam Spilsbury

Internally added the concepts of multiple vertex buffers per window

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/decor/src/decor.cpp'
2--- plugins/decor/src/decor.cpp 2012-08-14 06:33:22 +0000
3+++ plugins/decor/src/decor.cpp 2012-09-09 16:26:19 +0000
4@@ -42,6 +42,8 @@
5
6 COMPIZ_PLUGIN_20090315 (decor, DecorPluginVTable)
7
8+namespace cgl = compiz::opengl;
9+
10 MatchedDecorClipGroup::MatchedDecorClipGroup (const CompMatch &match) :
11 mMatch (match)
12 {
13@@ -209,6 +211,9 @@
14 const CompRegion &region,
15 unsigned int mask)
16 {
17+ cgl::VertexBufferPush vertexBufferPush (gWindow->vertexBufferStack (),
18+ mDecorationVertexBuffer);
19+
20 if (wd &&
21 wd->decor->type == WINDOW_DECORATION_TYPE_PIXMAP)
22 {
23@@ -3091,8 +3096,10 @@
24 mClipGroup (NULL),
25 mOutputRegion (window->outputRect ()),
26 mInputRegion (window->inputRect ()),
27- mRequestor (screen->dpy (), w->id (), &decor)
28+ mRequestor (screen->dpy (), w->id (), &decor),
29+ mDecorationVertexBuffer (new GLVertexBuffer (GL_STATIC_DRAW))
30 {
31+ mDecorationVertexBuffer->setAutoProgram (gWindow->autoProgram ());
32 WindowInterface::setHandler (window);
33
34 /* FIXME :DecorWindow::update can call updateWindowOutputExtents
35
36=== modified file 'plugins/decor/src/decor.h'
37--- plugins/decor/src/decor.h 2012-07-30 07:10:52 +0000
38+++ plugins/decor/src/decor.h 2012-09-09 16:26:19 +0000
39@@ -31,6 +31,7 @@
40
41 #include <composite/composite.h>
42 #include <opengl/opengl.h>
43+#include <opengl/vertexbufferstack.h>
44 #include <core/atoms.h>
45 #include <core/windowextents.h>
46
47@@ -362,6 +363,7 @@
48 CompRegion mInputRegion;
49
50 X11DecorPixmapRequestor mRequestor;
51+ compiz::opengl::GLVertexBufferPtr mDecorationVertexBuffer;
52 };
53
54 class DecorPluginVTable :
55
56=== modified file 'plugins/opengl/CMakeLists.txt'
57--- plugins/opengl/CMakeLists.txt 2012-09-04 10:19:19 +0000
58+++ plugins/opengl/CMakeLists.txt 2012-09-09 16:26:19 +0000
59@@ -5,10 +5,17 @@
60 set (INTERNAL_LIBRARIES
61 compiz_opengl_double_buffer
62 compiz_opengl_fsregion
63+ compiz_opengl_vertex_buffer_stack
64 )
65
66+set (COMPIZ_OPENGL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
67+set (COMPIZ_OPENGL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
68+
69 add_subdirectory (src/doublebuffer)
70 add_subdirectory (src/fsregion)
71+add_subdirectory (src/vertexbufferstack)
72+
73+include_directories (src/vertexbufferstack/include)
74
75 if (USE_GLES)
76 compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD "-DUSE_GLES -std=c++0x" LIBRARIES ${OPENGLES2_LIBRARIES} ${INTERNAL_LIBRARIES} dl INCDIRS ${OPENGLES2_INCLUDE_DIR})
77
78=== modified file 'plugins/opengl/include/opengl/opengl.h'
79--- plugins/opengl/include/opengl/opengl.h 2012-08-14 08:42:15 +0000
80+++ plugins/opengl/include/opengl/opengl.h 2012-09-09 16:26:19 +0000
81@@ -39,6 +39,9 @@
82 #include <GL/glx.h>
83 #endif
84
85+#include <boost/shared_ptr.hpp>
86+#include <boost/weak_ptr.hpp>
87+
88 #include <core/size.h>
89 #include <core/pluginclasshandler.h>
90
91@@ -871,6 +874,16 @@
92 const GLWindowPaintAttrib &, unsigned int);
93 };
94
95+namespace compiz
96+{
97+ namespace opengl
98+ {
99+ typedef boost::shared_ptr <GLVertexBuffer> GLVertexBufferPtr;
100+ typedef boost::weak_ptr <GLVertexBuffer> GLVertexBufferWeak;
101+ class VertexBufferStack;
102+ }
103+}
104+
105 class GLWindow :
106 public WrapableHandler<GLWindowInterface, 4>,
107 public PluginClassHandler<GLWindow, CompWindow, COMPIZ_OPENGL_ABI>
108@@ -926,6 +939,23 @@
109 GLVertexBuffer * vertexBuffer ();
110
111 /**
112+ * Returns the current vertex buffer stack
113+ */
114+ compiz::opengl::VertexBufferStack &
115+ vertexBufferStack ();
116+
117+ /**
118+ * Returns the AutoProgram used for this window's
119+ * GLVertexBuffer objects. The returned object
120+ * is internal to GLWindow and should not be
121+ * deleted
122+ *
123+ * TODO ABI: Return weak pointer
124+ */
125+ compiz::gl::AutoProgram *
126+ autoProgram ();
127+
128+ /**
129 * Add a vertex and/or fragment shader function to the pipeline.
130 *
131 * @param name Name of the plugin adding the functions
132
133=== added file 'plugins/opengl/include/opengl/vertexbufferstack.h'
134--- plugins/opengl/include/opengl/vertexbufferstack.h 1970-01-01 00:00:00 +0000
135+++ plugins/opengl/include/opengl/vertexbufferstack.h 2012-09-09 16:26:19 +0000
136@@ -0,0 +1,69 @@
137+/*
138+ * Compiz opengl plugin, VertexBufferStack interface
139+ *
140+ * Copyright (c) 2012 Canonical Ltd.
141+ * Author: Sam Spilsbury <sam.spilsbury@canonical.com>
142+ *
143+ * Permission is hereby granted, free of charge, to any person obtaining a
144+ * copy of this software and associated documentation files (the "Software"),
145+ * to deal in the Software without restriction, including without limitation
146+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
147+ * and/or sell copies of the Software, and to permit persons to whom the
148+ * Software is furnished to do so, subject to the following conditions:
149+ *
150+ * The above copyright notice and this permission notice shall be included in
151+ * all copies or substantial portions of the Software.
152+ *
153+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
155+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
156+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
157+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
158+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
159+ * DEALINGS IN THE SOFTWARE.
160+ */
161+#ifndef __COMPIZ_OPENGL_VERTEXBUFFERSTACK_H
162+#define __COMPIZ_OPENGL_VERTEXBUFFERSTACK_H
163+
164+#include <boost/shared_ptr.hpp>
165+#include <boost/weak_ptr.hpp>
166+
167+class GLVertexBuffer;
168+
169+namespace compiz
170+{
171+ namespace opengl
172+ {
173+ typedef boost::shared_ptr <GLVertexBuffer> GLVertexBufferPtr;
174+ typedef boost::weak_ptr <GLVertexBuffer> GLVertexBufferWeak;
175+
176+ class VertexBufferStack
177+ {
178+ public:
179+
180+ virtual ~VertexBufferStack () {}
181+
182+ virtual void pushVertexBuffer (const GLVertexBufferPtr &) = 0;
183+ virtual bool removeVertexBuffer (const GLVertexBufferPtr &) = 0;
184+ virtual bool removeLastVertexBuffer (const GLVertexBufferPtr &) = 0;
185+ virtual void popVertexBufferFromTop () = 0;
186+ virtual const GLVertexBufferWeak & activeVertexBuffer () const = 0;
187+ };
188+
189+ class VertexBufferPush
190+ {
191+ public:
192+
193+ VertexBufferPush (VertexBufferStack &vbStack,
194+ const GLVertexBufferPtr &vertexBuffer);
195+ ~VertexBufferPush ();
196+
197+ private:
198+
199+ VertexBufferStack &mVBStack;
200+ const GLVertexBufferPtr &mVertexBuffer;
201+ };
202+ }
203+}
204+
205+#endif
206
207=== modified file 'plugins/opengl/src/paint.cpp'
208--- plugins/opengl/src/paint.cpp 2012-09-06 09:55:05 +0000
209+++ plugins/opengl/src/paint.cpp 2012-09-09 16:26:19 +0000
210@@ -36,13 +36,14 @@
211 #define foreach BOOST_FOREACH
212
213 #include <opengl/opengl.h>
214+#include <opengl/vertexbufferstack.h>
215
216 #include "privates.h"
217 #include "fsregion/fsregion.h"
218
219 #define DEG2RAD (M_PI / 180.0f)
220
221-using namespace compiz::opengl;
222+namespace cgl = compiz::opengl;
223
224 GLScreenPaintAttrib defaultScreenPaintAttrib = {
225 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA
226@@ -275,7 +276,7 @@
227
228 if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK))
229 {
230- FullscreenRegion fs (*output);
231+ cgl::FullscreenRegion fs (*output);
232
233 /* detect occlusions */
234 for (rit = pl.rbegin (); rit != pl.rend (); ++rit)
235@@ -339,11 +340,11 @@
236 tmpRegion -= w->region ();
237 }
238
239- FullscreenRegion::WinFlags flags = 0;
240+ cgl::FullscreenRegion::WinFlags flags = 0;
241 if (w->type () & CompWindowTypeDesktopMask)
242- flags |= FullscreenRegion::Desktop;
243+ flags |= cgl::FullscreenRegion::Desktop;
244 if (w->alpha ())
245- flags |= FullscreenRegion::Alpha;
246+ flags |= cgl::FullscreenRegion::Alpha;
247
248 /*
249 * Windows with alpha channels can partially occlude windows
250@@ -895,9 +896,16 @@
251 {
252 WRAPABLE_HND_FUNCTN (glAddGeometry, matrix, region, clip)
253
254+ boost::shared_ptr <GLVertexBuffer> activeVertexBuffer = priv->vertexBufferStack.activeVertexBuffer ().lock ();
255+
256 BoxRec full;
257 int nMatrix = matrix.size ();
258
259+ /* Someone is modifying our internal vertex buffer */
260+ if (!priv->inGLDraw &&
261+ activeVertexBuffer == priv->windowVertexBuffer)
262+ priv->vertexBufferDirty = true;
263+
264 full = clip.handle ()->extents;
265 if (region.handle ()->extents.x1 > full.x1)
266 full.x1 = region.handle ()->extents.x1;
267@@ -954,7 +962,7 @@
268
269 if (nClip == 1)
270 {
271- addQuads (priv->vertexBuffer, matrix, nMatrix,
272+ addQuads (activeVertexBuffer.get (), matrix, nMatrix,
273 x1, y1, x2, y2,
274 rect,
275 maxGridWidth, maxGridHeight);
276@@ -980,7 +988,7 @@
277
278 if (cbox.x1 < cbox.x2 && cbox.y1 < cbox.y2)
279 {
280- addQuads (priv->vertexBuffer, matrix, nMatrix,
281+ addQuads (activeVertexBuffer.get (), matrix, nMatrix,
282 cbox.x1, cbox.y1, cbox.x2, cbox.y2,
283 rect,
284 maxGridWidth, maxGridHeight);
285@@ -1222,14 +1230,14 @@
286 texture->enable (filter);
287
288 #ifdef USE_GLES
289- priv->vertexBuffer->render (transform, attrib);
290+ priv->vertexBufferStack.activeVertexBuffer ().lock ()->render (transform, attrib);
291 #else
292
293 if (!GLVertexBuffer::enabled ())
294 enableLegacyOBSAndRender (priv->gScreen, this, texture, transform,
295 attrib, filter, mask);
296 else
297- priv->vertexBuffer->render (transform, attrib);
298+ priv->vertexBufferStack.activeVertexBuffer ().lock ()->render (transform, attrib);
299 #endif
300
301 priv->shaders.clear ();
302@@ -1248,9 +1256,22 @@
303 WRAPABLE_HND_FUNCTN_RETURN (bool, glDraw, transform,
304 attrib, region, mask)
305
306+ const bool transformedWindow = mask & (PAINT_WINDOW_WITH_OFFSET_MASK |
307+ PAINT_WINDOW_TRANSFORMED_MASK);
308+ const bool damageRegionChanged = priv->lastDamageRegion != region;
309+ const bool internalMatricesChanged = priv->updateState & (PrivateGLWindow::UpdateMatrix |
310+ PrivateGLWindow::UpdateRegion);
311+ const bool readdGeometry = priv->vertexBufferDirty ||
312+ transformedWindow ||
313+ internalMatricesChanged ||
314+ damageRegionChanged;
315+
316 const CompRegion &reg = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ?
317 infiniteRegion : region;
318
319+ if (readdGeometry)
320+ priv->lastDamageRegion = region;
321+
322 if (reg.isEmpty ())
323 return true;
324
325@@ -1282,10 +1303,23 @@
326
327 for (unsigned int i = 0; i < priv->textures.size (); i++)
328 {
329- ml[0] = priv->matrices[i];
330- priv->vertexBuffer->begin ();
331- glAddGeometry (ml, priv->regions[i], reg);
332- if (priv->vertexBuffer->end ())
333+ cgl::VertexBufferStack &vbStack (priv->vertexBufferStack);
334+ cgl::VertexBufferPush push (vbStack,
335+ priv->windowVertexBuffer);
336+ cgl::GLVertexBufferPtr activeVertexBuffer = vbStack.activeVertexBuffer ().lock ();
337+
338+ if (readdGeometry || true)
339+ {
340+ priv->inGLDraw = true;
341+ ml[0] = priv->matrices[i];
342+ activeVertexBuffer->begin ();
343+ glAddGeometry (ml, priv->regions[i], reg);
344+ activeVertexBuffer->end ();
345+ priv->inGLDraw = false;
346+ priv->vertexBufferDirty = false;
347+ }
348+
349+ if (activeVertexBuffer->countVertices ())
350 glDrawTexture (priv->textures[i], transform, attrib, mask);
351 }
352
353
354=== modified file 'plugins/opengl/src/privates.h'
355--- plugins/opengl/src/privates.h 2012-07-30 07:10:52 +0000
356+++ plugins/opengl/src/privates.h 2012-09-09 16:26:19 +0000
357@@ -28,6 +28,9 @@
358 #ifndef _OPENGL_PRIVATES_H
359 #define _OPENGL_PRIVATES_H
360
361+#include <boost/shared_ptr.hpp>
362+#include <boost/weak_ptr.hpp>
363+
364 #include <composite/composite.h>
365 #include <opengl/opengl.h>
366 #include <core/atoms.h>
367@@ -40,6 +43,7 @@
368
369 #include "privatetexture.h"
370 #include "privatevertexbuffer.h"
371+#include "vertexbufferstack-internal.h"
372 #include "opengl_options.h"
373
374 extern CompOutput *targetOutput;
375@@ -213,7 +217,8 @@
376
377 class PrivateGLWindow :
378 public WindowInterface,
379- public CompositeWindowInterface
380+ public CompositeWindowInterface,
381+ public compiz::opengl::VertexBufferStack
382 {
383 public:
384
385@@ -246,6 +251,9 @@
386 bool needsRebind;
387
388 CompRegion clip;
389+ CompRegion lastDamageRegion;
390+ bool vertexBufferDirty;
391+ bool inGLDraw;
392
393 bool bindFailed;
394 bool overlayWindow;
395@@ -259,7 +267,8 @@
396
397 unsigned int lastMask;
398
399- GLVertexBuffer *vertexBuffer;
400+ compiz::opengl::impl::VertexBufferStack vertexBufferStack;
401+ compiz::opengl::GLVertexBufferPtr windowVertexBuffer;
402
403 // map of shaders, plugin name is key, pair of vertex and fragment
404 // shader source code is value
405@@ -267,6 +276,15 @@
406 GLVertexBuffer::AutoProgram *autoProgram;
407
408 std::list<GLIcon> icons;
409+
410+ private:
411+
412+ /* Implementation of compiz::opengl::VertexBufferStack */
413+ void pushVertexBuffer (const compiz::opengl::GLVertexBufferPtr &);
414+ void popVertexBufferFromTop ();
415+ bool removeVertexBuffer (const compiz::opengl::GLVertexBufferPtr &);
416+ bool removeLastVertexBuffer (const compiz::opengl::GLVertexBufferPtr &);
417+ const compiz::opengl::GLVertexBufferWeak & activeVertexBuffer () const;
418 };
419
420 #endif
421
422=== added directory 'plugins/opengl/src/vertexbufferstack'
423=== added file 'plugins/opengl/src/vertexbufferstack/CMakeLists.txt'
424--- plugins/opengl/src/vertexbufferstack/CMakeLists.txt 1970-01-01 00:00:00 +0000
425+++ plugins/opengl/src/vertexbufferstack/CMakeLists.txt 2012-09-09 16:26:19 +0000
426@@ -0,0 +1,25 @@
427+INCLUDE_DIRECTORIES (
428+ ${COMPIZ_OPENGL_SOURCE_DIR}
429+ ${COMPIZ_OPENGL_INCLUDE_DIR}
430+ ${CMAKE_CURRENT_SOURCE_DIR}/include
431+ ${CMAKE_CURRENT_SOURCE_DIR}/src
432+
433+ ${Boost_INCLUDE_DIRS}
434+)
435+
436+LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
437+
438+SET(
439+ SRCS
440+ ${CMAKE_CURRENT_SOURCE_DIR}/src/vertex-buffer-stack.cpp
441+)
442+
443+ADD_LIBRARY(
444+ compiz_opengl_vertex_buffer_stack STATIC
445+
446+ ${SRCS}
447+)
448+
449+if (COMPIZ_BUILD_TESTING)
450+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
451+endif (COMPIZ_BUILD_TESTING)
452
453=== added directory 'plugins/opengl/src/vertexbufferstack/include'
454=== added file 'plugins/opengl/src/vertexbufferstack/include/vertexbufferstack-internal.h'
455--- plugins/opengl/src/vertexbufferstack/include/vertexbufferstack-internal.h 1970-01-01 00:00:00 +0000
456+++ plugins/opengl/src/vertexbufferstack/include/vertexbufferstack-internal.h 2012-09-09 16:26:19 +0000
457@@ -0,0 +1,67 @@
458+/*
459+ * Compiz opengl plugin, VertexBufferStack interface
460+ *
461+ * Copyright (c) 2012 Canonical Ltd.
462+ * Author: Sam Spilsbury <sam.spilsbury@canonical.com>
463+ *
464+ * Permission is hereby granted, free of charge, to any person obtaining a
465+ * copy of this software and associated documentation files (the "Software"),
466+ * to deal in the Software without restriction, including without limitation
467+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
468+ * and/or sell copies of the Software, and to permit persons to whom the
469+ * Software is furnished to do so, subject to the following conditions:
470+ *
471+ * The above copyright notice and this permission notice shall be included in
472+ * all copies or substantial portions of the Software.
473+ *
474+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
475+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
476+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
477+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
478+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
479+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
480+ * DEALINGS IN THE SOFTWARE.
481+ */
482+#ifndef __COMPIZ_OPENGL_VERTEXBUFFERSTACKINTERNAL_H
483+#define __COMPIZ_OPENGL_VERTEXBUFFERSTACKINTERNAL_H
484+
485+#include <opengl/vertexbufferstack.h>
486+
487+namespace compiz
488+{
489+ namespace opengl
490+ {
491+ namespace impl
492+ {
493+ namespace cgl = compiz::opengl;
494+
495+ class PrivateVertexBufferStack;
496+
497+ class VertexBufferStack :
498+ public cgl::VertexBufferStack
499+ {
500+ public:
501+
502+ VertexBufferStack ();
503+ ~VertexBufferStack ();
504+
505+ void pushVertexBuffer (const GLVertexBufferPtr &);
506+ bool removeLastVertexBuffer (const GLVertexBufferPtr &);
507+ bool removeVertexBuffer (const GLVertexBufferPtr &);
508+ void popVertexBufferFromTop ();
509+ const GLVertexBufferWeak & activeVertexBuffer () const;
510+
511+ private:
512+
513+ PrivateVertexBufferStack *priv;
514+ };
515+ }
516+ }
517+}
518+
519+bool operator== (const compiz::opengl::GLVertexBufferWeak &lhs,
520+ const compiz::opengl::GLVertexBufferWeak &rhs);
521+bool operator!= (const compiz::opengl::GLVertexBufferWeak &lhs,
522+ const compiz::opengl::GLVertexBufferWeak &rhs);
523+
524+#endif
525
526=== added directory 'plugins/opengl/src/vertexbufferstack/src'
527=== added file 'plugins/opengl/src/vertexbufferstack/src/vertex-buffer-stack.cpp'
528--- plugins/opengl/src/vertexbufferstack/src/vertex-buffer-stack.cpp 1970-01-01 00:00:00 +0000
529+++ plugins/opengl/src/vertexbufferstack/src/vertex-buffer-stack.cpp 2012-09-09 16:26:19 +0000
530@@ -0,0 +1,145 @@
531+/*
532+ * Compiz, opengl plugin, VertexBufferStack class
533+ *
534+ * Copyright (c) 2012 Canonical Ltd.
535+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
536+ *
537+ * Permission is hereby granted, free of charge, to any person obtaining a
538+ * copy of this software and associated documentation files (the "Software"),
539+ * to deal in the Software without restriction, including without limitation
540+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
541+ * and/or sell copies of the Software, and to permit persons to whom the
542+ * Software is furnished to do so, subject to the following conditions:
543+ *
544+ * The above copyright notice and this permission notice shall be included in
545+ * all copies or substantial portions of the Software.
546+ *
547+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
548+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
549+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
550+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
551+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
552+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
553+ * DEALINGS IN THE SOFTWARE.
554+ */
555+#include <algorithm>
556+#include <vector>
557+#include "vertexbufferstack-internal.h"
558+
559+namespace cgl = compiz::opengl;
560+namespace cgli = compiz::opengl::impl;
561+
562+class GLVertexBuffer;
563+
564+namespace compiz
565+{
566+ namespace opengl
567+ {
568+ namespace impl
569+ {
570+ class PrivateVertexBufferStack
571+ {
572+ public:
573+
574+ std::vector <cgl::GLVertexBufferWeak> savedVertexBuffers;
575+ cgl::GLVertexBufferWeak activeVertexBuffer;
576+ };
577+ }
578+ }
579+}
580+
581+bool operator== (const compiz::opengl::GLVertexBufferWeak &lhs,
582+ const compiz::opengl::GLVertexBufferWeak &rhs)
583+{
584+ return lhs.lock () == rhs.lock ();
585+}
586+
587+bool operator!= (const compiz::opengl::GLVertexBufferWeak &lhs,
588+ const compiz::opengl::GLVertexBufferWeak &rhs)
589+{
590+ return !(lhs == rhs);
591+}
592+
593+cgli::VertexBufferStack::VertexBufferStack () :
594+ priv (new PrivateVertexBufferStack)
595+{
596+}
597+
598+cgli::VertexBufferStack::~VertexBufferStack ()
599+{
600+ delete priv;
601+}
602+
603+void
604+cgli::VertexBufferStack::pushVertexBuffer (const cgl::GLVertexBufferPtr &vb)
605+{
606+ priv->savedVertexBuffers.push_back (priv->activeVertexBuffer);
607+ priv->activeVertexBuffer = vb;
608+}
609+
610+void
611+cgli::VertexBufferStack::popVertexBufferFromTop ()
612+{
613+ if (!priv->savedVertexBuffers.empty ())
614+ priv->activeVertexBuffer = priv->savedVertexBuffers.back ();
615+ else
616+ priv->activeVertexBuffer.reset ();
617+
618+ priv->savedVertexBuffers.pop_back ();
619+}
620+
621+bool
622+cgli::VertexBufferStack::removeLastVertexBuffer (const GLVertexBufferPtr &vb)
623+{
624+ cgl::GLVertexBufferWeak weak (vb);
625+ std::vector <cgl::GLVertexBufferWeak>::reverse_iterator rit = priv->savedVertexBuffers.rbegin ();
626+
627+ if (weak == priv->activeVertexBuffer)
628+ {
629+ popVertexBufferFromTop ();
630+ return true;
631+ }
632+
633+ while (rit != priv->savedVertexBuffers.rend ())
634+ {
635+ if (*rit == weak)
636+ {
637+ priv->savedVertexBuffers.erase (rit.base () - 1);
638+ return true;
639+ }
640+
641+ ++rit;
642+ };
643+
644+ return false;
645+}
646+
647+bool
648+cgli::VertexBufferStack::removeVertexBuffer (const cgl::GLVertexBufferPtr &vb)
649+{
650+ bool found = false;
651+
652+ while (removeLastVertexBuffer (vb))
653+ found = true;
654+
655+ return found;
656+}
657+
658+const cgl::GLVertexBufferWeak &
659+cgli::VertexBufferStack::activeVertexBuffer () const
660+{
661+ return priv->activeVertexBuffer;
662+}
663+
664+cgl::VertexBufferPush::VertexBufferPush (cgl::VertexBufferStack &vbStack,
665+ const cgl::GLVertexBufferPtr &vertexBuffer) :
666+ mVBStack (vbStack),
667+ mVertexBuffer (vertexBuffer)
668+{
669+ vbStack.pushVertexBuffer (vertexBuffer);
670+}
671+
672+cgl::VertexBufferPush::~VertexBufferPush ()
673+{
674+ mVBStack.removeLastVertexBuffer (mVertexBuffer);
675+}
676
677=== added directory 'plugins/opengl/src/vertexbufferstack/tests'
678=== added file 'plugins/opengl/src/vertexbufferstack/tests/CMakeLists.txt'
679--- plugins/opengl/src/vertexbufferstack/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
680+++ plugins/opengl/src/vertexbufferstack/tests/CMakeLists.txt 2012-09-09 16:26:19 +0000
681@@ -0,0 +1,24 @@
682+find_library (GMOCK_LIBRARY gmock)
683+find_library (GMOCK_MAIN_LIBRARY gmock_main)
684+
685+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
686+ message ("Google Mock and Google Test not found - cannot build tests!")
687+ set (COMPIZ_BUILD_TESTING OFF)
688+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
689+
690+include_directories (${GTEST_INCLUDE_DIRS})
691+
692+link_directories (${COMPIZ_LIBRARY_DIRS})
693+
694+add_executable (compiz_test_opengl_vertex_buffer_stack
695+ ${CMAKE_CURRENT_SOURCE_DIR}/test-opengl-vertex-buffer-stack.cpp)
696+
697+target_link_libraries (compiz_test_opengl_vertex_buffer_stack
698+ compiz_opengl_vertex_buffer_stack
699+ ${GTEST_BOTH_LIBRARIES}
700+ ${GMOCK_LIBRARY}
701+ ${GMOCK_MAIN_LIBRARY}
702+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
703+ )
704+
705+compiz_discover_tests (compiz_test_opengl_vertex_buffer_stack COVERAGE compiz_opengl_vertex_buffer_stack)
706
707=== added file 'plugins/opengl/src/vertexbufferstack/tests/test-opengl-vertex-buffer-stack.cpp'
708--- plugins/opengl/src/vertexbufferstack/tests/test-opengl-vertex-buffer-stack.cpp 1970-01-01 00:00:00 +0000
709+++ plugins/opengl/src/vertexbufferstack/tests/test-opengl-vertex-buffer-stack.cpp 2012-09-09 16:26:19 +0000
710@@ -0,0 +1,256 @@
711+/*
712+ * Compiz, opengl plugin, VertexBufferStack class
713+ *
714+ * Copyright (c) 2012 Canonical Ltd.
715+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
716+ *
717+ * Permission is hereby granted, free of charge, to any person obtaining a
718+ * copy of this software and associated documentation files (the "Software"),
719+ * to deal in the Software without restriction, including without limitation
720+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
721+ * and/or sell copies of the Software, and to permit persons to whom the
722+ * Software is furnished to do so, subject to the following conditions:
723+ *
724+ * The above copyright notice and this permission notice shall be included in
725+ * all copies or substantial portions of the Software.
726+ *
727+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
728+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
729+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
730+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
731+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
732+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
733+ * DEALINGS IN THE SOFTWARE.
734+ */
735+#include <boost/make_shared.hpp>
736+#include <gtest/gtest.h>
737+#include <gmock/gmock.h>
738+#include "vertexbufferstack-internal.h"
739+
740+using ::testing::MatcherInterface;
741+using ::testing::MakeMatcher;
742+using ::testing::MatchResultListener;
743+using ::testing::Matcher;
744+
745+template <class P>
746+class ExpiredPtrMatcher :
747+ public ::testing::MatcherInterface <const boost::weak_ptr <P> &>
748+{
749+ public:
750+
751+ bool MatchAndExplain (const boost::weak_ptr <P> &x, MatchResultListener *listener) const
752+ {
753+ return x.expired ();
754+ }
755+
756+ void DescribeTo (std::ostream *os) const
757+ {
758+ *os << "is expired";
759+ }
760+
761+ void DescribeNegationTo (std::ostream *os) const
762+ {
763+ *os << "is not expired";
764+ }
765+};
766+
767+template <class P>
768+inline Matcher<const boost::weak_ptr <P> &> IsExpired ()
769+{
770+ return MakeMatcher (new ExpiredPtrMatcher<P> ());
771+}
772+
773+namespace cgl = compiz::opengl;
774+namespace cgli = compiz::opengl::impl;
775+
776+class OpenGLVertexBufferStackTest :
777+ public ::testing::Test
778+{
779+ public:
780+
781+ cgli::VertexBufferStack vbStack;
782+};
783+
784+/* Provide a dummy definition of GLVertexBuffer for our purposes,
785+ * as we are only managing the pointer */
786+class GLVertexBuffer
787+{
788+};
789+
790+TEST_F (OpenGLVertexBufferStackTest, TestPushIsActive)
791+{
792+ cgl::GLVertexBufferPtr vb (boost::make_shared <GLVertexBuffer> ());
793+ cgl::GLVertexBufferWeak weak (vb);
794+
795+ vbStack.pushVertexBuffer (vb);
796+ EXPECT_EQ (weak, vbStack.activeVertexBuffer ());
797+}
798+
799+TEST_F (OpenGLVertexBufferStackTest, TestPushTwoPopFirstActive)
800+{
801+ cgl::GLVertexBufferPtr vbFirst (boost::make_shared <GLVertexBuffer> ());
802+ cgl::GLVertexBufferPtr vbSecond (boost::make_shared <GLVertexBuffer> ());
803+
804+ cgl::GLVertexBufferWeak weakFirst (vbFirst);
805+ cgl::GLVertexBufferWeak weakSecond (vbSecond);
806+
807+ vbStack.pushVertexBuffer (vbFirst);
808+ vbStack.pushVertexBuffer (vbSecond);
809+
810+ EXPECT_EQ (weakSecond, vbStack.activeVertexBuffer ());
811+
812+ vbStack.popVertexBufferFromTop ();
813+
814+ EXPECT_EQ (weakFirst, vbStack.activeVertexBuffer ());
815+}
816+
817+TEST_F (OpenGLVertexBufferStackTest, TestPushThreeRemoveSecondThirdIsActive)
818+{
819+ cgl::GLVertexBufferPtr vbFirst (boost::make_shared <GLVertexBuffer> ());
820+ cgl::GLVertexBufferPtr vbSecond (boost::make_shared <GLVertexBuffer> ());
821+ cgl::GLVertexBufferPtr vbThird (boost::make_shared <GLVertexBuffer> ());
822+
823+ cgl::GLVertexBufferWeak weakFirst (vbFirst);
824+ cgl::GLVertexBufferWeak weakSecond (vbSecond);
825+ cgl::GLVertexBufferWeak weakThird (vbThird);
826+
827+ vbStack.pushVertexBuffer (vbFirst);
828+ vbStack.pushVertexBuffer (vbSecond);
829+ vbStack.pushVertexBuffer (vbThird);
830+
831+ EXPECT_EQ (weakThird, vbStack.activeVertexBuffer ());
832+
833+ vbStack.removeVertexBuffer (vbSecond);
834+
835+ EXPECT_EQ (weakThird, vbStack.activeVertexBuffer ());
836+
837+ vbStack.popVertexBufferFromTop ();
838+
839+ EXPECT_EQ (weakFirst, vbStack.activeVertexBuffer ());
840+}
841+
842+TEST_F (OpenGLVertexBufferStackTest, TestOneAndTwoOfTheSameRemovesLast)
843+{
844+ cgl::GLVertexBufferPtr vbFirst (boost::make_shared <GLVertexBuffer> ());
845+ cgl::GLVertexBufferPtr vbSecond (boost::make_shared <GLVertexBuffer> ());
846+ cgl::GLVertexBufferPtr vbThird (vbSecond);
847+ cgl::GLVertexBufferPtr vbFourth (boost::make_shared <GLVertexBuffer> ());
848+
849+ cgl::GLVertexBufferWeak weakFirst (vbFirst);
850+ cgl::GLVertexBufferWeak weakSecond (vbSecond);
851+ cgl::GLVertexBufferWeak weakThird (vbThird);
852+ cgl::GLVertexBufferWeak weakFourth (vbFourth);
853+
854+ vbStack.pushVertexBuffer (vbFirst);
855+ vbStack.pushVertexBuffer (vbSecond);
856+ vbStack.pushVertexBuffer (vbThird);
857+ vbStack.pushVertexBuffer (vbFourth);
858+
859+ EXPECT_EQ (weakFourth, vbStack.activeVertexBuffer ());
860+
861+ vbStack.removeLastVertexBuffer (vbThird);
862+
863+ EXPECT_EQ (weakFourth, vbStack.activeVertexBuffer ());
864+
865+ vbStack.popVertexBufferFromTop ();
866+
867+ EXPECT_EQ (weakSecond, vbStack.activeVertexBuffer ());
868+
869+ vbStack.popVertexBufferFromTop ();
870+
871+ EXPECT_EQ (weakFirst, vbStack.activeVertexBuffer ());
872+}
873+
874+TEST_F (OpenGLVertexBufferStackTest, TestPushTwoRemoveLastFirstIsActive)
875+{
876+ cgl::GLVertexBufferPtr vbFirst (boost::make_shared <GLVertexBuffer> ());
877+ cgl::GLVertexBufferPtr vbSecond (boost::make_shared <GLVertexBuffer> ());
878+
879+ cgl::GLVertexBufferWeak weakFirst (vbFirst);
880+ cgl::GLVertexBufferWeak weakSecond (vbSecond);
881+
882+ vbStack.pushVertexBuffer (vbFirst);
883+ vbStack.pushVertexBuffer (vbSecond);
884+
885+ EXPECT_EQ (weakSecond, vbStack.activeVertexBuffer ());
886+
887+ vbStack.removeVertexBuffer (vbSecond);
888+
889+ EXPECT_EQ (weakFirst, vbStack.activeVertexBuffer ());
890+
891+ vbStack.popVertexBufferFromTop ();
892+
893+ EXPECT_THAT (vbStack.activeVertexBuffer (), IsExpired <GLVertexBuffer> ());
894+}
895+
896+TEST_F (OpenGLVertexBufferStackTest, TestPushAndRemoveNoneActive)
897+{
898+ cgl::GLVertexBufferPtr vb (boost::make_shared <GLVertexBuffer> ());
899+ cgl::GLVertexBufferWeak weak (vb);
900+
901+ vbStack.pushVertexBuffer (vb);
902+ EXPECT_EQ (weak, vbStack.activeVertexBuffer ());
903+ vbStack.removeVertexBuffer (vb);
904+ EXPECT_THAT (vbStack.activeVertexBuffer (), IsExpired <GLVertexBuffer> ());
905+}
906+
907+TEST_F (OpenGLVertexBufferStackTest, TestPushAndRemoveBothTheSameNoneActive)
908+{
909+ cgl::GLVertexBufferPtr vb (boost::make_shared <GLVertexBuffer> ());
910+ cgl::GLVertexBufferPtr vbIdentical (vb);
911+ cgl::GLVertexBufferWeak weak (vb);
912+ cgl::GLVertexBufferWeak weakIdentical (weak);
913+
914+ vbStack.pushVertexBuffer (vb);
915+ vbStack.pushVertexBuffer (vbIdentical);
916+ EXPECT_EQ (weak, vbStack.activeVertexBuffer ());
917+ vbStack.removeVertexBuffer (vb);
918+ EXPECT_THAT (vbStack.activeVertexBuffer (), IsExpired <GLVertexBuffer> ());
919+}
920+
921+TEST_F (OpenGLVertexBufferStackTest, TestPushAndRemoveNonPushedDoesNothing)
922+{
923+ cgl::GLVertexBufferPtr vb (boost::make_shared <GLVertexBuffer> ());
924+ cgl::GLVertexBufferWeak weak (vb);
925+ cgl::GLVertexBufferPtr nonExistant;
926+
927+ vbStack.pushVertexBuffer (vb);
928+ EXPECT_EQ (weak, vbStack.activeVertexBuffer ());
929+ vbStack.removeVertexBuffer (nonExistant);
930+ EXPECT_EQ (weak, vbStack.activeVertexBuffer ());
931+}
932+
933+TEST_F (OpenGLVertexBufferStackTest, TestVertexBufferPushObject)
934+{
935+ cgl::GLVertexBufferPtr vb (boost::make_shared <GLVertexBuffer> ());
936+ cgl::GLVertexBufferWeak weak (vb);
937+
938+ {
939+ cgl::VertexBufferPush pushedVertexBuffer (vbStack, vb);
940+
941+ EXPECT_EQ (vbStack.activeVertexBuffer (), weak);
942+ }
943+
944+ EXPECT_THAT (vbStack.activeVertexBuffer (), IsExpired <GLVertexBuffer> ());
945+}
946+
947+TEST_F (OpenGLVertexBufferStackTest, TestVertexBufferPushTwoIdenticalObjectOnlyRemovesOneEach)
948+{
949+ cgl::GLVertexBufferPtr vb (boost::make_shared <GLVertexBuffer> ());
950+ cgl::GLVertexBufferPtr vbIdentical (vb);
951+ cgl::GLVertexBufferWeak weak (vb);
952+
953+ {
954+ cgl::VertexBufferPush pushedVertexBuffer (vbStack, vb);
955+
956+ {
957+ cgl::VertexBufferPush pushedVertexBuffer (vbStack, vbIdentical);
958+
959+ EXPECT_EQ (vbStack.activeVertexBuffer (), weak);
960+ }
961+
962+ EXPECT_EQ (vbStack.activeVertexBuffer (), weak);
963+ }
964+
965+ EXPECT_THAT (vbStack.activeVertexBuffer (), IsExpired <GLVertexBuffer> ());
966+}
967
968=== modified file 'plugins/opengl/src/window.cpp'
969--- plugins/opengl/src/window.cpp 2012-08-14 06:33:22 +0000
970+++ plugins/opengl/src/window.cpp 2012-09-09 16:26:19 +0000
971@@ -24,9 +24,12 @@
972 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
973 * David Reveman <davidr@novell.com>
974 */
975-
976+#include <boost/make_shared.hpp>
977 #include "privates.h"
978
979+namespace cgl = compiz::opengl;
980+namespace cgli = compiz::opengl::impl;
981+
982 GLWindow::GLWindow (CompWindow *w) :
983 PluginClassHandler<GLWindow, CompWindow, COMPIZ_OPENGL_ABI> (w),
984 priv (new PrivateGLWindow (w, this))
985@@ -68,6 +71,36 @@
986
987 };
988
989+const cgl::GLVertexBufferWeak &
990+PrivateGLWindow::activeVertexBuffer () const
991+{
992+ return vertexBufferStack.activeVertexBuffer ();
993+}
994+
995+void
996+PrivateGLWindow::pushVertexBuffer (const cgl::GLVertexBufferPtr &vertexBuffer)
997+{
998+ vertexBufferStack.pushVertexBuffer (vertexBuffer);
999+}
1000+
1001+void
1002+PrivateGLWindow::popVertexBufferFromTop ()
1003+{
1004+ vertexBufferStack.popVertexBufferFromTop ();
1005+}
1006+
1007+bool
1008+PrivateGLWindow::removeVertexBuffer (const cgl::GLVertexBufferPtr &vertexBuffer)
1009+{
1010+ return vertexBufferStack.removeVertexBuffer (vertexBuffer);
1011+}
1012+
1013+bool
1014+PrivateGLWindow::removeLastVertexBuffer (const cgl::GLVertexBufferPtr &vertexBuffer)
1015+{
1016+ return vertexBufferStack.removeLastVertexBuffer (vertexBuffer);
1017+}
1018+
1019 PrivateGLWindow::PrivateGLWindow (CompWindow *w,
1020 GLWindow *gw) :
1021 window (w),
1022@@ -79,11 +112,21 @@
1023 updateState (UpdateRegion | UpdateMatrix),
1024 needsRebind (true),
1025 clip (),
1026+ lastDamageRegion (),
1027+ vertexBufferDirty (false),
1028+ inGLDraw (false),
1029 bindFailed (false),
1030- vertexBuffer (new GLVertexBuffer ()),
1031- autoProgram(new GLWindowAutoProgram(this)),
1032+ /* We are using GL_DYNAMIC_DRAW here as the vertex buffer contents
1033+ * will change across different regions of the screen being damaged,
1034+ * however if the same region of the screen is being damaged (video)
1035+ * this will yeild the best performance in that case */
1036+ windowVertexBuffer (new GLVertexBuffer (GL::DYNAMIC_DRAW)),
1037+ autoProgram (new GLWindowAutoProgram(this)),
1038 icons ()
1039 {
1040+ windowVertexBuffer->setAutoProgram (autoProgram);
1041+ vertexBufferStack.pushVertexBuffer (windowVertexBuffer);
1042+
1043 paint.xScale = 1.0f;
1044 paint.yScale = 1.0f;
1045 paint.xTranslate = 0.0f;
1046@@ -92,14 +135,11 @@
1047 WindowInterface::setHandler (w);
1048 CompositeWindowInterface::setHandler (cWindow);
1049
1050- vertexBuffer->setAutoProgram(autoProgram);
1051-
1052 cWindow->setNewPixmapReadyCallback (boost::bind (&PrivateGLWindow::clearTextures, this));
1053 }
1054
1055 PrivateGLWindow::~PrivateGLWindow ()
1056 {
1057- delete vertexBuffer;
1058 delete autoProgram;
1059 cWindow->setNewPixmapReadyCallback (boost::function <void ()> ());
1060 }
1061@@ -128,6 +168,18 @@
1062 textures.clear ();
1063 }
1064
1065+compiz::opengl::VertexBufferStack &
1066+GLWindow::vertexBufferStack ()
1067+{
1068+ return *priv;
1069+}
1070+
1071+compiz::gl::AutoProgram *
1072+GLWindow::autoProgram ()
1073+{
1074+ return priv->autoProgram;
1075+}
1076+
1077 bool
1078 GLWindow::bind ()
1079 {
1080@@ -287,7 +339,7 @@
1081 GLVertexBuffer *
1082 GLWindow::vertexBuffer ()
1083 {
1084- return priv->vertexBuffer;
1085+ return priv->vertexBufferStack.activeVertexBuffer ().lock ().get ();
1086 }
1087
1088 const GLTexture::List &

Subscribers

People subscribed via source and target branches