Merge lp:~smspillaz/unity/unity.oem-fixes into lp:unity/4.0

Proposed by David Barth on 2012-01-04
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve on 2012-01-05
Robert Carr 2012-01-04 Approve on 2012-01-04
Review via email: mp+87493@code.launchpad.net

Description of the Change

Fix for bug #838128, which is on the OEM priority list.

To post a comment you must log in.
Robert Carr (robertcarr) wrote :

+1. Though, I'm wondering if it should always be GL_LINEAR? Didn't we have a setting for that?

review: Approve
Sam Spilsbury (smspillaz) wrote :

It doesn't make sense to do texture filtering on the framebuffer object since its always painted on-screen at the same position and same size.

Jason Smith (jassmith) wrote :

style fixes:
- please make sure to use brackets around all loops (for loops especially)

GL changes:
There is no reason to disable the scissor bit if you are going to pop the attrib right afterwards. Small change though I remember we ran into another weird state issue not long ago. I can't remember what exactly it was but it was something similar to this (multiple changes to the same bit in a row for no reason)

Please check the result of glGetError

review: Approve
Sam Spilsbury (smspillaz) wrote :

done

lp:~smspillaz/unity/unity.oem-fixes updated on 2012-01-05
1728. By Sam Spilsbury on 2012-01-05

Don't disable the scissor test explicitly

1729. By Sam Spilsbury on 2012-01-05

Minor style fix - use for loop

1730. By Sam Spilsbury on 2012-01-05

Check glGetError ()

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

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

Subscribers

People subscribed via source and target branches

to all changes: