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

Proposed by David Barth
Status: Merged
Approved by: David Barth
Approved revision: no longer in the source branch.
Merged at revision: 1726
Proposed branch: lp:~smspillaz/unity/unity.oem-fixes
Merge into: lp:unity/4.0
Diff against target: 1711 lines (+1184/-294)
12 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 (+84/-0)
plugins/unityshell/src/comptransientfor.cpp (+2/-0)
plugins/unityshell/src/unityshell.cpp (+73/-256)
plugins/unityshell/src/unityshell.h (+7/-35)
tests/CMakeLists.txt (+14/-0)
tests/GLFuncLoader.cpp (+51/-0)
tests/GLFuncLoader.h (+33/-0)
tests/TestScreenEffectFramebufferObject.cpp (+671/-0)
To merge this branch: bzr merge lp:~smspillaz/unity/unity.oem-fixes
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve
Robert Carr (community) Approve
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.
Revision history for this message
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
Revision history for this message
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.

Revision history for this message
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
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

done

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
=== modified file 'plugins/unityshell/src/BackgroundEffectHelper.cpp'
--- plugins/unityshell/src/BackgroundEffectHelper.cpp 2011-09-28 05:19:39 +0000
+++ plugins/unityshell/src/BackgroundEffectHelper.cpp 2012-01-05 02:50:46 +0000
@@ -85,7 +85,20 @@
85bool BackgroundEffectHelper::HasEnabledHelpers()85bool BackgroundEffectHelper::HasEnabledHelpers()
86{86{
87 for (BackgroundEffectHelper * bg_effect_helper : registered_list_)87 for (BackgroundEffectHelper * bg_effect_helper : registered_list_)
88 {
88 if (bg_effect_helper->enabled)89 if (bg_effect_helper->enabled)
90 {
91 return true;
92 }
93 }
94
95 return false;
96}
97
98bool BackgroundEffectHelper::HasDirtyHelpers()
99{
100 for (BackgroundEffectHelper * bg_effect_helper : registered_list_)
101 if (bg_effect_helper->enabled && bg_effect_helper->cache_dirty)
89 return true;102 return true;
90103
91 return false;104 return false;
92105
=== modified file 'plugins/unityshell/src/BackgroundEffectHelper.h'
--- plugins/unityshell/src/BackgroundEffectHelper.h 2011-09-21 02:52:26 +0000
+++ plugins/unityshell/src/BackgroundEffectHelper.h 2012-01-05 02:50:46 +0000
@@ -54,7 +54,7 @@
54 void DirtyCache();54 void DirtyCache();
5555
56 static void ProcessDamage(nux::Geometry geo);56 static void ProcessDamage(nux::Geometry geo);
5757 static bool HasDirtyHelpers();
58 static bool HasEnabledHelpers();58 static bool HasEnabledHelpers();
5959
60 static nux::Property<unity::BlurType> blur_type;60 static nux::Property<unity::BlurType> blur_type;
6161
=== modified file 'plugins/unityshell/src/PanelView.cpp'
--- plugins/unityshell/src/PanelView.cpp 2011-10-13 16:56:43 +0000
+++ plugins/unityshell/src/PanelView.cpp 2012-01-05 02:50:46 +0000
@@ -604,8 +604,7 @@
604604
605 _opacity = opacity;605 _opacity = opacity;
606606
607 if (_opacity < 1.0f && !_dash_is_open)607 bg_effect_helper_.enabled = (_opacity < 1.0f || _dash_is_open);
608 bg_effect_helper_.enabled = false;
609608
610 ForceUpdateBackground();609 ForceUpdateBackground();
611}610}
612611
=== added file 'plugins/unityshell/src/ScreenEffectFramebufferObject.cpp'
--- plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 1970-01-01 00:00:00 +0000
+++ plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-01-05 02:50:46 +0000
@@ -0,0 +1,234 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/* Compiz unity plugin
3 * unity.h
4 *
5 * Copyright (c) 2010-11 Canonical Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#include "ScreenEffectFramebufferObject.h"
21#include "BackgroundEffectHelper.h"
22#include <NuxCore/Logger.h>
23#include <dlfcn.h>
24
25namespace
26{
27 nux::logging::Logger logger ("unity.screeneffectframebufferobject");
28}
29
30void ScreenEffectFramebufferObject::paint (const nux::Geometry &output)
31{
32 /* Draw the bit of the relevant framebuffer for each output */
33
34 glPushAttrib (GL_VIEWPORT_BIT);
35 glViewport (0, mScreenSize.height - (output.y + output.height), mScreenSize.width, mScreenSize.height);
36
37 if (mFBTexture)
38 {
39 glEnable (GL_TEXTURE_2D);
40 activeTexture (GL_TEXTURE0_ARB);
41 glBindTexture (GL_TEXTURE_2D, mFBTexture);
42 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
43 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
44
45 glPushAttrib (GL_SCISSOR_BIT);
46 glEnable (GL_SCISSOR_TEST);
47
48 glScissor (output.x, mScreenSize.height - (output.y + output.height),
49 output.width, output.height);
50
51 /* FIXME: This needs to be GL_TRIANGLE_STRIP */
52 glBegin (GL_QUADS);
53 glTexCoord2f (0, 1);
54 glVertex2i (mGeometry.x, mGeometry.y);
55 glTexCoord2f (0, 0);
56 glVertex2i (mGeometry.x, mGeometry.y + mGeometry.height);
57 glTexCoord2f (1, 0);
58 glVertex2i (mGeometry.x + mGeometry.width, mGeometry.y + mGeometry.height);
59 glTexCoord2f (1, 1);
60 glVertex2i (mGeometry.x + mGeometry.width, mGeometry.y);
61 glEnd ();
62
63 activeTexture (GL_TEXTURE0_ARB);
64 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
65 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
66 glBindTexture (GL_TEXTURE_2D, 0);
67 glDisable (GL_TEXTURE_2D);
68 glPopAttrib ();
69 }
70 glPopAttrib ();
71}
72
73void ScreenEffectFramebufferObject::onScreenSizeChanged(const nux::Geometry& screenSize)
74{
75 mScreenSize = screenSize;
76}
77
78
79void ScreenEffectFramebufferObject::unbind ()
80{
81 if (!mBoundCnt)
82 return;
83
84 mBoundCnt--;
85
86 (*bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
87
88 glDrawBuffer (GL_BACK);
89 glReadBuffer (GL_BACK);
90
91 /* Matches the viewport set we did in ::bind () */
92 glPopAttrib ();
93
94}
95
96bool ScreenEffectFramebufferObject::status ()
97{
98 return mFboStatus;
99}
100
101void ScreenEffectFramebufferObject::bind (const nux::Geometry &output)
102{
103 if (!BackgroundEffectHelper::HasDirtyHelpers())
104 return;
105
106 /* Clear the error bit */
107 glGetError ();
108
109 if (!mFBTexture)
110 {
111 glGenTextures (1, &mFBTexture);
112
113 glBindTexture (GL_TEXTURE_2D, mFBTexture);
114 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
115 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
116 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
117 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
118 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, mGeometry.width, mGeometry.height, 0, GL_BGRA,
119#if IMAGE_BYTE_ORDER == MSBFirst
120 GL_UNSIGNED_INT_8_8_8_8_REV,
121#else
122 GL_UNSIGNED_BYTE,
123#endif
124 NULL);
125
126 glBindTexture (GL_TEXTURE_2D, 0);
127
128 if (glGetError () != GL_NO_ERROR)
129 {
130 mFboHandle = 0;
131 mFboStatus = false;
132 return;
133 }
134 }
135
136 (*bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
137
138 (*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
139 GL_TEXTURE_2D, mFBTexture, 0);
140
141 (*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
142 GL_TEXTURE_2D, 0, 0);
143
144 /* Ensure that a framebuffer is actually available */
145 if (!mFboStatus)
146 {
147 GLint status = (*checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
148
149 if (status != GL_FRAMEBUFFER_COMPLETE)
150 {
151 switch (status)
152 {
153 case GL_FRAMEBUFFER_UNDEFINED:
154 LOG_WARN (logger) << "no window";
155 break;
156 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
157 LOG_WARN (logger) << "attachment incomplete";
158 break;
159 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
160 LOG_WARN (logger) << "no buffers attached to fbo";
161 break;
162 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
163 LOG_WARN (logger) << "some attachment in glDrawBuffers doesn't exist in FBO";
164 break;
165 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
166 LOG_WARN (logger) << "some attachment in glReadBuffers doesn't exist in FBO";
167 break;
168 case GL_FRAMEBUFFER_UNSUPPORTED:
169 LOG_WARN (logger) << "unsupported internal format";
170 break;
171 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
172 LOG_WARN (logger) << "different levels of sampling for each attachment";
173 break;
174 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
175 LOG_WARN (logger) << "number of layers is different";
176 break;
177 default:
178 LOG_WARN (logger) << "unable to bind the framebuffer for an unknown reason";
179 break;
180 }
181
182 bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
183 deleteFramebuffers (1, &mFboHandle);
184
185 glDrawBuffer (GL_BACK);
186 glReadBuffer (GL_BACK);
187
188 mFboHandle = 0;
189
190 mFboStatus = false;
191 }
192 else
193 mFboStatus = true;
194 }
195
196 if (mFboStatus)
197 {
198 glPushAttrib (GL_VIEWPORT_BIT);
199
200 glViewport (output.x,
201 mScreenSize.height - (output.y + output.height),
202 output.width,
203 output.height);
204 }
205
206 mBoundCnt++;
207}
208
209
210ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom)
211 : getProcAddressGLX (p)
212 , mFboStatus (false)
213 , mFBTexture (0)
214 , mGeometry (geom)
215 , mBoundCnt (0)
216 , mScreenSize (geom)
217{
218 activeTexture = (GLActiveTextureProc) (*getProcAddressGLX) ((GLubyte *) "glActiveTexture");
219 genFramebuffers = (GLGenFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glGenFramebuffersEXT");
220 deleteFramebuffers = (GLDeleteFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glDeleteFramebuffersEXT");
221 bindFramebuffer = (GLBindFramebufferProc) (*getProcAddressGLX) ((GLubyte *)"glBindFramebufferEXT");
222 checkFramebufferStatus = (GLCheckFramebufferStatusProc) (*getProcAddressGLX) ((GLubyte *) "glCheckFramebufferStatusEXT");
223 framebufferTexture2D = (GLFramebufferTexture2DProc) (*getProcAddressGLX) ((GLubyte *) "glFramebufferTexture2DEXT");
224
225 (*genFramebuffers) (1, &mFboHandle);
226}
227
228ScreenEffectFramebufferObject::~ScreenEffectFramebufferObject ()
229{
230 (*deleteFramebuffers) (1, &mFboHandle);
231
232 if (mFBTexture)
233 glDeleteTextures (1, &mFBTexture);
234}
0235
=== added file 'plugins/unityshell/src/ScreenEffectFramebufferObject.h'
--- plugins/unityshell/src/ScreenEffectFramebufferObject.h 1970-01-01 00:00:00 +0000
+++ plugins/unityshell/src/ScreenEffectFramebufferObject.h 2012-01-05 02:50:46 +0000
@@ -0,0 +1,84 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/* Compiz unity plugin
3 * unity.h
4 *
5 * Copyright (c) 2010-11 Canonical Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#ifndef UNITY_SCREENEFFECT_FRAMEBUFFER_H
21#define UNITY_SCREENEFFECT_FRAMEBUFFER_H
22
23#include <Nux/Nux.h>
24
25class ScreenEffectFramebufferObject
26{
27public:
28
29 typedef boost::shared_ptr <ScreenEffectFramebufferObject> Ptr;
30 typedef void (*FuncPtr) (void);
31 typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
32
33 ScreenEffectFramebufferObject (GLXGetProcAddressProc, const nux::Geometry &geom);
34 ~ScreenEffectFramebufferObject ();
35
36public:
37
38 void bind (const nux::Geometry &geom);
39 void unbind ();
40
41 bool status ();
42 void paint (const nux::Geometry &geom);
43 bool bound () { return mBoundCnt > 0; }
44
45 GLuint texture () { return mFBTexture; }
46
47 void onScreenSizeChanged (const nux::Geometry &screenSize);
48
49private:
50
51 FuncPtr getProcAddr (const std::string &);
52
53 typedef void (*GLActiveTextureProc) (GLenum texture);
54 typedef void (*GLGenFramebuffersProc) (GLsizei n,
55 GLuint *framebuffers);
56 typedef void (*GLDeleteFramebuffersProc) (GLsizei n,
57 GLuint *framebuffers);
58 typedef void (*GLBindFramebufferProc) (GLenum target,
59 GLuint framebuffer);
60 typedef GLenum (*GLCheckFramebufferStatusProc) (GLenum target);
61 typedef void (*GLFramebufferTexture2DProc) (GLenum target,
62 GLenum attachment,
63 GLenum textarget,
64 GLuint texture,
65 GLint level);
66
67 GLXGetProcAddressProc getProcAddressGLX;
68 GLActiveTextureProc activeTexture;
69 GLGenFramebuffersProc genFramebuffers;
70 GLDeleteFramebuffersProc deleteFramebuffers;
71 GLBindFramebufferProc bindFramebuffer;
72 GLCheckFramebufferStatusProc checkFramebufferStatus;
73 GLFramebufferTexture2DProc framebufferTexture2D;
74 /* compiz fbo handle that goes through to nux */
75 GLuint mFboHandle; // actual handle to the framebuffer_ext
76 bool mFboStatus; // did the framebuffer texture bind succeed
77 GLuint mFBTexture;
78 nux::Geometry mGeometry;
79 unsigned int mBoundCnt;
80
81 nux::Geometry mScreenSize;
82};
83
84#endif
085
=== modified file 'plugins/unityshell/src/comptransientfor.cpp'
--- plugins/unityshell/src/comptransientfor.cpp 2011-12-15 15:14:48 +0000
+++ plugins/unityshell/src/comptransientfor.cpp 2012-01-05 02:50:46 +0000
@@ -57,6 +57,8 @@
57{57{
58 if (!ancestor ||58 if (!ancestor ||
59 !priv->mWindow->id ())59 !priv->mWindow->id ())
60 return false;
61
60 return priv->mWindow->transientFor () == ancestor;62 return priv->mWindow->transientFor () == ancestor;
61}63}
6264
6365
=== modified file 'plugins/unityshell/src/unityshell.cpp'
--- plugins/unityshell/src/unityshell.cpp 2011-12-15 16:05:39 +0000
+++ plugins/unityshell/src/unityshell.cpp 2012-01-05 02:50:46 +0000
@@ -111,8 +111,7 @@
111 , damaged(false)111 , damaged(false)
112 , _key_nav_mode_requested(false)112 , _key_nav_mode_requested(false)
113 , _last_output(nullptr)113 , _last_output(nullptr)
114 , switcher_desktop_icon(nullptr)114 , _active_fbo (0)
115 , mActiveFbo (0)
116 , dash_is_open_ (false)115 , dash_is_open_ (false)
117 , grab_index_ (0)116 , grab_index_ (0)
118 , painting_tray_ (false)117 , painting_tray_ (false)
@@ -225,12 +224,21 @@
225 _edge_timeout = optionGetLauncherRevealEdgeTimeout ();224 _edge_timeout = optionGetLauncherRevealEdgeTimeout ();
226 _in_paint = false;225 _in_paint = false;
227226
227 void *dlhand = dlopen ("libunityshell.so", RTLD_LAZY);
228
229 if (dlhand)
230 {
231 dlerror ();
232 glXGetProcAddressP = (ScreenEffectFramebufferObject::GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
233 if (dlerror () != NULL)
234 glXGetProcAddressP = NULL;
235 }
236
228 if (GL::fbo)237 if (GL::fbo)
229 {238 {
230 foreach (CompOutput & o, screen->outputDevs())239 nux::Geometry geometry (0, 0, screen->width (), screen->height ());
231 uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO(&o));240 uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
232241 uScreen->_fbo->onScreenSizeChanged (geometry);
233 uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO(&(screen->fullscreenOutput ())));
234 }242 }
235243
236 optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));244 optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
@@ -451,7 +459,7 @@
451459
452void UnityScreen::nuxEpilogue()460void UnityScreen::nuxEpilogue()
453{461{
454 (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, mActiveFbo);462 (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo);
455463
456 glMatrixMode(GL_PROJECTION);464 glMatrixMode(GL_PROJECTION);
457 glLoadIdentity();465 glLoadIdentity();
@@ -492,8 +500,6 @@
492 if (PluginAdapter::Default()->IsExpoActive())500 if (PluginAdapter::Default()->IsExpoActive())
493 return;501 return;
494502
495 nuxPrologue();
496
497 CompOutput* output = _last_output;503 CompOutput* output = _last_output;
498 float vc[4];504 float vc[4];
499 float h = 20.0f;505 float h = 20.0f;
@@ -504,6 +510,9 @@
504 float y1 = output->y() + panel_h;510 float y1 = output->y() + panel_h;
505 float x2 = x1 + output->width();511 float x2 = x1 + output->width();
506 float y2 = y1 + h;512 float y2 = y1 + h;
513 GLMatrix sTransform = GLMatrix ();
514
515 sTransform.toScreenSpace(output, -DEFAULT_Z_CAMERA);
507516
508 vc[0] = x1;517 vc[0] = x1;
509 vc[1] = x2;518 vc[1] = x2;
@@ -543,7 +552,6 @@
543 glDisable(GL_BLEND);552 glDisable(GL_BLEND);
544 }553 }
545 }554 }
546 nuxEpilogue();
547}555}
548556
549void557void
@@ -562,30 +570,35 @@
562{570{
563 CompOutput *output = _last_output;571 CompOutput *output = _last_output;
564 Window tray_xid = panelController->GetTrayXid ();572 Window tray_xid = panelController->GetTrayXid ();
565 bool bound = mFbos[output]->bound ();573
566574 bool was_bound = _fbo->bound ();
567575 _fbo->unbind ();
568 if (bound)576
577 /* Draw the bit of the relevant framebuffer for each output */
578
579 if (was_bound)
569 {580 {
570 mFbos[output]->unbind ();581 GLMatrix sTransform;
571582 sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
572 /* Draw the bit of the relevant framebuffer for each output */583 glPushMatrix ();
573 mFbos[output]->paint ();584 glLoadMatrixf (sTransform.getMatrix ());
585 _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
586 glPopMatrix ();
574 }587 }
575588
576 nuxPrologue();
577
578 nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =589 nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
579 nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(mFbos[output]->texture(),590 nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),
580 output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);591 screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
581592
582 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;593 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
583594
584 nux::Geometry geo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());595 nux::Geometry geo = nux::Geometry (0, 0, screen->width (), screen->height ());
596 nux::Geometry oGeo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
585 BackgroundEffectHelper::monitor_rect_ = geo;597 BackgroundEffectHelper::monitor_rect_ = geo;
586598
599 nuxPrologue();
587 _in_paint = true;600 _in_paint = true;
588 wt->RenderInterfaceFromForeignCmd (&geo);601 wt->RenderInterfaceFromForeignCmd (&oGeo);
589 _in_paint = false;602 _in_paint = false;
590 nuxEpilogue();603 nuxEpilogue();
591604
@@ -985,6 +998,10 @@
985{998{
986 bool ret;999 bool ret;
9871000
1001 doShellRepaint = true;
1002 allowWindowPaint = true;
1003 _last_output = output;
1004
988 /* bind the framebuffer here1005 /* bind the framebuffer here
989 * - it will be unbound and flushed1006 * - it will be unbound and flushed
990 * to the backbuffer when some1007 * to the backbuffer when some
@@ -995,11 +1012,7 @@
995 * attempts to bind it will only increment1012 * attempts to bind it will only increment
996 * its bind reference so make sure that1013 * its bind reference so make sure that
997 * you always unbind as much as you bind */1014 * you always unbind as much as you bind */
998 mFbos[output]->bind ();1015 _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
999
1000 doShellRepaint = true;
1001 allowWindowPaint = true;
1002 _last_output = output;
10031016
1004 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */1017 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
1005 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);1018 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
@@ -1154,16 +1167,37 @@
1154 {1167 {
1155 XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;1168 XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
1156 CompWindow* w = screen->findWindow (de->drawable);1169 CompWindow* w = screen->findWindow (de->drawable);
1170 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
1171 CompWindow* lastNWindow = screen->findWindow (xwns.back ());
1172 bool processDamage = true;
11571173
1158 if (w)1174 if (w)
1159 {1175 {
1160 nux::Geometry damage (de->area.x, de->area.y, de->area.width, de->area.height);1176 if (!w->overrideRedirect () &&
11611177 w->isViewable () &&
1162 CompWindow::Geometry geom = w->geometry ();1178 !w->invisible ())
1163 damage.x += geom.x () + geom.border ();1179 {
1164 damage.y += geom.y () + geom.border ();1180
11651181 for (; lastNWindow != NULL; lastNWindow = lastNWindow->next)
1166 BackgroundEffectHelper::ProcessDamage(damage);1182 {
1183 if (lastNWindow == w)
1184 {
1185 processDamage = false;
1186 break;
1187 }
1188 }
1189
1190 if (processDamage)
1191 {
1192 nux::Geometry damage (de->area.x, de->area.y, de->area.width, de->area.height);
1193
1194 const CompWindow::Geometry &geom = w->geometry ();
1195 damage.x += geom.x () + geom.border ();
1196 damage.y += geom.y () + geom.border ();
1197
1198 BackgroundEffectHelper::ProcessDamage(damage);
1199 }
1200 }
1167 }1201 }
1168 }1202 }
1169}1203}
@@ -2146,16 +2180,15 @@
2146 GdkRectangle rect;2180 GdkRectangle rect;
2147 nux::Geometry lCurGeom;2181 nux::Geometry lCurGeom;
2148 int panel_height = 24;2182 int panel_height = 24;
2183 nux::Geometry geometry (0, 0, screen->width (), screen->height ());
21492184
2150 if (!needsRelayout)2185 if (!needsRelayout)
2151 return;2186 return;
21522187
2153 if (GL::fbo)2188 if (GL::fbo)
2154 {2189 {
2155 foreach (CompOutput &o, screen->outputDevs ())2190 uScreen->_fbo.reset (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
2156 uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO (&o));2191 uScreen->_fbo->onScreenSizeChanged (geometry);
2157
2158 uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO (&(screen->fullscreenOutput ())));
2159 }2192 }
21602193
2161 UScreen *uscreen = UScreen::GetDefault();2194 UScreen *uscreen = UScreen::GetDefault();
@@ -2194,8 +2227,6 @@
2194{2227{
2195 UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);2228 UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);
21962229
2197 uScreen->mFbos.clear ();
2198
2199 uScr->NeedsRelayout ();2230 uScr->NeedsRelayout ();
2200 uScr->Relayout();2231 uScr->Relayout();
2201 uScr->relayoutSourceId = 0;2232 uScr->relayoutSourceId = 0;
@@ -2228,220 +2259,6 @@
2228 ScheduleRelayout(500);2259 ScheduleRelayout(500);
2229}2260}
22302261
2231void UnityFBO::paint ()
2232{
2233 //CompositeScreen *cScreen = CompositeScreen::get (screen);
2234 //unsigned int mask = cScreen->damageMask ();
2235 float texx, texy, texwidth, texheight;
2236
2237 /* Must be completely unbound before painting */
2238 if (mBoundCnt)
2239 return;
2240
2241 /* Draw the bit of the relevant framebuffer for each output */
2242 GLMatrix transform;
2243
2244 glViewport (output->x (), screen->height () - output->y2 (), output->width (), output->height ());
2245 GLScreen::get (screen)->clearOutput (output, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2246
2247 transform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
2248 glPushMatrix ();
2249 glLoadMatrixf (transform.getMatrix ());
2250
2251 /* Note that texcoords here are normalized, so it's just (0,0)-(1,1) */
2252 texx = 0.0;
2253 texy = 0.0;
2254 texwidth = 1.0f;
2255 texheight = 1.0f;
2256
2257 if (mFBTexture)
2258 {
2259 glEnable (GL_TEXTURE_2D);
2260 GL::activeTexture (GL_TEXTURE0_ARB);
2261 glBindTexture (GL_TEXTURE_2D, mFBTexture);
2262 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2263 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2264
2265 glPushAttrib (GL_SCISSOR_BIT);
2266 glEnable (GL_SCISSOR_TEST);
2267
2268 glScissor (output->x1 (), screen->height () - output->y2 (),
2269 output->width (), output->height ());
2270
2271 /* FIXME: This needs to be GL_TRIANGLE_STRIP */
2272 glBegin (GL_QUADS);
2273 glTexCoord2f (texx, texy + texheight);
2274 glVertex2i (output->x1 (), output->y1 ());
2275 glTexCoord2f (texx, texy);
2276 glVertex2i (output->x1 (), output->y2 ());
2277 glTexCoord2f (texx + texwidth, texy);
2278 glVertex2i (output->x2 (), output->y2 ());
2279 glTexCoord2f (texx + texwidth, texy + texheight);
2280 glVertex2i (output->x2 (), output->y1 ());
2281 glEnd ();
2282
2283 GL::activeTexture (GL_TEXTURE0_ARB);
2284 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2285 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2286 glBindTexture (GL_TEXTURE_2D, 0);
2287 glEnable (GL_TEXTURE_2D);
2288
2289 glDisable (GL_SCISSOR_TEST);
2290 glPopAttrib ();
2291 }
2292
2293 glPopMatrix();
2294}
2295
2296void UnityFBO::unbind ()
2297{
2298 mBoundCnt--;
2299
2300 if (mBoundCnt)
2301 return;
2302
2303 uScreen->setActiveFbo (0);
2304 (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
2305
2306 glDrawBuffer (GL_BACK);
2307 glReadBuffer (GL_BACK);
2308
2309}
2310
2311bool UnityFBO::bound ()
2312{
2313 return mBoundCnt > 0;
2314}
2315
2316bool UnityFBO::status ()
2317{
2318 return mFboStatus;
2319}
2320
2321void UnityFBO::bind ()
2322{
2323 if (mBoundCnt)
2324 {
2325 mBoundCnt++;
2326 return;
2327 }
2328
2329 if (!mFBTexture)
2330 {
2331 glGenTextures (1, &mFBTexture);
2332
2333 glBindTexture (GL_TEXTURE_2D, mFBTexture);
2334 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2335 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2336 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2337 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2338 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, output->width(), output->height(), 0, GL_BGRA,
2339#if IMAGE_BYTE_ORDER == MSBFirst
2340 GL_UNSIGNED_INT_8_8_8_8_REV,
2341#else
2342 GL_UNSIGNED_BYTE,
2343#endif
2344 NULL);
2345
2346 glBindTexture (GL_TEXTURE_2D, 0);
2347 }
2348
2349 glGetError ();
2350
2351 (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
2352
2353 (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
2354 GL_TEXTURE_2D, mFBTexture, 0);
2355
2356 (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
2357 GL_TEXTURE_2D, 0, 0);
2358
2359 /* Ensure that a framebuffer is actually available */
2360 if (!mFboStatus)
2361 {
2362 GLint status = (*GL::checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
2363
2364 if (status != GL_FRAMEBUFFER_COMPLETE)
2365 {
2366 switch (status)
2367 {
2368 case GL_FRAMEBUFFER_UNDEFINED:
2369 compLogMessage ("unity", CompLogLevelWarn, "no window");
2370 break;
2371 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
2372 compLogMessage ("unity", CompLogLevelWarn, "attachment incomplete");
2373 break;
2374 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
2375 compLogMessage ("unity", CompLogLevelWarn, "no buffers attached to fbo");
2376 break;
2377 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
2378 compLogMessage ("unity", CompLogLevelWarn, "some attachment in glDrawBuffers doesn't exist in FBO");
2379 break;
2380 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
2381 compLogMessage ("unity", CompLogLevelWarn, "some attachment in glReadBuffers doesn't exist in FBO");
2382 break;
2383 case GL_FRAMEBUFFER_UNSUPPORTED:
2384 compLogMessage ("unity", CompLogLevelWarn, "unsupported internal format");
2385 break;
2386 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
2387 compLogMessage ("unity", CompLogLevelWarn, "different levels of sampling for each attachment");
2388 break;
2389 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
2390 compLogMessage ("unity", CompLogLevelWarn, "number of layers is different");
2391 break;
2392 default:
2393 compLogMessage ("unity", CompLogLevelWarn, "unable to bind the framebuffer for an unknown reason");
2394 break;
2395 }
2396
2397 GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
2398 GL::deleteFramebuffers (1, &mFboHandle);
2399
2400 glDrawBuffer (GL_BACK);
2401 glReadBuffer (GL_BACK);
2402
2403 mFboHandle = 0;
2404
2405 mFboStatus = false;
2406 uScreen->setActiveFbo (0);
2407 }
2408 else
2409 mFboStatus = true;
2410 }
2411
2412 if (mFboStatus)
2413 {
2414 uScreen->setActiveFbo (mFboHandle);
2415
2416 glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
2417 glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
2418
2419 glViewport (0,
2420 0,
2421 output->width(),
2422 output->height());
2423
2424 mBoundCnt++;
2425 }
2426}
2427
2428UnityFBO::UnityFBO (CompOutput *o)
2429 : mFboStatus (false)
2430 , mFBTexture (0)
2431 , output (o)
2432 , mBoundCnt (0)
2433{
2434 (*GL::genFramebuffers) (1, &mFboHandle);
2435}
2436
2437UnityFBO::~UnityFBO ()
2438{
2439 (*GL::deleteFramebuffers) (1, &mFboHandle);
2440
2441 if (mFBTexture)
2442 glDeleteTextures (1, &mFBTexture);
2443}
2444
2445void UnityScreen::OnDashRealized ()2262void UnityScreen::OnDashRealized ()
2446{2263{
2447 /* stack any windows named "onboard" above us */2264 /* stack any windows named "onboard" above us */
24482265
=== modified file 'plugins/unityshell/src/unityshell.h'
--- plugins/unityshell/src/unityshell.h 2011-12-15 15:17:39 +0000
+++ plugins/unityshell/src/unityshell.h 2012-01-05 02:50:46 +0000
@@ -45,42 +45,14 @@
45#include <Nux/WindowThread.h>45#include <Nux/WindowThread.h>
46#include <sigc++/sigc++.h>46#include <sigc++/sigc++.h>
47#include <boost/shared_ptr.hpp>47#include <boost/shared_ptr.hpp>
48#include "ScreenEffectFramebufferObject.h"
4849
49#include "compizminimizedwindowhandler.h"50#include "compizminimizedwindowhandler.h"
5051#include <dlfcn.h>
51class UnityFBO
52{
53public:
54
55 typedef boost::shared_ptr <UnityFBO> Ptr;
56
57 UnityFBO (CompOutput *o);
58 ~UnityFBO ();
59
60public:
61
62 void bind ();
63 void unbind ();
64
65 bool status ();
66 bool bound ();
67 void paint ();
68
69 GLuint texture () { return mFBTexture; }
70
71private:
72
73 /* compiz fbo handle that goes through to nux */
74 GLuint mFboHandle; // actual handle to the framebuffer_ext
75 bool mFboStatus; // did the framebuffer texture bind succeed
76 GLuint mFBTexture;
77 CompOutput *output;
78 unsigned int mBoundCnt;
79};
8052
81class UnityShowdesktopHandler53class UnityShowdesktopHandler
82{54{
83public:55 public:
8456
85 UnityShowdesktopHandler (CompWindow *w);57 UnityShowdesktopHandler (CompWindow *w);
86 ~UnityShowdesktopHandler ();58 ~UnityShowdesktopHandler ();
@@ -240,8 +212,6 @@
240 void NeedsRelayout();212 void NeedsRelayout();
241 void ScheduleRelayout(guint timeout);213 void ScheduleRelayout(guint timeout);
242214
243 void setActiveFbo (GLuint fbo) { mActiveFbo = fbo; }
244
245 bool forcePaintOnTop ();215 bool forcePaintOnTop ();
246216
247protected:217protected:
@@ -329,8 +299,8 @@
329299
330 unity::BGHash _bghash;300 unity::BGHash _bghash;
331301
332 std::map <CompOutput *, UnityFBO::Ptr> mFbos;302 ScreenEffectFramebufferObject::Ptr _fbo;
333 GLuint mActiveFbo;303 GLuint _active_fbo;
334304
335 bool queryForShader ();305 bool queryForShader ();
336306
@@ -341,6 +311,8 @@
341 bool painting_tray_;311 bool painting_tray_;
342 unsigned int tray_paint_mask_;312 unsigned int tray_paint_mask_;
343313
314 ScreenEffectFramebufferObject::GLXGetProcAddressProc glXGetProcAddressP;
315
344 friend class UnityWindow;316 friend class UnityWindow;
345};317};
346318
347319
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2011-10-04 12:15:09 +0000
+++ tests/CMakeLists.txt 2012-01-05 02:50:46 +0000
@@ -481,6 +481,20 @@
481 )481 )
482add_dependencies (test-bg-hash unity-core-${UNITY_API_VERSION})482add_dependencies (test-bg-hash unity-core-${UNITY_API_VERSION})
483483
484find_package (OpenGL)
485
486include_directories (${OPENGL_gl_INCDIRS})
487add_library (glfuncloader SHARED
488 ${CMAKE_CURRENT_SOURCE_DIR}/GLFuncLoader.cpp)
489target_link_libraries (glfuncloader dl ${OPENGL_gl_LIBRARY})
490add_executable (screen-effect-fbo
491 TestScreenEffectFramebufferObject.cpp
492 ${UNITY_SRC}/ScreenEffectFramebufferObject.cpp
493 ${UNITY_SRC}/BackgroundEffectHelper.cpp)
494
495target_link_libraries (screen-effect-fbo glfuncloader ${OPENGL_gl_LIBRARY})
496add_dependencies (screen-effect-fbo unity-core-${UNITY_API_VERSION})
497
484add_subdirectory (test-input-remover)498add_subdirectory (test-input-remover)
485add_subdirectory (test-minimize-window-handler)499add_subdirectory (test-minimize-window-handler)
486add_subdirectory (test-get-transients)500add_subdirectory (test-get-transients)
487501
=== added file 'tests/GLFuncLoader.cpp'
--- tests/GLFuncLoader.cpp 1970-01-01 00:00:00 +0000
+++ tests/GLFuncLoader.cpp 2012-01-05 02:50:46 +0000
@@ -0,0 +1,51 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/* Compiz unity plugin
3 * unity.h
4 *
5 * Copyright (c) 2010-11 Canonical Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#include "GLFuncLoader.h"
21#include <dlfcn.h>
22
23unity::GLLoader::FuncPtr unity::GLLoader::getProcAddr(const std::string &name)
24{
25 static void *dlhand = NULL;
26 FuncPtr funcPtr = NULL;
27
28 glGetError ();
29
30 if (!funcPtr)
31 {
32 if (!dlhand)
33 dlhand = dlopen ("libglfuncloader.so", RTLD_LAZY);
34
35 char *error = dlerror ();
36
37 if (dlhand)
38 {
39 dlerror ();
40 funcPtr = (FuncPtr) dlsym (dlhand, name.c_str ());
41
42 error = dlerror ();
43 if (error != NULL)
44 funcPtr = NULL;
45 }
46 }
47
48 return funcPtr;
49}
50
51
052
=== added file 'tests/GLFuncLoader.h'
--- tests/GLFuncLoader.h 1970-01-01 00:00:00 +0000
+++ tests/GLFuncLoader.h 2012-01-05 02:50:46 +0000
@@ -0,0 +1,33 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/* Compiz unity plugin
3 * unity.h
4 *
5 * Copyright (c) 2010-11 Canonical Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#include <string>
21#include <GL/gl.h>
22#include <GL/glx.h>
23
24namespace unity
25{
26namespace GLLoader
27{
28typedef void (*FuncPtr) (void);
29typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
30
31FuncPtr getProcAddr(const std::string &name);
32}
33}
034
=== added file 'tests/TestScreenEffectFramebufferObject.cpp'
--- tests/TestScreenEffectFramebufferObject.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestScreenEffectFramebufferObject.cpp 2012-01-05 02:50:46 +0000
@@ -0,0 +1,671 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/* Compiz unity plugin
3 * unity.h
4 *
5 * Copyright (c) 2010-11 Canonical Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#include "ScreenEffectFramebufferObject.h"
21#include "BackgroundEffectHelper.h"
22#include "GLFuncLoader.h"
23#include <Nux/Nux.h>
24#include <Nux/VLayout.h>
25#include <Nux/View.h>
26#include <Nux/BaseWindow.h>
27#include <Nux/WindowCompositor.h>
28#include <NuxCore/Logger.h>
29#include <NuxCore/Object.h>
30#include <X11/Xlib.h>
31#include <X11/Xutil.h>
32#include <GL/glx.h>
33#include <GL/gl.h>
34#include <dlfcn.h>
35#include <sys/poll.h>
36#include <unistd.h>
37#include <glib.h>
38#include <gtk/gtk.h>
39#include <cmath>
40
41using namespace unity::GLLoader;
42
43namespace
44{
45 nux::logging::Logger logger ("unity.test-screeneffectframebufferobject");
46
47 const static int attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT,
48 GLX_X_RENDERABLE, True,
49 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
50 GLX_DOUBLEBUFFER, True,
51 GLX_RED_SIZE, 8,
52 GLX_GREEN_SIZE, 8,
53 GLX_BLUE_SIZE, 8, 0};
54}
55
56namespace GLFuncs
57{
58 GLXGetProcAddressProc glXGetProcAddressP;
59 PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfigP;
60 PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfigP;
61 PFNGLXCREATEWINDOWPROC glXCreateWindowP;
62 PFNGLXDESTROYWINDOWPROC glXDestroyWindowP;
63 PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrentP;
64
65 void init ()
66 {
67 glXGetProcAddressP = (GLXGetProcAddressProc) getProcAddr ("glXGetProcAddress");
68 glXChooseFBConfigP = (PFNGLXCHOOSEFBCONFIGPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXChooseFBConfig");
69 glXGetVisualFromFBConfigP = (PFNGLXGETVISUALFROMFBCONFIGPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXGetVisualFromFBConfig");
70 glXCreateWindowP = (PFNGLXCREATEWINDOWPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXCreateWindow");
71 glXMakeContextCurrentP = (PFNGLXMAKECONTEXTCURRENTPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXMakeContextCurrent");
72 glXDestroyWindowP = (PFNGLXDESTROYWINDOWPROC) (*glXGetProcAddressP) ((const GLubyte *) "glXDestroyWindow");
73 }
74}
75
76class EffectView :
77 public nux::View
78{
79public:
80 EffectView (NUX_FILE_LINE_PROTO);
81 virtual ~EffectView ();
82
83 void Draw (nux::GraphicsEngine &context, bool force) { return; };
84 void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
85private:
86 BackgroundEffectHelper bg_effect_helper_;
87};
88
89class Shape
90{
91 public:
92
93 typedef boost::shared_ptr <Shape> Ptr;
94
95 Shape ();
96 virtual ~Shape ();
97
98 float rotation () { return mRotation; }
99
100 void draw (unsigned int width, unsigned int height) { glDraw (width, height); }
101 void rotate () { applyRotation (); }
102
103 protected:
104
105 float mRotation;
106
107 virtual void glDraw (unsigned int width, unsigned int height) = 0;
108 virtual void applyRotation () = 0;
109 virtual void getRotationAxes (float &x, float &y, float &z) = 0;
110};
111
112Shape::Shape () :
113 mRotation (0.0f)
114{
115}
116
117Shape::~Shape ()
118{
119}
120
121class Triangle :
122 public Shape
123{
124 public:
125
126 typedef boost::shared_ptr <Triangle> Ptr;
127
128 protected:
129
130 void glDraw (unsigned int width, unsigned int height);
131 void applyRotation () { mRotation += 5.0f; }
132 void getRotationAxes (float &x, float &y, float &z) { x = 0.0f; y = 1.0f; z = 0.0f; }
133};
134
135void
136Triangle::glDraw (unsigned int width, unsigned int height)
137{
138 glBegin(GL_TRIANGLES);
139 glColor3f(1.0f, 0.0f, 0.0f);
140 glVertex3f(width / 4, height, 0.0f);
141 glColor3f(0.0f, 1.0f, 0.0f);
142 glVertex3f(0.0f, 0.0f, 0.0f);
143 glColor3f(0.0f, 0.0f, 1.0f);
144 glVertex3f(width / 2, 0.0f, 0.0f);
145 glEnd();
146}
147
148class Square :
149 public Shape
150{
151 public:
152
153 typedef boost::shared_ptr <Square> Ptr;
154
155 protected:
156
157 void glDraw (unsigned int width, unsigned int height);
158 void applyRotation () { mRotation -= 2.5f; }
159 void getRotationAxes (float &x, float &y, float &z) { x = 1.0f; y = 0.0f; z = 0.0f; }
160
161};
162
163void
164Square::glDraw (unsigned int width, unsigned int height)
165{
166 glBegin(GL_QUADS);
167 glColor3f(sin (rotation () / 100.0f), -sin (rotation () / 100.0f), cos (rotation () / 100.0f));
168 glVertex3f(width / 2, height, 0.0f);
169 glColor3f(-sin (rotation () / 100.0f), sin (rotation () / 100.0f), cos (rotation () / 100.0f));
170 glVertex3f(width, height, 0.0f);
171 glColor3f(sin (rotation () / 100.0f), sin (rotation () / 100.0f), sin (rotation () / 100.0f));
172 glVertex3f(width, 0.0f, 0.0f);
173 glColor3f(-sin (rotation () / 100.0f), cos (rotation () / 100.0f), cos (rotation () / 100.0f));
174 glVertex3f(width / 2, 0.0f, 0.0f);
175 glEnd();
176}
177
178class BaseContext
179{
180 public:
181
182 BaseContext (Display *);
183 ~BaseContext ();
184
185 void run ();
186
187 protected:
188
189 bool eventHandler ();
190 bool paintDispatch ();
191
192 enum class ModifierApplication
193 {
194 Square,
195 Triangle,
196 Both
197 };
198
199 void nextWindowPosition ();
200 void nextShapeRotation ();
201 void setupContextForSize (unsigned int width,
202 unsigned int height);
203 void drawShape (const Shape::Ptr &) {};
204
205 private:
206
207 static gboolean onNewEvents (GIOChannel *channel,
208 GIOCondition condition,
209 gpointer data);
210
211 static gboolean onPaintTimeout (gpointer data);
212
213 static void onWindowThreadCreation (nux::NThread *thread, void *d);
214
215 Display *mDisplay;
216 Window mWindow;
217 Colormap mColormap;
218 nux::WindowThread *mWindowThread;
219 nux::View *mRootView;
220 ScreenEffectFramebufferObject::Ptr mFbo;
221 GLXWindow mGlxWindow;
222 GLXContext mContext;
223 ModifierApplication mRotating;
224 ModifierApplication mBlur;
225 unsigned int mWidth;
226 unsigned int mHeight;
227 bool mNuxReady;
228 Shape::Ptr mTriangle;
229 Shape::Ptr mSquare;
230};
231
232BaseContext::BaseContext (Display *display) :
233 mDisplay (display),
234 mWindowThread (NULL),
235 mRotating (ModifierApplication::Both),
236 mBlur (ModifierApplication::Both),
237 mWidth (640),
238 mHeight (480),
239 mNuxReady (false),
240 mTriangle (new Triangle ()),
241 mSquare (new Square ())
242{
243 int numFBConfig = 0;
244 GLXFBConfig *fbConfigs = (*GLFuncs::glXChooseFBConfigP) (mDisplay,
245 DefaultScreen (mDisplay),
246 attributes,
247 &numFBConfig);
248 XVisualInfo *visinfo = (*GLFuncs::glXGetVisualFromFBConfigP) (mDisplay,
249 fbConfigs[0]);
250
251 mContext = glXCreateContext (mDisplay, visinfo, 0, GL_TRUE);
252 mColormap = XCreateColormap (mDisplay,
253 DefaultRootWindow (mDisplay),
254 visinfo->visual,
255 AllocNone);
256
257 XSetWindowAttributes wa;
258
259 wa.colormap = mColormap;
260 wa.border_pixel = 0;
261 wa.event_mask = StructureNotifyMask | KeyPressMask | ExposureMask;
262
263 mWindow = XCreateWindow (mDisplay, DefaultRootWindow (mDisplay),
264 0, 0, mWidth, mHeight, 0, visinfo->depth, InputOutput,
265 visinfo->visual, CWColormap | CWEventMask | CWBorderPixel,
266 &wa);
267
268 mGlxWindow = (*GLFuncs::glXCreateWindowP) (mDisplay, fbConfigs[0], mWindow, NULL);
269
270 XStoreName (mDisplay, mWindow, "F1: Toggle Effect, F2: Rotation, F3: Effect");
271 XMapWindow (mDisplay, mWindow);
272
273 bool ready = false;
274
275 do
276 {
277 XEvent ev;
278 XNextEvent (mDisplay, &ev);
279 switch (ev.type)
280 {
281 case MapNotify:
282 case ConfigureNotify:
283 case Expose:
284 ready = true;
285 break;
286 default:
287 break;
288 }
289
290 } while (!ready);
291
292 (*GLFuncs::glXMakeContextCurrentP) (mDisplay, mGlxWindow, mGlxWindow, mContext);
293
294 setupContextForSize (mWidth, mHeight);
295}
296
297void
298BaseContext::run ()
299{
300 GIOChannel *channel;
301 mWindowThread = nux::CreateFromForeignWindow (mWindow,
302 mContext,
303 &BaseContext::onWindowThreadCreation,
304 (void *) this);
305
306 mWindowThread->Run(NULL);
307
308 while (!mNuxReady);
309 g_timeout_add (128, &BaseContext::onPaintTimeout, (gpointer) this);
310
311 channel = g_io_channel_unix_new (ConnectionNumber (mDisplay));
312
313 g_io_add_watch (channel, (GIOCondition) (G_IO_IN | G_IO_HUP | G_IO_ERR),
314 &BaseContext::onNewEvents, (gpointer) this);
315 gtk_main ();
316}
317
318BaseContext::~BaseContext ()
319{
320 delete mWindowThread;
321
322 (*GLFuncs::glXMakeContextCurrentP) (mDisplay, None, None, mContext);
323 glXDestroyContext (mDisplay, mContext);
324 (*GLFuncs::glXDestroyWindowP) (mDisplay, mGlxWindow);
325
326 XFreeColormap (mDisplay, mColormap);
327 XDestroyWindow (mDisplay, mWindow);
328}
329
330void
331BaseContext::setupContextForSize (unsigned int width,
332 unsigned int height)
333{
334 mWidth = width;
335 mHeight = height;
336
337 glViewport(0, 0, width, height);
338 glDrawBuffer (GL_BACK);
339 glReadBuffer (GL_BACK);
340 glMatrixMode(GL_PROJECTION);
341 glLoadIdentity();
342 gluPerspective(60.0f, 1.0f, 0.1f, 100.0f);
343 glMatrixMode(GL_MODELVIEW);
344 glLoadIdentity ();
345 glClearColor (1, 1, 1, 1);
346 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
347 glXSwapBuffers (mDisplay, mGlxWindow);
348
349 if (mFbo)
350 mFbo.reset (new ScreenEffectFramebufferObject (GLFuncs::glXGetProcAddressP, nux::Geometry (0, 0, mWidth, mHeight)));
351
352 if (mRootView && mNuxReady)
353 {
354 switch (mBlur)
355 {
356 case ModifierApplication::Both:
357 mRootView->SetGeometry (nux::Geometry (0, 0, mWidth / 2, mHeight));
358 break;
359 case ModifierApplication::Triangle:
360 mRootView->SetGeometry (nux::Geometry (mWidth / 2, 0, mWidth / 2, mHeight));
361 break;
362 case ModifierApplication::Square:
363 mRootView->SetGeometry (nux::Geometry (0, 0, mWidth, mHeight));
364 break;
365 default:
366 break;
367 }
368 }
369}
370
371bool
372BaseContext::eventHandler ()
373{
374 XEvent event;
375 XEvent *ev = &event;
376
377 XNextEvent (mDisplay, &event);
378
379 switch (ev->type)
380 {
381 case KeyPress:
382 if (XLookupKeysym (&ev->xkey, 0) == XK_Escape)
383 return false;
384 else if (XLookupKeysym (&ev->xkey, 0) == XK_F1)
385 {
386 if (!mFbo)
387 {
388 BackgroundEffectHelper::blur_type = unity::BLUR_ACTIVE;
389 mFbo.reset (new ScreenEffectFramebufferObject (GLFuncs::glXGetProcAddressP, nux::Geometry (0, 0, mWidth, mHeight)));
390 }
391 else
392 {
393 BackgroundEffectHelper::blur_type = unity::BLUR_NONE;
394 mFbo.reset ();
395 }
396 }
397 else if (XLookupKeysym (&ev->xkey, 0) == XK_F2)
398 nextShapeRotation ();
399 else if (XLookupKeysym (&ev->xkey, 0) == XK_F3)
400 nextWindowPosition ();
401 break;
402 case ConfigureNotify:
403 setupContextForSize (ev->xconfigure.width, ev->xconfigure.height);
404 default:
405 break;
406 }
407
408 return true;
409}
410
411gboolean
412BaseContext::onNewEvents (GIOChannel *channel,
413 GIOCondition condition,
414 gpointer data)
415{
416 BaseContext *self = static_cast <BaseContext *> (data);
417
418 if (condition & G_IO_IN)
419 {
420 if (self->eventHandler ())
421 return TRUE;
422 else
423 return FALSE;
424 }
425
426 return TRUE;
427}
428
429gboolean
430BaseContext::onPaintTimeout (gpointer data)
431{
432 BaseContext *self = static_cast <BaseContext *> (data);
433
434 if (self->paintDispatch ())
435 return TRUE;
436
437 return FALSE;
438}
439
440void
441BaseContext::nextShapeRotation ()
442{
443 switch (mRotating)
444 {
445 case ModifierApplication::Both:
446 mRotating = ModifierApplication::Triangle;
447 break;
448 case ModifierApplication::Triangle:
449 mRotating = ModifierApplication::Square;
450 break;
451 case ModifierApplication::Square:
452 mRotating = ModifierApplication::Both;
453 break;
454 default:
455 break;
456 }
457}
458
459void
460BaseContext::nextWindowPosition ()
461{
462 switch (mBlur)
463 {
464 case ModifierApplication::Both:
465 mBlur = ModifierApplication::Triangle;
466 mRootView->SetGeometry (nux::Geometry (0, 0, mWidth / 2, mHeight));
467 break;
468 case ModifierApplication::Triangle:
469 mBlur = ModifierApplication::Square;
470 mRootView->SetGeometry (nux::Geometry (mWidth / 2, 0, mWidth / 2, mHeight));
471 break;
472 case ModifierApplication::Square:
473 mBlur = ModifierApplication::Both;
474 mRootView->SetGeometry (nux::Geometry (0, 0, mWidth, mHeight));
475 break;
476 default:
477 break;
478 }
479}
480
481EffectView::EffectView (NUX_FILE_LINE_DECL)
482 : View (NUX_FILE_LINE_PARAM)
483{
484 bg_effect_helper_.owner = this;
485}
486
487EffectView::~EffectView ()
488{
489}
490
491void EffectView::DrawContent (nux::GraphicsEngine &GfxContext, bool force_draw)
492{
493 nux::Geometry base = GetGeometry();
494 GfxContext.PushClippingRectangle(base);
495 nux::Geometry blur_geo (base.x, base.y, base.width, base.height);
496
497 if (BackgroundEffectHelper::blur_type == unity::BLUR_ACTIVE)
498 {
499 bg_effect_helper_.enabled = true;
500
501 auto blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo);
502
503 if (blur_texture.IsValid ())
504 {
505 nux::TexCoordXForm texxform_blur_bg;
506 texxform_blur_bg.flip_v_coord = true;
507 texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
508 texxform_blur_bg.uoffset = ((float) base.x) / (base.width);
509 texxform_blur_bg.voffset = ((float) base.y) / (base.height);
510
511 nux::ROPConfig rop;
512 rop.Blend = false;
513 rop.SrcBlend = GL_ONE;
514 rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
515
516 gPainter.PushDrawTextureLayer(GfxContext, base,
517 blur_texture,
518 texxform_blur_bg,
519 nux::color::White,
520 true,
521 rop);
522 }
523 }
524 else
525 bg_effect_helper_.enabled = false;
526 GfxContext.PopClippingRectangle();
527}
528
529bool
530BaseContext::paintDispatch ()
531{
532 if (mFbo)
533 {
534 switch (mRotating)
535 {
536 case ModifierApplication::Both:
537 BackgroundEffectHelper::ProcessDamage (nux::Geometry (0, 0, mWidth, mHeight));
538 break;
539 case ModifierApplication::Triangle:
540 BackgroundEffectHelper::ProcessDamage (nux::Geometry (0, 0, mWidth / 2, mHeight));
541 break;
542 case ModifierApplication::Square:
543 BackgroundEffectHelper::ProcessDamage (nux::Geometry (mWidth / 2, 0, mWidth / 2, mHeight));
544 break;
545 }
546
547 mFbo->bind (nux::Geometry (0, 0, mWidth, mHeight));
548
549 if (!mFbo->status ())
550 {
551 LOG_INFO (logger) << "FBO not ok!";
552 }
553 }
554
555 glClearColor (1, 1, 1, 1);
556 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
557 glPushMatrix ();
558 glLoadIdentity();
559 glTranslatef(-0.5f, -0.5f, -0.866025404f);
560 glScalef (1.0f / mWidth, 1.0f / mHeight, 0.0f);
561 glTranslatef(mWidth * 0.25, 0, 0);
562 glRotatef(mTriangle->rotation (), 0.0f, 1.0f, 0.0f);
563 glTranslatef(-(mWidth * 0.25), 0, 0);
564
565 mTriangle->draw (mWidth, mHeight);
566
567 glLoadIdentity();
568 glTranslatef(-0.5f, -0.5f, -0.866025404f);
569 glScalef (1.0f / mWidth, 1.0f / mHeight, 0.0f);
570 glTranslatef(mWidth * 0.75, 0, 0);
571 glRotatef(mSquare->rotation (), 0.0f, 1.0f, 0.0f);
572 glTranslatef(-(mWidth * 0.75), 0, 0);
573
574 mSquare->draw (mWidth, mHeight);
575
576 glColor4f (1.0f, 1.0f, 1.0f, 5.0f);
577 glPopMatrix ();
578
579 if (mFbo)
580 mFbo->unbind ();
581
582 if (mFbo && mFbo->status ())
583 {
584 glClearColor (1, 1, 1, 1);
585 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
586 glPushMatrix ();
587 glLoadIdentity();
588 glTranslatef(-0.5f, 0.5f, -0.866025404f);
589 glScalef (1.0f / mWidth, -(1.0f / mHeight), 0.0f);
590 mFbo->paint (nux::Geometry (0, 0, mWidth, mHeight));
591 glPopMatrix ();
592
593 nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
594 nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID (mFbo->texture(),
595 mWidth, mHeight, 1, nux::BITFMT_R8G8B8A8);
596
597 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
598
599 nux::Geometry geo = nux::Geometry (0, 0, mWidth, mHeight);
600 BackgroundEffectHelper::monitor_rect_ = geo;
601 }
602
603 glMatrixMode(GL_PROJECTION);
604 glPushMatrix();
605
606 glMatrixMode(GL_MODELVIEW);
607 glPushMatrix();
608 glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT |
609 GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
610 mRootView->ProcessDraw (mWindowThread->GetGraphicsEngine (), true);
611 glMatrixMode(GL_PROJECTION);
612 glPopMatrix();
613 glMatrixMode(GL_MODELVIEW);
614 glPopMatrix();
615
616 glDrawBuffer(GL_BACK);
617 glReadBuffer(GL_BACK);
618
619 glPopAttrib();
620
621 glXSwapBuffers (mDisplay, mGlxWindow);
622
623 switch (mRotating)
624 {
625 case ModifierApplication::Both:
626 mTriangle->rotate ();
627 mSquare->rotate ();
628 break;
629 case ModifierApplication::Triangle:
630 mTriangle->rotate ();
631 break;
632 case ModifierApplication::Square:
633 mSquare->rotate ();
634 break;
635 }
636
637 return true;
638}
639
640void
641BaseContext::onWindowThreadCreation (nux::NThread *thread, void *data)
642{
643 BaseContext *bc = static_cast <BaseContext *> (data);
644
645 bc->mRootView = new EffectView ();
646 bc->mRootView->SetGeometry (nux::Geometry (0, 0, 640, 480));
647 bc->mNuxReady = true;
648 BackgroundEffectHelper::blur_type = unity::BLUR_ACTIVE;
649}
650
651int main (int argc, char **argv)
652{
653 Display *display = XOpenDisplay (NULL);
654 nux::NuxInitialize (0);
655 GLFuncs::init ();
656 g_type_init ();
657 g_thread_init (NULL);
658 gtk_init(&argc, &argv);
659
660 BaseContext *bc = new BaseContext (display);
661
662 bc->run ();
663
664 delete bc;
665
666 XCloseDisplay (display);
667
668 return 0;
669}
670
671

Subscribers

People subscribed via source and target branches

to all changes: