Merge lp:~smspillaz/unity/unity.fix_864784_868120_872625v2 into lp:unity

Proposed by Sam Spilsbury
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 1816
Proposed branch: lp:~smspillaz/unity/unity.fix_864784_868120_872625v2
Merge into: lp:unity
Diff against target: 1729 lines (+1188/-297)
11 files modified
plugins/unityshell/src/BackgroundEffectHelper.cpp (+13/-0)
plugins/unityshell/src/BackgroundEffectHelper.h (+1/-1)
plugins/unityshell/src/PanelView.cpp (+1/-2)
plugins/unityshell/src/ScreenEffectFramebufferObject.cpp (+234/-0)
plugins/unityshell/src/ScreenEffectFramebufferObject.h (+87/-0)
plugins/unityshell/src/unityshell.cpp (+75/-257)
plugins/unityshell/src/unityshell.h (+7/-35)
standalone-clients/CMakeLists.txt (+16/-2)
standalone-clients/GLFuncLoader.cpp (+51/-0)
standalone-clients/GLFuncLoader.h (+33/-0)
standalone-clients/TestScreenEffectFramebufferObject.cpp (+670/-0)
To merge this branch: bzr merge lp:~smspillaz/unity/unity.fix_864784_868120_872625v2
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve
Mirco Müller Pending
Neil J. Patel Pending
Review via email: mp+86064@code.launchpad.net

This proposal supersedes a proposal from 2011-11-14.

Description of the change

Fix bug 868120 and bug 872625

We should use one framebuffer object per screen rather than one per monitor. Using one per monitor leads to all kinds of interesting rendering glitches because the plugins expect that paint is clipped to the entire backbuffer rather than paint being contained in one buffer.

This should also fix crashes on changing resolutions, as we don't have the race condition where a monitor paints and an fbo hasn't been created for it yet.

Also adds a testcase now, its in standalone-tests/TestScreenEffectFramebufferObject.cpp .

The testcase is a little quirky because we're trying to simulate what's going on when unity is actually running embedded in another opengl application, which means that we have to use nux's embedded mode rather than testing BackgroundEffectHelper directly. The testcase shows what happens in cases where parts of the scene are blurred and other parts aren't as well as what happens when some parts need updating and others don't (eg, the framebuffer should unbind). There's no automated test yet, but I imagine we could make one.

To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote : Posted in a previous version of this proposal

This branch does break the repaint-cycle. While it compiles/works/runs screen-updates only happen when a window is moved. From the diff I currently don't see what you're missing.

review: Needs Fixing
Revision history for this message
Mirco Müller (macslow) wrote : Posted in a previous version of this proposal

I tried this on my laptop (intel graphics, mesa) and it worked ok. So something odd is happening with nvidia (binary driver). Might need to see how ATI/fglrx behaves with this.

Revision history for this message
Michal Hruby (mhr3) wrote : Posted in a previous version of this proposal

Nvidia here and I can confirm MacSlow's findings.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> Nvidia here and I can confirm MacSlow's findings.

Damn, ok. Their driver is broken :( I will have to work around it.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Noted: the driver is not carrying over attributes when set using glPushAttrib (GL_CURRENT_BIT), Jay says that they should be, and this is what the mesa drivers do, so NVIDIA should know about this.

Revision history for this message
Michal Hruby (mhr3) wrote : Posted in a previous version of this proposal

I can confirm that it properly repaints now, can't test multiple monitors though.

Revision history for this message
Jason Smith (jassmith) wrote : Posted in a previous version of this proposal

+1

review: Approve
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Can someone with fglrx test this ?

Revision history for this message
Gord Allott (gordallott) wrote : Posted in a previous version of this proposal

On 11/10/11 12:18, Sam Spilsbury wrote:
> Noted: the driver is not carrying over attributes when set using glPushAttrib (GL_CURRENT_BIT), Jay says that they should be, and this is what the mesa drivers do, so NVIDIA should know about this.

merge approved

--
Gordon Allott
Canonical Ltd.
27 Floor, Millbank Tower
London SW1P 4QP
www.canonical.com

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Testcase is to make sure that the screen actually redraws the way you'd expect it to. Bonus points if you can

 1) Test with multiple monitors to make sure the blur is correct on both
 2) No blur offsets
 3) No "flickering" when switching workspaces using expo
 4) No crashes when you hotplug a monitor on intel.

There is no unit test.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

*cough* *cough* someone test this on fglrx *cough*

Revision history for this message
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal

Instead of
  uScreen->_fbo = UnityFBO::Ptr (new UnityFBO (geometry));
you can go
  uScreen->_fbo.reset(new UnityFBO(geometry));

Saves a little typing (and it is more efficient in behaviour),

  UnityFBO::UnityFBO (CompRect geometry)
should be
  UnityFBO::UnityFBO(CompRect const& geometry)

Avoids an extra copy.

Revision history for this message
Jason Smith (jassmith) wrote : Posted in a previous version of this proposal

This requires testing for merge

review: Needs Fixing
Revision history for this message
Mirco Müller (macslow) wrote :

I checked this again. It works on nvidia (binary driver) now. Still unable to test it on any ATI-gfx-card, due to lack of hardware.

Regarding the missing unit-test... you could at least add a manual-test derived from your bullet-point list you posted in the comments. Than I'd be ok to give it a +1 when we found someone to test it successfully in a ATI-gfx-card.

Revision history for this message
Jason Smith (jassmith) wrote :

Works like the other oem branch afaict, no merge conflicts after time. I say approve :)

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

standalone-clients/TestScreenEffectFramebufferObject is a unit test in this case. It isn't automated, but it should how how the code works and you can test every possible case it hits.

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

For the record, this proposal also contains the fixes for bug 861061 and bug 880707. This is because Sam's branches copied the fix from lp:~vanvugt/unity/fix-861061-trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/BackgroundEffectHelper.cpp'
2--- plugins/unityshell/src/BackgroundEffectHelper.cpp 2011-09-28 05:19:39 +0000
3+++ plugins/unityshell/src/BackgroundEffectHelper.cpp 2012-01-05 02:50:45 +0000
4@@ -85,7 +85,20 @@
5 bool BackgroundEffectHelper::HasEnabledHelpers()
6 {
7 for (BackgroundEffectHelper * bg_effect_helper : registered_list_)
8+ {
9 if (bg_effect_helper->enabled)
10+ {
11+ return true;
12+ }
13+ }
14+
15+ return false;
16+}
17+
18+bool BackgroundEffectHelper::HasDirtyHelpers()
19+{
20+ for (BackgroundEffectHelper * bg_effect_helper : registered_list_)
21+ if (bg_effect_helper->enabled && bg_effect_helper->cache_dirty)
22 return true;
23
24 return false;
25
26=== modified file 'plugins/unityshell/src/BackgroundEffectHelper.h'
27--- plugins/unityshell/src/BackgroundEffectHelper.h 2011-10-19 22:13:57 +0000
28+++ plugins/unityshell/src/BackgroundEffectHelper.h 2012-01-05 02:50:45 +0000
29@@ -53,7 +53,7 @@
30 void DirtyCache();
31
32 static void ProcessDamage(nux::Geometry geo);
33-
34+ static bool HasDirtyHelpers();
35 static bool HasEnabledHelpers();
36
37 static nux::Property<unity::BlurType> blur_type;
38
39=== modified file 'plugins/unityshell/src/PanelView.cpp'
40--- plugins/unityshell/src/PanelView.cpp 2011-12-19 20:20:22 +0000
41+++ plugins/unityshell/src/PanelView.cpp 2012-01-05 02:50:45 +0000
42@@ -616,8 +616,7 @@
43
44 _opacity = opacity;
45
46- if (_opacity < 1.0f && !_dash_is_open)
47- bg_effect_helper_.enabled = false;
48+ bg_effect_helper_.enabled = (_opacity < 1.0f || _dash_is_open);
49
50 ForceUpdateBackground();
51 }
52
53=== added file 'plugins/unityshell/src/ScreenEffectFramebufferObject.cpp'
54--- plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 1970-01-01 00:00:00 +0000
55+++ plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-01-05 02:50:45 +0000
56@@ -0,0 +1,234 @@
57+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
58+/* Compiz unity plugin
59+ * unity.h
60+ *
61+ * Copyright (c) 2010-11 Canonical Ltd.
62+ *
63+ * This program is free software; you can redistribute it and/or
64+ * modify it under the terms of the GNU General Public License
65+ * as published by the Free Software Foundation; either version 3
66+ * of the License, or (at your option) any later version.
67+ *
68+ * This program is distributed in the hope that it will be useful,
69+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
70+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71+ * GNU General Public License for more details.
72+ *
73+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
74+ */
75+
76+#include "ScreenEffectFramebufferObject.h"
77+#include "BackgroundEffectHelper.h"
78+#include <NuxCore/Logger.h>
79+#include <dlfcn.h>
80+
81+namespace
82+{
83+ nux::logging::Logger logger ("unity.screeneffectframebufferobject");
84+}
85+
86+void unity::ScreenEffectFramebufferObject::paint (const nux::Geometry &output)
87+{
88+ /* Draw the bit of the relevant framebuffer for each output */
89+
90+ glPushAttrib (GL_VIEWPORT_BIT);
91+ glViewport (0, mScreenSize.height - (output.y + output.height), mScreenSize.width, mScreenSize.height);
92+
93+ if (mFBTexture)
94+ {
95+ glEnable (GL_TEXTURE_2D);
96+ activeTexture (GL_TEXTURE0_ARB);
97+ glBindTexture (GL_TEXTURE_2D, mFBTexture);
98+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
99+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
100+
101+ glPushAttrib (GL_SCISSOR_BIT);
102+ glEnable (GL_SCISSOR_TEST);
103+
104+ glScissor (output.x, mScreenSize.height - (output.y + output.height),
105+ output.width, output.height);
106+
107+ /* FIXME: This needs to be GL_TRIANGLE_STRIP */
108+ glBegin (GL_QUADS);
109+ glTexCoord2f (0, 1);
110+ glVertex2i (mGeometry.x, mGeometry.y);
111+ glTexCoord2f (0, 0);
112+ glVertex2i (mGeometry.x, mGeometry.y + mGeometry.height);
113+ glTexCoord2f (1, 0);
114+ glVertex2i (mGeometry.x + mGeometry.width, mGeometry.y + mGeometry.height);
115+ glTexCoord2f (1, 1);
116+ glVertex2i (mGeometry.x + mGeometry.width, mGeometry.y);
117+ glEnd ();
118+
119+ activeTexture (GL_TEXTURE0_ARB);
120+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
121+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
122+ glBindTexture (GL_TEXTURE_2D, 0);
123+ glDisable (GL_TEXTURE_2D);
124+ glPopAttrib ();
125+ }
126+ glPopAttrib ();
127+}
128+
129+void unity::ScreenEffectFramebufferObject::onScreenSizeChanged(const nux::Geometry& screenSize)
130+{
131+ mScreenSize = screenSize;
132+}
133+
134+
135+void unity::ScreenEffectFramebufferObject::unbind ()
136+{
137+ if (!mBoundCnt)
138+ return;
139+
140+ mBoundCnt--;
141+
142+ (*bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
143+
144+ glDrawBuffer (GL_BACK);
145+ glReadBuffer (GL_BACK);
146+
147+ /* Matches the viewport set we did in ::bind () */
148+ glPopAttrib ();
149+
150+}
151+
152+bool unity::ScreenEffectFramebufferObject::status ()
153+{
154+ return mFboStatus;
155+}
156+
157+void unity::ScreenEffectFramebufferObject::bind (const nux::Geometry &output)
158+{
159+ if (!BackgroundEffectHelper::HasDirtyHelpers())
160+ return;
161+
162+ /* Clear the error bit */
163+ glGetError ();
164+
165+ if (!mFBTexture)
166+ {
167+ glGenTextures (1, &mFBTexture);
168+
169+ glBindTexture (GL_TEXTURE_2D, mFBTexture);
170+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
171+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
172+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
173+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
174+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, mGeometry.width, mGeometry.height, 0, GL_BGRA,
175+#if IMAGE_BYTE_ORDER == MSBFirst
176+ GL_UNSIGNED_INT_8_8_8_8_REV,
177+#else
178+ GL_UNSIGNED_BYTE,
179+#endif
180+ NULL);
181+
182+ glBindTexture (GL_TEXTURE_2D, 0);
183+
184+ if (glGetError () != GL_NO_ERROR)
185+ {
186+ mFboHandle = 0;
187+ mFboStatus = false;
188+ return;
189+ }
190+ }
191+
192+ (*bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
193+
194+ (*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
195+ GL_TEXTURE_2D, mFBTexture, 0);
196+
197+ (*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
198+ GL_TEXTURE_2D, 0, 0);
199+
200+ /* Ensure that a framebuffer is actually available */
201+ if (!mFboStatus)
202+ {
203+ GLint status = (*checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
204+
205+ if (status != GL_FRAMEBUFFER_COMPLETE)
206+ {
207+ switch (status)
208+ {
209+ case GL_FRAMEBUFFER_UNDEFINED:
210+ LOG_WARN (logger) << "no window";
211+ break;
212+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
213+ LOG_WARN (logger) << "attachment incomplete";
214+ break;
215+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
216+ LOG_WARN (logger) << "no buffers attached to fbo";
217+ break;
218+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
219+ LOG_WARN (logger) << "some attachment in glDrawBuffers doesn't exist in FBO";
220+ break;
221+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
222+ LOG_WARN (logger) << "some attachment in glReadBuffers doesn't exist in FBO";
223+ break;
224+ case GL_FRAMEBUFFER_UNSUPPORTED:
225+ LOG_WARN (logger) << "unsupported internal format";
226+ break;
227+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
228+ LOG_WARN (logger) << "different levels of sampling for each attachment";
229+ break;
230+ case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
231+ LOG_WARN (logger) << "number of layers is different";
232+ break;
233+ default:
234+ LOG_WARN (logger) << "unable to bind the framebuffer for an unknown reason";
235+ break;
236+ }
237+
238+ bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
239+ deleteFramebuffers (1, &mFboHandle);
240+
241+ glDrawBuffer (GL_BACK);
242+ glReadBuffer (GL_BACK);
243+
244+ mFboHandle = 0;
245+
246+ mFboStatus = false;
247+ }
248+ else
249+ mFboStatus = true;
250+ }
251+
252+ if (mFboStatus)
253+ {
254+ glPushAttrib (GL_VIEWPORT_BIT);
255+
256+ glViewport (output.x,
257+ mScreenSize.height - (output.y + output.height),
258+ output.width,
259+ output.height);
260+ }
261+
262+ mBoundCnt++;
263+}
264+
265+
266+unity::ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom)
267+ : getProcAddressGLX (p)
268+ , mFboStatus (false)
269+ , mFBTexture (0)
270+ , mGeometry (geom)
271+ , mBoundCnt (0)
272+ , mScreenSize (geom)
273+{
274+ activeTexture = (GLActiveTextureProc) (*getProcAddressGLX) ((GLubyte *) "glActiveTexture");
275+ genFramebuffers = (GLGenFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glGenFramebuffersEXT");
276+ deleteFramebuffers = (GLDeleteFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glDeleteFramebuffersEXT");
277+ bindFramebuffer = (GLBindFramebufferProc) (*getProcAddressGLX) ((GLubyte *)"glBindFramebufferEXT");
278+ checkFramebufferStatus = (GLCheckFramebufferStatusProc) (*getProcAddressGLX) ((GLubyte *) "glCheckFramebufferStatusEXT");
279+ framebufferTexture2D = (GLFramebufferTexture2DProc) (*getProcAddressGLX) ((GLubyte *) "glFramebufferTexture2DEXT");
280+
281+ (*genFramebuffers) (1, &mFboHandle);
282+}
283+
284+unity::ScreenEffectFramebufferObject::~ScreenEffectFramebufferObject ()
285+{
286+ (*deleteFramebuffers) (1, &mFboHandle);
287+
288+ if (mFBTexture)
289+ glDeleteTextures (1, &mFBTexture);
290+}
291
292=== added file 'plugins/unityshell/src/ScreenEffectFramebufferObject.h'
293--- plugins/unityshell/src/ScreenEffectFramebufferObject.h 1970-01-01 00:00:00 +0000
294+++ plugins/unityshell/src/ScreenEffectFramebufferObject.h 2012-01-05 02:50:45 +0000
295@@ -0,0 +1,87 @@
296+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
297+/* Compiz unity plugin
298+ * unity.h
299+ *
300+ * Copyright (c) 2010-11 Canonical Ltd.
301+ *
302+ * This program is free software; you can redistribute it and/or
303+ * modify it under the terms of the GNU General Public License
304+ * as published by the Free Software Foundation; either version 3
305+ * of the License, or (at your option) any later version.
306+ *
307+ * This program is distributed in the hope that it will be useful,
308+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
309+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
310+ * GNU General Public License for more details.
311+ *
312+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
313+ */
314+
315+#ifndef UNITY_SCREENEFFECT_FRAMEBUFFER_H
316+#define UNITY_SCREENEFFECT_FRAMEBUFFER_H
317+
318+#include <Nux/Nux.h>
319+
320+namespace unity
321+{
322+class ScreenEffectFramebufferObject
323+{
324+public:
325+
326+ typedef boost::shared_ptr <ScreenEffectFramebufferObject> Ptr;
327+ typedef void (*FuncPtr) (void);
328+ typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
329+
330+ ScreenEffectFramebufferObject (GLXGetProcAddressProc, const nux::Geometry &geom);
331+ ~ScreenEffectFramebufferObject ();
332+
333+public:
334+
335+ void bind (const nux::Geometry &geom);
336+ void unbind ();
337+
338+ bool status ();
339+ void paint (const nux::Geometry &geom);
340+ bool bound () { return mBoundCnt > 0; }
341+
342+ GLuint texture () { return mFBTexture; }
343+
344+ void onScreenSizeChanged (const nux::Geometry &screenSize);
345+
346+private:
347+
348+ FuncPtr getProcAddr (const std::string &);
349+
350+ typedef void (*GLActiveTextureProc) (GLenum texture);
351+ typedef void (*GLGenFramebuffersProc) (GLsizei n,
352+ GLuint *framebuffers);
353+ typedef void (*GLDeleteFramebuffersProc) (GLsizei n,
354+ GLuint *framebuffers);
355+ typedef void (*GLBindFramebufferProc) (GLenum target,
356+ GLuint framebuffer);
357+ typedef GLenum (*GLCheckFramebufferStatusProc) (GLenum target);
358+ typedef void (*GLFramebufferTexture2DProc) (GLenum target,
359+ GLenum attachment,
360+ GLenum textarget,
361+ GLuint texture,
362+ GLint level);
363+
364+ GLXGetProcAddressProc getProcAddressGLX;
365+ GLActiveTextureProc activeTexture;
366+ GLGenFramebuffersProc genFramebuffers;
367+ GLDeleteFramebuffersProc deleteFramebuffers;
368+ GLBindFramebufferProc bindFramebuffer;
369+ GLCheckFramebufferStatusProc checkFramebufferStatus;
370+ GLFramebufferTexture2DProc framebufferTexture2D;
371+ /* compiz fbo handle that goes through to nux */
372+ GLuint mFboHandle; // actual handle to the framebuffer_ext
373+ bool mFboStatus; // did the framebuffer texture bind succeed
374+ GLuint mFBTexture;
375+ nux::Geometry mGeometry;
376+ unsigned int mBoundCnt;
377+
378+ nux::Geometry mScreenSize;
379+};
380+} // namespace unity
381+
382+#endif
383
384=== modified file 'plugins/unityshell/src/unityshell.cpp'
385--- plugins/unityshell/src/unityshell.cpp 2012-01-02 20:51:09 +0000
386+++ plugins/unityshell/src/unityshell.cpp 2012-01-05 02:50:45 +0000
387@@ -65,7 +65,6 @@
388 /* Set up vtable symbols */
389 COMPIZ_PLUGIN_20090315(unityshell, unity::UnityPluginVTable);
390
391-
392 namespace unity
393 {
394 using launcher::AbstractLauncherIcon;
395@@ -114,7 +113,7 @@
396 , damaged(false)
397 , _key_nav_mode_requested(false)
398 , _last_output(nullptr)
399- , mActiveFbo (0)
400+ , _active_fbo (0)
401 , dash_is_open_ (false)
402 , grab_index_ (0)
403 , painting_tray_ (false)
404@@ -227,12 +226,21 @@
405 _edge_timeout = optionGetLauncherRevealEdgeTimeout ();
406 _in_paint = false;
407
408+ void *dlhand = dlopen ("libunityshell.so", RTLD_LAZY);
409+
410+ if (dlhand)
411+ {
412+ dlerror ();
413+ glXGetProcAddressP = (ScreenEffectFramebufferObject::GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
414+ if (dlerror () != NULL)
415+ glXGetProcAddressP = NULL;
416+ }
417+
418 if (GL::fbo)
419 {
420- foreach (CompOutput & o, screen->outputDevs())
421- uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO(&o));
422-
423- uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO(&(screen->fullscreenOutput ())));
424+ nux::Geometry geometry (0, 0, screen->width (), screen->height ());
425+ uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
426+ uScreen->_fbo->onScreenSizeChanged (geometry);
427 }
428
429 optionSetBackgroundColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
430@@ -451,7 +459,7 @@
431
432 void UnityScreen::nuxEpilogue()
433 {
434- (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, mActiveFbo);
435+ (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo);
436
437 glMatrixMode(GL_PROJECTION);
438 glLoadIdentity();
439@@ -492,8 +500,6 @@
440 if (PluginAdapter::Default()->IsExpoActive())
441 return;
442
443- nuxPrologue();
444-
445 CompOutput* output = _last_output;
446 float vc[4];
447 float h = 20.0f;
448@@ -504,6 +510,9 @@
449 float y1 = output->y() + panel_h;
450 float x2 = x1 + output->width();
451 float y2 = y1 + h;
452+ GLMatrix sTransform = GLMatrix ();
453+
454+ sTransform.toScreenSpace(output, -DEFAULT_Z_CAMERA);
455
456 vc[0] = x1;
457 vc[1] = x2;
458@@ -543,7 +552,6 @@
459 glDisable(GL_BLEND);
460 }
461 }
462- nuxEpilogue();
463 }
464
465 void
466@@ -562,30 +570,35 @@
467 {
468 CompOutput *output = _last_output;
469 Window tray_xid = panel_controller_->GetTrayXid ();
470- bool bound = mFbos[output]->bound ();
471-
472-
473- if (bound)
474+
475+ bool was_bound = _fbo->bound ();
476+ _fbo->unbind ();
477+
478+ /* Draw the bit of the relevant framebuffer for each output */
479+
480+ if (was_bound)
481 {
482- mFbos[output]->unbind ();
483-
484- /* Draw the bit of the relevant framebuffer for each output */
485- mFbos[output]->paint ();
486+ GLMatrix sTransform;
487+ sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
488+ glPushMatrix ();
489+ glLoadMatrixf (sTransform.getMatrix ());
490+ _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
491+ glPopMatrix ();
492 }
493
494- nuxPrologue();
495-
496 nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
497- nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(mFbos[output]->texture(),
498- output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
499+ nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),
500+ screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
501
502 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
503
504- nux::Geometry geo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
505+ nux::Geometry geo = nux::Geometry (0, 0, screen->width (), screen->height ());
506+ nux::Geometry oGeo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
507 BackgroundEffectHelper::monitor_rect_ = geo;
508
509+ nuxPrologue();
510 _in_paint = true;
511- wt->RenderInterfaceFromForeignCmd (&geo);
512+ wt->RenderInterfaceFromForeignCmd (&oGeo);
513 _in_paint = false;
514 nuxEpilogue();
515
516@@ -985,6 +998,10 @@
517 {
518 bool ret;
519
520+ doShellRepaint = true;
521+ allowWindowPaint = true;
522+ _last_output = output;
523+
524 /* bind the framebuffer here
525 * - it will be unbound and flushed
526 * to the backbuffer when some
527@@ -995,11 +1012,7 @@
528 * attempts to bind it will only increment
529 * its bind reference so make sure that
530 * you always unbind as much as you bind */
531- mFbos[output]->bind ();
532-
533- doShellRepaint = true;
534- allowWindowPaint = true;
535- _last_output = output;
536+ _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
537
538 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
539 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
540@@ -1160,16 +1173,37 @@
541 {
542 XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
543 CompWindow* w = screen->findWindow (de->drawable);
544+ std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
545+ CompWindow* lastNWindow = screen->findWindow (xwns.back ());
546+ bool processDamage = true;
547
548- if (w and !(w->wmType() & CompWindowTypeDndMask))
549+ if (w)
550 {
551- nux::Geometry damage (de->area.x, de->area.y, de->area.width, de->area.height);
552-
553- CompWindow::Geometry geom = w->geometry ();
554- damage.x += geom.x () + geom.border ();
555- damage.y += geom.y () + geom.border ();
556-
557- BackgroundEffectHelper::ProcessDamage(damage);
558+ if (!w->overrideRedirect () &&
559+ w->isViewable () &&
560+ !w->invisible ())
561+ {
562+
563+ for (; lastNWindow != NULL; lastNWindow = lastNWindow->next)
564+ {
565+ if (lastNWindow == w)
566+ {
567+ processDamage = false;
568+ break;
569+ }
570+ }
571+
572+ if (processDamage)
573+ {
574+ nux::Geometry damage (de->area.x, de->area.y, de->area.width, de->area.height);
575+
576+ const CompWindow::Geometry &geom = w->geometry ();
577+ damage.x += geom.x () + geom.border ();
578+ damage.y += geom.y () + geom.border ();
579+
580+ BackgroundEffectHelper::ProcessDamage(damage);
581+ }
582+ }
583 }
584 }
585 }
586@@ -2164,15 +2198,15 @@
587
588 void UnityScreen::Relayout()
589 {
590+ nux::Geometry geometry (0, 0, screen->width (), screen->height ());
591+
592 if (!needsRelayout)
593 return;
594
595 if (GL::fbo)
596 {
597- foreach (CompOutput &o, screen->outputDevs ())
598- uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO (&o));
599-
600- uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO (&(screen->fullscreenOutput ())));
601+ uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
602+ uScreen->_fbo->onScreenSizeChanged (geometry);
603 }
604
605 UScreen *uscreen = UScreen::GetDefault();
606@@ -2195,8 +2229,6 @@
607 {
608 UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);
609
610- uScreen->mFbos.clear ();
611-
612 uScr->NeedsRelayout ();
613 uScr->Relayout();
614 uScr->relayoutSourceId = 0;
615@@ -2229,220 +2261,6 @@
616 ScheduleRelayout(500);
617 }
618
619-void UnityFBO::paint ()
620-{
621- //CompositeScreen *cScreen = CompositeScreen::get (screen);
622- //unsigned int mask = cScreen->damageMask ();
623- float texx, texy, texwidth, texheight;
624-
625- /* Must be completely unbound before painting */
626- if (mBoundCnt)
627- return;
628-
629- /* Draw the bit of the relevant framebuffer for each output */
630- GLMatrix transform;
631-
632- glViewport (output->x (), screen->height () - output->y2 (), output->width (), output->height ());
633- GLScreen::get (screen)->clearOutput (output, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
634-
635- transform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
636- glPushMatrix ();
637- glLoadMatrixf (transform.getMatrix ());
638-
639- /* Note that texcoords here are normalized, so it's just (0,0)-(1,1) */
640- texx = 0.0;
641- texy = 0.0;
642- texwidth = 1.0f;
643- texheight = 1.0f;
644-
645- if (mFBTexture)
646- {
647- glEnable (GL_TEXTURE_2D);
648- GL::activeTexture (GL_TEXTURE0_ARB);
649- glBindTexture (GL_TEXTURE_2D, mFBTexture);
650- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
651- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
652-
653- glPushAttrib (GL_SCISSOR_BIT);
654- glEnable (GL_SCISSOR_TEST);
655-
656- glScissor (output->x1 (), screen->height () - output->y2 (),
657- output->width (), output->height ());
658-
659- /* FIXME: This needs to be GL_TRIANGLE_STRIP */
660- glBegin (GL_QUADS);
661- glTexCoord2f (texx, texy + texheight);
662- glVertex2i (output->x1 (), output->y1 ());
663- glTexCoord2f (texx, texy);
664- glVertex2i (output->x1 (), output->y2 ());
665- glTexCoord2f (texx + texwidth, texy);
666- glVertex2i (output->x2 (), output->y2 ());
667- glTexCoord2f (texx + texwidth, texy + texheight);
668- glVertex2i (output->x2 (), output->y1 ());
669- glEnd ();
670-
671- GL::activeTexture (GL_TEXTURE0_ARB);
672- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
673- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
674- glBindTexture (GL_TEXTURE_2D, 0);
675- glEnable (GL_TEXTURE_2D);
676-
677- glDisable (GL_SCISSOR_TEST);
678- glPopAttrib ();
679- }
680-
681- glPopMatrix();
682-}
683-
684-void UnityFBO::unbind ()
685-{
686- mBoundCnt--;
687-
688- if (mBoundCnt)
689- return;
690-
691- uScreen->setActiveFbo (0);
692- (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
693-
694- glDrawBuffer (GL_BACK);
695- glReadBuffer (GL_BACK);
696-
697-}
698-
699-bool UnityFBO::bound ()
700-{
701- return mBoundCnt > 0;
702-}
703-
704-bool UnityFBO::status ()
705-{
706- return mFboStatus;
707-}
708-
709-void UnityFBO::bind ()
710-{
711- if (mBoundCnt)
712- {
713- mBoundCnt++;
714- return;
715- }
716-
717- if (!mFBTexture)
718- {
719- glGenTextures (1, &mFBTexture);
720-
721- glBindTexture (GL_TEXTURE_2D, mFBTexture);
722- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
723- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
724- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
725- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
726- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, output->width(), output->height(), 0, GL_BGRA,
727-#if IMAGE_BYTE_ORDER == MSBFirst
728- GL_UNSIGNED_INT_8_8_8_8_REV,
729-#else
730- GL_UNSIGNED_BYTE,
731-#endif
732- NULL);
733-
734- glBindTexture (GL_TEXTURE_2D, 0);
735- }
736-
737- glGetError ();
738-
739- (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
740-
741- (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
742- GL_TEXTURE_2D, mFBTexture, 0);
743-
744- (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
745- GL_TEXTURE_2D, 0, 0);
746-
747- /* Ensure that a framebuffer is actually available */
748- if (!mFboStatus)
749- {
750- GLint status = (*GL::checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
751-
752- if (status != GL_FRAMEBUFFER_COMPLETE)
753- {
754- switch (status)
755- {
756- case GL_FRAMEBUFFER_UNDEFINED:
757- compLogMessage ("unity", CompLogLevelWarn, "no window");
758- break;
759- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
760- compLogMessage ("unity", CompLogLevelWarn, "attachment incomplete");
761- break;
762- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
763- compLogMessage ("unity", CompLogLevelWarn, "no buffers attached to fbo");
764- break;
765- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
766- compLogMessage ("unity", CompLogLevelWarn, "some attachment in glDrawBuffers doesn't exist in FBO");
767- break;
768- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
769- compLogMessage ("unity", CompLogLevelWarn, "some attachment in glReadBuffers doesn't exist in FBO");
770- break;
771- case GL_FRAMEBUFFER_UNSUPPORTED:
772- compLogMessage ("unity", CompLogLevelWarn, "unsupported internal format");
773- break;
774- case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
775- compLogMessage ("unity", CompLogLevelWarn, "different levels of sampling for each attachment");
776- break;
777- case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
778- compLogMessage ("unity", CompLogLevelWarn, "number of layers is different");
779- break;
780- default:
781- compLogMessage ("unity", CompLogLevelWarn, "unable to bind the framebuffer for an unknown reason");
782- break;
783- }
784-
785- GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
786- GL::deleteFramebuffers (1, &mFboHandle);
787-
788- glDrawBuffer (GL_BACK);
789- glReadBuffer (GL_BACK);
790-
791- mFboHandle = 0;
792-
793- mFboStatus = false;
794- uScreen->setActiveFbo (0);
795- }
796- else
797- mFboStatus = true;
798- }
799-
800- if (mFboStatus)
801- {
802- uScreen->setActiveFbo (mFboHandle);
803-
804- glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
805- glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
806-
807- glViewport (0,
808- 0,
809- output->width(),
810- output->height());
811-
812- mBoundCnt++;
813- }
814-}
815-
816-UnityFBO::UnityFBO (CompOutput *o)
817- : mFboStatus (false)
818- , mFBTexture (0)
819- , output (o)
820- , mBoundCnt (0)
821-{
822- (*GL::genFramebuffers) (1, &mFboHandle);
823-}
824-
825-UnityFBO::~UnityFBO ()
826-{
827- (*GL::deleteFramebuffers) (1, &mFboHandle);
828-
829- if (mFBTexture)
830- glDeleteTextures (1, &mFBTexture);
831-}
832-
833 void UnityScreen::OnDashRealized ()
834 {
835 /* stack any windows named "onboard" above us */
836
837=== modified file 'plugins/unityshell/src/unityshell.h'
838--- plugins/unityshell/src/unityshell.h 2011-12-15 07:08:41 +0000
839+++ plugins/unityshell/src/unityshell.h 2012-01-05 02:50:45 +0000
840@@ -47,47 +47,19 @@
841 #include "DebugDBusInterface.h"
842 #include "SwitcherController.h"
843 #include "UBusWrapper.h"
844+#include "ScreenEffectFramebufferObject.h"
845
846 #include "compizminimizedwindowhandler.h"
847 #include "BGHash.h"
848 #include <compiztoolbox/compiztoolbox.h>
849+#include <dlfcn.h>
850
851 namespace unity
852 {
853
854-class UnityFBO
855-{
856-public:
857-
858- typedef boost::shared_ptr <UnityFBO> Ptr;
859-
860- UnityFBO (CompOutput *o);
861- ~UnityFBO ();
862-
863-public:
864-
865- void bind ();
866- void unbind ();
867-
868- bool status ();
869- bool bound ();
870- void paint ();
871-
872- GLuint texture () { return mFBTexture; }
873-
874-private:
875-
876- /* compiz fbo handle that goes through to nux */
877- GLuint mFboHandle; // actual handle to the framebuffer_ext
878- bool mFboStatus; // did the framebuffer texture bind succeed
879- GLuint mFBTexture;
880- CompOutput *output;
881- unsigned int mBoundCnt;
882-};
883-
884 class UnityShowdesktopHandler
885 {
886-public:
887+ public:
888
889 UnityShowdesktopHandler (CompWindow *w);
890 ~UnityShowdesktopHandler ();
891@@ -234,8 +206,6 @@
892 void NeedsRelayout();
893 void ScheduleRelayout(guint timeout);
894
895- void setActiveFbo (GLuint fbo) { mActiveFbo = fbo; }
896-
897 bool forcePaintOnTop ();
898
899 protected:
900@@ -320,8 +290,8 @@
901
902 unity::BGHash _bghash;
903
904- std::map <CompOutput *, UnityFBO::Ptr> mFbos;
905- GLuint mActiveFbo;
906+ ScreenEffectFramebufferObject::Ptr _fbo;
907+ GLuint _active_fbo;
908
909 bool queryForShader ();
910
911@@ -332,6 +302,8 @@
912 bool painting_tray_;
913 unsigned int tray_paint_mask_;
914
915+ ScreenEffectFramebufferObject::GLXGetProcAddressProc glXGetProcAddressP;
916+
917 friend class UnityWindow;
918 };
919
920
921=== modified file 'standalone-clients/CMakeLists.txt'
922--- standalone-clients/CMakeLists.txt 2011-12-14 01:47:53 +0000
923+++ standalone-clients/CMakeLists.txt 2012-01-05 02:50:45 +0000
924@@ -26,13 +26,13 @@
925 )
926 add_definitions (${CFLAGS})
927
928-set (LIBS ${TEST_UNIT_DEPS_LIBRARIES} "-lunity-core-${UNITY_API_VERSION} -lm")
929+set (LIBS ${TEST_UNIT_DEPS_LIBRARIES} "-lunity-core-${UNITY_API_VERSION} -lm -lGL -lGLU")
930 link_libraries (${LIBS})
931
932 set (LIB_PATHS ${TEST_UNIT_DEPS_LIBRARY_DIRS})
933 link_directories (${CMAKE_BINARY_DIR}/UnityCore ${LIB_PATHS})
934
935-include_directories (. .. ../services ../UnityCore ${UNITY_SRC} ${CMAKE_BINARY_DIR})
936+include_directories (. .. ../services ../UnityCore ${UNITY_SRC} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
937
938 # We can't have convenience libs so we need to rebuild with what we need
939 # Please keep actual test files alphabetically at top and then files
940@@ -452,6 +452,20 @@
941 )
942 add_dependencies (bg-hash unity-core-${UNITY_API_VERSION})
943
944+find_package (OpenGL)
945+
946+include_directories (${OPENGL_gl_INCDIRS})
947+add_library (glfuncloader SHARED
948+ ${CMAKE_CURRENT_SOURCE_DIR}/GLFuncLoader.cpp)
949+target_link_libraries (glfuncloader dl ${OPENGL_gl_LIBRARY})
950+add_executable (screen-effect-fbo
951+ TestScreenEffectFramebufferObject.cpp
952+ ${UNITY_SRC}/ScreenEffectFramebufferObject.cpp
953+ ${UNITY_SRC}/BackgroundEffectHelper.cpp)
954+
955+target_link_libraries (screen-effect-fbo glfuncloader ${OPENGL_gl_LIBRARY})
956+add_dependencies (screen-effect-fbo ${UNITY_API_VERSION})
957+
958
959 # Custom target to make all the other targets here, add your test to this list
960 add_custom_target(standalone-clients DEPENDS dash panel launcher switcher keyutil quicklist quicklist-visuals filters filter-bar preview-applicaiton preview-generic preview-music result-view dash-style bg-hash)
961
962=== added file 'standalone-clients/GLFuncLoader.cpp'
963--- standalone-clients/GLFuncLoader.cpp 1970-01-01 00:00:00 +0000
964+++ standalone-clients/GLFuncLoader.cpp 2012-01-05 02:50:45 +0000
965@@ -0,0 +1,51 @@
966+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
967+/* Compiz unity plugin
968+ * unity.h
969+ *
970+ * Copyright (c) 2010-11 Canonical Ltd.
971+ *
972+ * This program is free software; you can redistribute it and/or
973+ * modify it under the terms of the GNU General Public License
974+ * as published by the Free Software Foundation; either version 3
975+ * of the License, or (at your option) any later version.
976+ *
977+ * This program is distributed in the hope that it will be useful,
978+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
979+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
980+ * GNU General Public License for more details.
981+ *
982+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
983+ */
984+
985+#include "GLFuncLoader.h"
986+#include <dlfcn.h>
987+
988+unity::GLLoader::FuncPtr unity::GLLoader::getProcAddr(const std::string &name)
989+{
990+ static void *dlhand = NULL;
991+ FuncPtr funcPtr = NULL;
992+
993+ glGetError ();
994+
995+ if (!funcPtr)
996+ {
997+ if (!dlhand)
998+ dlhand = dlopen ("libglfuncloader.so", RTLD_LAZY);
999+
1000+ char *error = dlerror ();
1001+
1002+ if (dlhand)
1003+ {
1004+ dlerror ();
1005+ funcPtr = (FuncPtr) dlsym (dlhand, name.c_str ());
1006+
1007+ error = dlerror ();
1008+ if (error != NULL)
1009+ funcPtr = NULL;
1010+ }
1011+ }
1012+
1013+ return funcPtr;
1014+}
1015+
1016+
1017
1018=== added file 'standalone-clients/GLFuncLoader.h'
1019--- standalone-clients/GLFuncLoader.h 1970-01-01 00:00:00 +0000
1020+++ standalone-clients/GLFuncLoader.h 2012-01-05 02:50:45 +0000
1021@@ -0,0 +1,33 @@
1022+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1023+/* Compiz unity plugin
1024+ * unity.h
1025+ *
1026+ * Copyright (c) 2010-11 Canonical Ltd.
1027+ *
1028+ * This program is free software; you can redistribute it and/or
1029+ * modify it under the terms of the GNU General Public License
1030+ * as published by the Free Software Foundation; either version 3
1031+ * of the License, or (at your option) any later version.
1032+ *
1033+ * This program is distributed in the hope that it will be useful,
1034+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1035+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1036+ * GNU General Public License for more details.
1037+ *
1038+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
1039+ */
1040+
1041+#include <string>
1042+#include <GL/gl.h>
1043+#include <GL/glx.h>
1044+
1045+namespace unity
1046+{
1047+namespace GLLoader
1048+{
1049+typedef void (*FuncPtr) (void);
1050+typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
1051+
1052+FuncPtr getProcAddr(const std::string &name);
1053+}
1054+}
1055
1056=== added file 'standalone-clients/TestScreenEffectFramebufferObject.cpp'
1057--- standalone-clients/TestScreenEffectFramebufferObject.cpp 1970-01-01 00:00:00 +0000
1058+++ standalone-clients/TestScreenEffectFramebufferObject.cpp 2012-01-05 02:50:45 +0000
1059@@ -0,0 +1,670 @@
1060+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1061+/* Compiz unity plugin
1062+ * unity.h
1063+ *
1064+ * Copyright (c) 2010-11 Canonical Ltd.
1065+ *
1066+ * This program is free software; you can redistribute it and/or
1067+ * modify it under the terms of the GNU General Public License
1068+ * as published by the Free Software Foundation; either version 3
1069+ * of the License, or (at your option) any later version.
1070+ *
1071+ * This program is distributed in the hope that it will be useful,
1072+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1073+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1074+ * GNU General Public License for more details.
1075+ *
1076+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
1077+ */
1078+
1079+#include "ScreenEffectFramebufferObject.h"
1080+#include "BackgroundEffectHelper.h"
1081+#include "GLFuncLoader.h"
1082+#include <Nux/Nux.h>
1083+#include <Nux/VLayout.h>
1084+#include <Nux/View.h>
1085+#include <Nux/BaseWindow.h>
1086+#include <Nux/WindowCompositor.h>
1087+#include <NuxCore/Logger.h>
1088+#include <NuxCore/Object.h>
1089+#include <X11/Xlib.h>
1090+#include <X11/Xutil.h>
1091+#include <GL/glx.h>
1092+#include <GL/gl.h>
1093+#include <dlfcn.h>
1094+#include <sys/poll.h>
1095+#include <unistd.h>
1096+#include <glib.h>
1097+#include <gtk/gtk.h>
1098+#include <cmath>
1099+
1100+using namespace unity::GLLoader;
1101+
1102+namespace
1103+{
1104+ nux::logging::Logger logger ("unity.test-screeneffectframebufferobject");
1105+
1106+ const static int attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT,
1107+ GLX_X_RENDERABLE, True,
1108+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
1109+ GLX_DOUBLEBUFFER, True,
1110+ GLX_RED_SIZE, 8,
1111+ GLX_GREEN_SIZE, 8,
1112+ GLX_BLUE_SIZE, 8, 0};
1113+}
1114+
1115+namespace GLFuncs
1116+{
1117+ GLXGetProcAddressProc glXGetProcAddressP;
1118+ PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfigP;
1119+ PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfigP;
1120+ PFNGLXCREATEWINDOWPROC glXCreateWindowP;
1121+ PFNGLXDESTROYWINDOWPROC glXDestroyWindowP;
1122+ PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrentP;
1123+
1124+ void init ()
1125+ {
1126+ glXGetProcAddressP = (GLXGetProcAddressProc) getProcAddr ("glXGetProcAddress");
1127+ glXChooseFBConfigP = (PFNGLXCHOOSEFBCONFIGPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXChooseFBConfig");
1128+ glXGetVisualFromFBConfigP = (PFNGLXGETVISUALFROMFBCONFIGPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXGetVisualFromFBConfig");
1129+ glXCreateWindowP = (PFNGLXCREATEWINDOWPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXCreateWindow");
1130+ glXMakeContextCurrentP = (PFNGLXMAKECONTEXTCURRENTPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXMakeContextCurrent");
1131+ glXDestroyWindowP = (PFNGLXDESTROYWINDOWPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXDestroyWindow");
1132+ }
1133+}
1134+
1135+class EffectView :
1136+ public nux::View
1137+{
1138+public:
1139+ EffectView (NUX_FILE_LINE_PROTO);
1140+ virtual ~EffectView ();
1141+
1142+ void Draw (nux::GraphicsEngine &context, bool force) { return; };
1143+ void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
1144+private:
1145+ BackgroundEffectHelper bg_effect_helper_;
1146+};
1147+
1148+class Shape
1149+{
1150+ public:
1151+
1152+ typedef boost::shared_ptr <Shape> Ptr;
1153+
1154+ Shape ();
1155+ virtual ~Shape ();
1156+
1157+ float rotation () { return mRotation; }
1158+
1159+ void draw (unsigned int width, unsigned int height) { glDraw (width, height); }
1160+ void rotate () { applyRotation (); }
1161+
1162+ protected:
1163+
1164+ float mRotation;
1165+
1166+ virtual void glDraw (unsigned int width, unsigned int height) = 0;
1167+ virtual void applyRotation () = 0;
1168+ virtual void getRotationAxes (float &x, float &y, float &z) = 0;
1169+};
1170+
1171+Shape::Shape () :
1172+ mRotation (0.0f)
1173+{
1174+}
1175+
1176+Shape::~Shape ()
1177+{
1178+}
1179+
1180+class Triangle :
1181+ public Shape
1182+{
1183+ public:
1184+
1185+ typedef boost::shared_ptr <Triangle> Ptr;
1186+
1187+ protected:
1188+
1189+ void glDraw (unsigned int width, unsigned int height);
1190+ void applyRotation () { mRotation += 5.0f; }
1191+ void getRotationAxes (float &x, float &y, float &z) { x = 0.0f; y = 1.0f; z = 0.0f; }
1192+};
1193+
1194+void
1195+Triangle::glDraw (unsigned int width, unsigned int height)
1196+{
1197+ glBegin(GL_TRIANGLES);
1198+ glColor3f(1.0f, 0.0f, 0.0f);
1199+ glVertex3f(width / 4, height, 0.0f);
1200+ glColor3f(0.0f, 1.0f, 0.0f);
1201+ glVertex3f(0.0f, 0.0f, 0.0f);
1202+ glColor3f(0.0f, 0.0f, 1.0f);
1203+ glVertex3f(width / 2, 0.0f, 0.0f);
1204+ glEnd();
1205+}
1206+
1207+class Square :
1208+ public Shape
1209+{
1210+ public:
1211+
1212+ typedef boost::shared_ptr <Square> Ptr;
1213+
1214+ protected:
1215+
1216+ void glDraw (unsigned int width, unsigned int height);
1217+ void applyRotation () { mRotation -= 2.5f; }
1218+ void getRotationAxes (float &x, float &y, float &z) { x = 1.0f; y = 0.0f; z = 0.0f; }
1219+
1220+};
1221+
1222+void
1223+Square::glDraw (unsigned int width, unsigned int height)
1224+{
1225+ glBegin(GL_QUADS);
1226+ glColor3f(sin (rotation () / 100.0f), -sin (rotation () / 100.0f), cos (rotation () / 100.0f));
1227+ glVertex3f(width / 2, height, 0.0f);
1228+ glColor3f(-sin (rotation () / 100.0f), sin (rotation () / 100.0f), cos (rotation () / 100.0f));
1229+ glVertex3f(width, height, 0.0f);
1230+ glColor3f(sin (rotation () / 100.0f), sin (rotation () / 100.0f), sin (rotation () / 100.0f));
1231+ glVertex3f(width, 0.0f, 0.0f);
1232+ glColor3f(-sin (rotation () / 100.0f), cos (rotation () / 100.0f), cos (rotation () / 100.0f));
1233+ glVertex3f(width / 2, 0.0f, 0.0f);
1234+ glEnd();
1235+}
1236+
1237+class BaseContext
1238+{
1239+ public:
1240+
1241+ BaseContext (Display *);
1242+ ~BaseContext ();
1243+
1244+ void run ();
1245+
1246+ protected:
1247+
1248+ bool eventHandler ();
1249+ bool paintDispatch ();
1250+
1251+ enum class ModifierApplication
1252+ {
1253+ Square,
1254+ Triangle,
1255+ Both
1256+ };
1257+
1258+ void nextWindowPosition ();
1259+ void nextShapeRotation ();
1260+ void setupContextForSize (unsigned int width,
1261+ unsigned int height);
1262+ void drawShape (const Shape::Ptr &) {};
1263+
1264+ private:
1265+
1266+ static gboolean onNewEvents (GIOChannel *channel,
1267+ GIOCondition condition,
1268+ gpointer data);
1269+
1270+ static gboolean onPaintTimeout (gpointer data);
1271+
1272+ static void onWindowThreadCreation (nux::NThread *thread, void *d);
1273+
1274+ Display *mDisplay;
1275+ Window mWindow;
1276+ Colormap mColormap;
1277+ nux::WindowThread *mWindowThread;
1278+ nux::View *mRootView;
1279+ unity::ScreenEffectFramebufferObject::Ptr mFbo;
1280+ GLXWindow mGlxWindow;
1281+ GLXContext mContext;
1282+ ModifierApplication mRotating;
1283+ ModifierApplication mBlur;
1284+ unsigned int mWidth;
1285+ unsigned int mHeight;
1286+ bool mNuxReady;
1287+ Shape::Ptr mTriangle;
1288+ Shape::Ptr mSquare;
1289+};
1290+
1291+BaseContext::BaseContext (Display *display) :
1292+ mDisplay (display),
1293+ mWindowThread (NULL),
1294+ mRotating (ModifierApplication::Both),
1295+ mBlur (ModifierApplication::Both),
1296+ mWidth (640),
1297+ mHeight (480),
1298+ mNuxReady (false),
1299+ mTriangle (new Triangle ()),
1300+ mSquare (new Square ())
1301+{
1302+ int numFBConfig = 0;
1303+ GLXFBConfig *fbConfigs = (*GLFuncs::glXChooseFBConfigP) (mDisplay,
1304+ DefaultScreen (mDisplay),
1305+ attributes,
1306+ &numFBConfig);
1307+ XVisualInfo *visinfo = (*GLFuncs::glXGetVisualFromFBConfigP) (mDisplay,
1308+ fbConfigs[0]);
1309+
1310+ mContext = glXCreateContext (mDisplay, visinfo, 0, GL_TRUE);
1311+ mColormap = XCreateColormap (mDisplay,
1312+ DefaultRootWindow (mDisplay),
1313+ visinfo->visual,
1314+ AllocNone);
1315+
1316+ XSetWindowAttributes wa;
1317+
1318+ wa.colormap = mColormap;
1319+ wa.border_pixel = 0;
1320+ wa.event_mask = StructureNotifyMask | KeyPressMask | ExposureMask;
1321+
1322+ mWindow = XCreateWindow (mDisplay, DefaultRootWindow (mDisplay),
1323+ 0, 0, mWidth, mHeight, 0, visinfo->depth, InputOutput,
1324+ visinfo->visual, CWColormap | CWEventMask | CWBorderPixel,
1325+ &wa);
1326+
1327+ mGlxWindow = (*GLFuncs::glXCreateWindowP) (mDisplay, fbConfigs[0], mWindow, NULL);
1328+
1329+ XStoreName (mDisplay, mWindow, "F1: Toggle Effect, F2: Rotation, F3: Effect");
1330+ XMapWindow (mDisplay, mWindow);
1331+
1332+ bool ready = false;
1333+
1334+ do
1335+ {
1336+ XEvent ev;
1337+ XNextEvent (mDisplay, &ev);
1338+ switch (ev.type)
1339+ {
1340+ case MapNotify:
1341+ case ConfigureNotify:
1342+ case Expose:
1343+ ready = true;
1344+ break;
1345+ default:
1346+ break;
1347+ }
1348+
1349+ } while (!ready);
1350+
1351+ (*GLFuncs::glXMakeContextCurrentP) (mDisplay, mGlxWindow, mGlxWindow, mContext);
1352+
1353+ setupContextForSize (mWidth, mHeight);
1354+}
1355+
1356+void
1357+BaseContext::run ()
1358+{
1359+ GIOChannel *channel;
1360+ mWindowThread = nux::CreateFromForeignWindow (mWindow,
1361+ mContext,
1362+ &BaseContext::onWindowThreadCreation,
1363+ (void *) this);
1364+
1365+ mWindowThread->Run(NULL);
1366+
1367+ while (!mNuxReady);
1368+ g_timeout_add (128, &BaseContext::onPaintTimeout, (gpointer) this);
1369+
1370+ channel = g_io_channel_unix_new (ConnectionNumber (mDisplay));
1371+
1372+ g_io_add_watch (channel, (GIOCondition) (G_IO_IN | G_IO_HUP | G_IO_ERR),
1373+ &BaseContext::onNewEvents, (gpointer) this);
1374+ gtk_main ();
1375+}
1376+
1377+BaseContext::~BaseContext ()
1378+{
1379+ delete mWindowThread;
1380+
1381+ (*GLFuncs::glXMakeContextCurrentP) (mDisplay, None, None, mContext);
1382+ glXDestroyContext (mDisplay, mContext);
1383+ (*GLFuncs::glXDestroyWindowP) (mDisplay, mGlxWindow);
1384+
1385+ XFreeColormap (mDisplay, mColormap);
1386+ XDestroyWindow (mDisplay, mWindow);
1387+}
1388+
1389+void
1390+BaseContext::setupContextForSize (unsigned int width,
1391+ unsigned int height)
1392+{
1393+ mWidth = width;
1394+ mHeight = height;
1395+
1396+ glViewport(0, 0, width, height);
1397+ glDrawBuffer (GL_BACK);
1398+ glReadBuffer (GL_BACK);
1399+ glMatrixMode(GL_PROJECTION);
1400+ glLoadIdentity();
1401+ gluPerspective(60.0f, 1.0f, 0.1f, 100.0f);
1402+ glMatrixMode(GL_MODELVIEW);
1403+ glLoadIdentity ();
1404+ glClearColor (1, 1, 1, 1);
1405+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1406+ glXSwapBuffers (mDisplay, mGlxWindow);
1407+
1408+ if (mFbo)
1409+ mFbo.reset (new unity::ScreenEffectFramebufferObject (GLFuncs::glXGetProcAddressP, nux::Geometry (0, 0, mWidth, mHeight)));
1410+
1411+ if (mRootView && mNuxReady)
1412+ {
1413+ switch (mBlur)
1414+ {
1415+ case ModifierApplication::Both:
1416+ mRootView->SetGeometry (nux::Geometry (0, 0, mWidth / 2, mHeight));
1417+ break;
1418+ case ModifierApplication::Triangle:
1419+ mRootView->SetGeometry (nux::Geometry (mWidth / 2, 0, mWidth / 2, mHeight));
1420+ break;
1421+ case ModifierApplication::Square:
1422+ mRootView->SetGeometry (nux::Geometry (0, 0, mWidth, mHeight));
1423+ break;
1424+ default:
1425+ break;
1426+ }
1427+ }
1428+}
1429+
1430+bool
1431+BaseContext::eventHandler ()
1432+{
1433+ XEvent event;
1434+ XEvent *ev = &event;
1435+
1436+ XNextEvent (mDisplay, &event);
1437+
1438+ switch (ev->type)
1439+ {
1440+ case KeyPress:
1441+ if (XLookupKeysym (&ev->xkey, 0) == XK_Escape)
1442+ return false;
1443+ else if (XLookupKeysym (&ev->xkey, 0) == XK_F1)
1444+ {
1445+ if (!mFbo)
1446+ {
1447+ BackgroundEffectHelper::blur_type = unity::BLUR_ACTIVE;
1448+ mFbo.reset (new unity::ScreenEffectFramebufferObject (GLFuncs::glXGetProcAddressP, nux::Geometry (0, 0, mWidth, mHeight)));
1449+ }
1450+ else
1451+ {
1452+ BackgroundEffectHelper::blur_type = unity::BLUR_NONE;
1453+ mFbo.reset ();
1454+ }
1455+ }
1456+ else if (XLookupKeysym (&ev->xkey, 0) == XK_F2)
1457+ nextShapeRotation ();
1458+ else if (XLookupKeysym (&ev->xkey, 0) == XK_F3)
1459+ nextWindowPosition ();
1460+ break;
1461+ case ConfigureNotify:
1462+ setupContextForSize (ev->xconfigure.width, ev->xconfigure.height);
1463+ default:
1464+ break;
1465+ }
1466+
1467+ return true;
1468+}
1469+
1470+gboolean
1471+BaseContext::onNewEvents (GIOChannel *channel,
1472+ GIOCondition condition,
1473+ gpointer data)
1474+{
1475+ BaseContext *self = static_cast <BaseContext *> (data);
1476+ gboolean keep_going = TRUE;
1477+
1478+ if (condition & G_IO_IN)
1479+ {
1480+ if (self->eventHandler ())
1481+ return TRUE;
1482+ else
1483+ return FALSE;
1484+ }
1485+
1486+ return TRUE;
1487+}
1488+
1489+gboolean
1490+BaseContext::onPaintTimeout (gpointer data)
1491+{
1492+ BaseContext *self = static_cast <BaseContext *> (data);
1493+
1494+ if (self->paintDispatch ())
1495+ return TRUE;
1496+
1497+ return FALSE;
1498+}
1499+
1500+void
1501+BaseContext::nextShapeRotation ()
1502+{
1503+ switch (mRotating)
1504+ {
1505+ case ModifierApplication::Both:
1506+ mRotating = ModifierApplication::Triangle;
1507+ break;
1508+ case ModifierApplication::Triangle:
1509+ mRotating = ModifierApplication::Square;
1510+ break;
1511+ case ModifierApplication::Square:
1512+ mRotating = ModifierApplication::Both;
1513+ break;
1514+ default:
1515+ break;
1516+ }
1517+}
1518+
1519+void
1520+BaseContext::nextWindowPosition ()
1521+{
1522+ switch (mBlur)
1523+ {
1524+ case ModifierApplication::Both:
1525+ mBlur = ModifierApplication::Triangle;
1526+ mRootView->SetGeometry (nux::Geometry (0, 0, mWidth / 2, mHeight));
1527+ break;
1528+ case ModifierApplication::Triangle:
1529+ mBlur = ModifierApplication::Square;
1530+ mRootView->SetGeometry (nux::Geometry (mWidth / 2, 0, mWidth / 2, mHeight));
1531+ break;
1532+ case ModifierApplication::Square:
1533+ mBlur = ModifierApplication::Both;
1534+ mRootView->SetGeometry (nux::Geometry (0, 0, mWidth, mHeight));
1535+ break;
1536+ default:
1537+ break;
1538+ }
1539+}
1540+
1541+EffectView::EffectView (NUX_FILE_LINE_DECL)
1542+ : View (NUX_FILE_LINE_PARAM)
1543+{
1544+ bg_effect_helper_.owner = this;
1545+}
1546+
1547+EffectView::~EffectView ()
1548+{
1549+}
1550+
1551+void EffectView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
1552+{
1553+ nux::Geometry base = GetGeometry();
1554+ GfxContext.PushClippingRectangle(base);
1555+ nux::Geometry blur_geo (base.x, base.y, base.width, base.height);
1556+
1557+ if (BackgroundEffectHelper::blur_type == unity::BLUR_ACTIVE)
1558+ {
1559+ bg_effect_helper_.enabled = true;
1560+
1561+ auto blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo);
1562+
1563+ if (blur_texture.IsValid ())
1564+ {
1565+ nux::TexCoordXForm texxform_blur_bg;
1566+ texxform_blur_bg.flip_v_coord = true;
1567+ texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
1568+ texxform_blur_bg.uoffset = ((float) base.x) / (base.width);
1569+ texxform_blur_bg.voffset = ((float) base.y) / (base.height);
1570+
1571+ nux::ROPConfig rop;
1572+ rop.Blend = false;
1573+ rop.SrcBlend = GL_ONE;
1574+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
1575+
1576+ gPainter.PushDrawTextureLayer(GfxContext, base,
1577+ blur_texture,
1578+ texxform_blur_bg,
1579+ nux::color::White,
1580+ true,
1581+ rop);
1582+ }
1583+ }
1584+ else
1585+ bg_effect_helper_.enabled = false;
1586+ GfxContext.PopClippingRectangle();
1587+}
1588+
1589+bool
1590+BaseContext::paintDispatch ()
1591+{
1592+ if (mFbo)
1593+ {
1594+ switch (mRotating)
1595+ {
1596+ case ModifierApplication::Both:
1597+ BackgroundEffectHelper::ProcessDamage (nux::Geometry (0, 0, mWidth, mHeight));
1598+ break;
1599+ case ModifierApplication::Triangle:
1600+ BackgroundEffectHelper::ProcessDamage (nux::Geometry (0, 0, mWidth / 2, mHeight));
1601+ break;
1602+ case ModifierApplication::Square:
1603+ BackgroundEffectHelper::ProcessDamage (nux::Geometry (mWidth / 2, 0, mWidth / 2, mHeight));
1604+ break;
1605+ }
1606+
1607+ mFbo->bind (nux::Geometry (0, 0, mWidth, mHeight));
1608+
1609+ if (!mFbo->status ())
1610+ LOG_INFO (logger) << "FBO not ok!";
1611+ }
1612+
1613+ glClearColor (1, 1, 1, 1);
1614+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1615+ glPushMatrix ();
1616+ glLoadIdentity();
1617+ glTranslatef(-0.5f, -0.5f, -0.866025404f);
1618+ glScalef (1.0f / mWidth, 1.0f / mHeight, 0.0f);
1619+ glTranslatef(mWidth * 0.25, 0, 0);
1620+ glRotatef(mTriangle->rotation (), 0.0f, 1.0f, 0.0f);
1621+ glTranslatef(-(mWidth * 0.25), 0, 0);
1622+
1623+ mTriangle->draw (mWidth, mHeight);
1624+
1625+ glLoadIdentity();
1626+ glTranslatef(-0.5f, -0.5f, -0.866025404f);
1627+ glScalef (1.0f / mWidth, 1.0f / mHeight, 0.0f);
1628+ glTranslatef(mWidth * 0.75, 0, 0);
1629+ glRotatef(mSquare->rotation (), 0.0f, 1.0f, 0.0f);
1630+ glTranslatef(-(mWidth * 0.75), 0, 0);
1631+
1632+ mSquare->draw (mWidth, mHeight);
1633+
1634+ glColor4f (1.0f, 1.0f, 1.0f, 5.0f);
1635+ glPopMatrix ();
1636+
1637+ if (mFbo)
1638+ mFbo->unbind ();
1639+
1640+ if (mFbo && mFbo->status ())
1641+ {
1642+ glClearColor (1, 1, 1, 1);
1643+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1644+ glPushMatrix ();
1645+ glLoadIdentity();
1646+ glTranslatef(-0.5f, 0.5f, -0.866025404f);
1647+ glScalef (1.0f / mWidth, -(1.0f / mHeight), 0.0f);
1648+ mFbo->paint (nux::Geometry (0, 0, mWidth, mHeight));
1649+ glPopMatrix ();
1650+
1651+ nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
1652+ nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID (mFbo->texture(),
1653+ mWidth, mHeight, 1, nux::BITFMT_R8G8B8A8);
1654+
1655+ nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
1656+
1657+ nux::Geometry geo = nux::Geometry (0, 0, mWidth, mHeight);
1658+ BackgroundEffectHelper::monitor_rect_ = geo;
1659+ }
1660+
1661+ glMatrixMode(GL_PROJECTION);
1662+ glPushMatrix();
1663+
1664+ glMatrixMode(GL_MODELVIEW);
1665+ glPushMatrix();
1666+ glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT |
1667+ GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
1668+ mRootView->ProcessDraw (mWindowThread->GetGraphicsEngine (), true);
1669+ glMatrixMode(GL_PROJECTION);
1670+ glPopMatrix();
1671+ glMatrixMode(GL_MODELVIEW);
1672+ glPopMatrix();
1673+
1674+ glDrawBuffer(GL_BACK);
1675+ glReadBuffer(GL_BACK);
1676+
1677+ glPopAttrib();
1678+
1679+ glXSwapBuffers (mDisplay, mGlxWindow);
1680+
1681+ switch (mRotating)
1682+ {
1683+ case ModifierApplication::Both:
1684+ mTriangle->rotate ();
1685+ mSquare->rotate ();
1686+ break;
1687+ case ModifierApplication::Triangle:
1688+ mTriangle->rotate ();
1689+ break;
1690+ case ModifierApplication::Square:
1691+ mSquare->rotate ();
1692+ break;
1693+ }
1694+
1695+ return true;
1696+}
1697+
1698+void
1699+BaseContext::onWindowThreadCreation (nux::NThread *thread, void *data)
1700+{
1701+ BaseContext *bc = static_cast <BaseContext *> (data);
1702+
1703+ bc->mRootView = new EffectView ();
1704+ bc->mRootView->SetGeometry (nux::Geometry (0, 0, 640, 480));
1705+ bc->mNuxReady = true;
1706+ BackgroundEffectHelper::blur_type = unity::BLUR_ACTIVE;
1707+}
1708+
1709+int main (int argc, char **argv)
1710+{
1711+ Display *display = XOpenDisplay (NULL);
1712+ nux::NuxInitialize (0);
1713+ GLFuncs::init ();
1714+ g_type_init ();
1715+ g_thread_init (NULL);
1716+ gtk_init(&argc, &argv);
1717+
1718+ BaseContext *bc = new BaseContext (display);
1719+
1720+ bc->run ();
1721+
1722+ delete bc;
1723+
1724+ XCloseDisplay (display);
1725+
1726+ return 0;
1727+}
1728+
1729+