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

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/unity/unity.big_fbo
Merge into: lp:unity
Diff against target: 369 lines (+57/-85)
2 files modified
plugins/unityshell/src/unityshell.cpp (+50/-77)
plugins/unityshell/src/unityshell.h (+7/-8)
To merge this branch: bzr merge lp:~smspillaz/unity/unity.big_fbo
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve
Mirco Müller (community) Needs Fixing
Neil J. Patel Pending
Review via email: mp+78202@code.launchpad.net

This proposal has been superseded by a proposal from 2011-11-14.

Description of the change

Fix bug 868120 and bug 872625

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

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

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

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

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

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

Revision history for this message
Michal Hruby (mhr3) wrote :

Nvidia here and I can confirm MacSlow's findings.

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

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

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

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

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

Revision history for this message
Michal Hruby (mhr3) wrote :

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

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

+1

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

Can someone with fglrx test this ?

Revision history for this message
Gord Allott (gordallott) wrote :

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

merge approved

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/unityshell.cpp'
2--- plugins/unityshell/src/unityshell.cpp 2011-10-11 02:24:19 +0000
3+++ plugins/unityshell/src/unityshell.cpp 2011-10-12 14:53:30 +0000
4@@ -112,7 +112,7 @@
5 , _key_nav_mode_requested(false)
6 , _last_output(nullptr)
7 , switcher_desktop_icon(nullptr)
8- , mActiveFbo (0)
9+ , _active_fbo (0)
10 , dash_is_open_ (false)
11 , grab_index_ (0)
12 , painting_tray_ (false)
13@@ -227,10 +227,8 @@
14
15 if (GL::fbo)
16 {
17- foreach (CompOutput & o, screen->outputDevs())
18- uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO(&o));
19-
20- uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO(&(screen->fullscreenOutput ())));
21+ CompRect geometry = CompRect (0, 0, screen->width (), screen->height ());
22+ uScreen->_fbo = UnityFBO::Ptr (new UnityFBO (geometry));
23 }
24
25 optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
26@@ -433,6 +431,8 @@
27 * drivers (lp:703140). */
28 glDisable(GL_LIGHTING);
29
30+ _fbo->unbind ();
31+
32 /* reset matrices */
33 glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT |
34 GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
35@@ -448,7 +448,7 @@
36
37 void UnityScreen::nuxEpilogue()
38 {
39- (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, mActiveFbo);
40+ (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo);
41
42 glMatrixMode(GL_PROJECTION);
43 glLoadIdentity();
44@@ -471,6 +471,8 @@
45 glPopAttrib();
46
47 glDisable(GL_SCISSOR_TEST);
48+
49+ _fbo->bind (_last_output);
50 }
51
52 void UnityScreen::OnLauncherHiddenChanged()
53@@ -489,8 +491,6 @@
54 if (PluginAdapter::Default()->IsExpoActive())
55 return;
56
57- nuxPrologue();
58-
59 CompOutput* output = _last_output;
60 float vc[4];
61 float h = 20.0f;
62@@ -501,6 +501,9 @@
63 float y1 = output->y() + panel_h;
64 float x2 = x1 + output->width();
65 float y2 = y1 + h;
66+ GLMatrix sTransform = GLMatrix ();
67+
68+ sTransform.toScreenSpace(output, -DEFAULT_Z_CAMERA);
69
70 vc[0] = x1;
71 vc[1] = x2;
72@@ -540,7 +543,6 @@
73 glDisable(GL_BLEND);
74 }
75 }
76- nuxEpilogue();
77 }
78
79 void
80@@ -559,33 +561,29 @@
81 {
82 CompOutput *output = _last_output;
83 Window tray_xid = panelController->GetTrayXid ();
84- bool bound = mFbos[output]->bound ();
85-
86-
87- if (bound)
88- {
89- mFbos[output]->unbind ();
90-
91- /* Draw the bit of the relevant framebuffer for each output */
92- mFbos[output]->paint ();
93- }
94
95 nuxPrologue();
96
97+ /* Draw the bit of the relevant framebuffer for each output */
98+ _fbo->paint (output);
99+
100 nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
101- nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(mFbos[output]->texture(),
102- output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
103+ nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),
104+ screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
105
106 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
107
108- nux::Geometry geo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
109+ nux::Geometry geo = nux::Geometry (0, 0, screen->width (), screen->height ());
110+ nux::Geometry oGeo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
111 BackgroundEffectHelper::monitor_rect_ = geo;
112
113 _in_paint = true;
114- wt->RenderInterfaceFromForeignCmd (&geo);
115+ wt->RenderInterfaceFromForeignCmd (&oGeo);
116 _in_paint = false;
117 nuxEpilogue();
118
119+ _fbo->unbind ();
120+
121 if (tray_xid && !allowWindowPaint)
122 {
123 CompWindow *tray = screen->findWindow (tray_xid);
124@@ -936,6 +934,10 @@
125 {
126 bool ret;
127
128+ doShellRepaint = true;
129+ allowWindowPaint = true;
130+ _last_output = output;
131+
132 /* bind the framebuffer here
133 * - it will be unbound and flushed
134 * to the backbuffer when some
135@@ -946,11 +948,7 @@
136 * attempts to bind it will only increment
137 * its bind reference so make sure that
138 * you always unbind as much as you bind */
139- mFbos[output]->bind ();
140-
141- doShellRepaint = true;
142- allowWindowPaint = true;
143- _last_output = output;
144+ _fbo->bind (output);
145
146 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
147 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
148@@ -2084,16 +2082,14 @@
149 GdkRectangle rect;
150 nux::Geometry lCurGeom;
151 int panel_height = 24;
152+ CompRect geometry = CompRect (0, 0, screen->width (), screen->height ());
153
154 if (!needsRelayout)
155 return;
156
157 if (GL::fbo)
158 {
159- foreach (CompOutput &o, screen->outputDevs ())
160- uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO (&o));
161-
162- uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO (&(screen->fullscreenOutput ())));
163+ uScreen->_fbo = UnityFBO::Ptr (new UnityFBO (geometry));
164 }
165
166 UScreen *uscreen = UScreen::GetDefault();
167@@ -2132,8 +2128,6 @@
168 {
169 UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);
170
171- uScreen->mFbos.clear ();
172-
173 uScr->NeedsRelayout ();
174 uScr->Relayout();
175 uScr->relayoutSourceId = 0;
176@@ -2166,23 +2160,17 @@
177 ScheduleRelayout(500);
178 }
179
180-void UnityFBO::paint ()
181+void UnityFBO::paint (CompOutput *output)
182 {
183- //CompositeScreen *cScreen = CompositeScreen::get (screen);
184- //unsigned int mask = cScreen->damageMask ();
185 float texx, texy, texwidth, texheight;
186
187- /* Must be completely unbound before painting */
188- if (mBoundCnt)
189- return;
190-
191 /* Draw the bit of the relevant framebuffer for each output */
192 GLMatrix transform;
193
194- glViewport (output->x (), screen->height () - output->y2 (), output->width (), output->height ());
195- GLScreen::get (screen)->clearOutput (output, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
196+ glPushAttrib (GL_VIEWPORT_BIT);
197+ glViewport (0, 0, screen->width (), screen->height ());
198
199- transform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
200+ transform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
201 glPushMatrix ();
202 glLoadMatrixf (transform.getMatrix ());
203
204@@ -2204,18 +2192,18 @@
205 glEnable (GL_SCISSOR_TEST);
206
207 glScissor (output->x1 (), screen->height () - output->y2 (),
208- output->width (), output->height ());
209+ output->width (), output->height ());
210
211 /* FIXME: This needs to be GL_TRIANGLE_STRIP */
212 glBegin (GL_QUADS);
213 glTexCoord2f (texx, texy + texheight);
214- glVertex2i (output->x1 (), output->y1 ());
215+ glVertex2i (mGeometry.x1 (), mGeometry.y1 ());
216 glTexCoord2f (texx, texy);
217- glVertex2i (output->x1 (), output->y2 ());
218+ glVertex2i (mGeometry.x1 (), mGeometry.y2 ());
219 glTexCoord2f (texx + texwidth, texy);
220- glVertex2i (output->x2 (), output->y2 ());
221+ glVertex2i (mGeometry.x2 (), mGeometry.y2 ());
222 glTexCoord2f (texx + texwidth, texy + texheight);
223- glVertex2i (output->x2 (), output->y1 ());
224+ glVertex2i (mGeometry.x2 (), mGeometry.y1 ());
225 glEnd ();
226
227 GL::activeTexture (GL_TEXTURE0_ARB);
228@@ -2227,16 +2215,13 @@
229 glDisable (GL_SCISSOR_TEST);
230 glPopAttrib ();
231 }
232+ glPopAttrib ();
233
234 glPopMatrix();
235 }
236
237 void UnityFBO::unbind ()
238 {
239- mBoundCnt--;
240-
241- if (mBoundCnt)
242- return;
243
244 uScreen->setActiveFbo (0);
245 (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
246@@ -2244,11 +2229,9 @@
247 glDrawBuffer (GL_BACK);
248 glReadBuffer (GL_BACK);
249
250-}
251+ /* Matches the viewport set we did in ::bind () */
252+ glPopAttrib ();
253
254-bool UnityFBO::bound ()
255-{
256- return mBoundCnt > 0;
257 }
258
259 bool UnityFBO::status ()
260@@ -2256,14 +2239,8 @@
261 return mFboStatus;
262 }
263
264-void UnityFBO::bind ()
265+void UnityFBO::bind (CompOutput *output)
266 {
267- if (mBoundCnt)
268- {
269- mBoundCnt++;
270- return;
271- }
272-
273 if (!mFBTexture)
274 {
275 glGenTextures (1, &mFBTexture);
276@@ -2273,7 +2250,7 @@
277 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
278 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
279 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
280- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, output->width(), output->height(), 0, GL_BGRA,
281+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, mGeometry.width (), mGeometry.height (), 0, GL_BGRA,
282 #if IMAGE_BYTE_ORDER == MSBFirst
283 GL_UNSIGNED_INT_8_8_8_8_REV,
284 #else
285@@ -2351,23 +2328,19 @@
286 {
287 uScreen->setActiveFbo (mFboHandle);
288
289- glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
290- glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
291-
292- glViewport (0,
293- 0,
294- output->width(),
295- output->height());
296-
297- mBoundCnt++;
298+ glPushAttrib (GL_VIEWPORT_BIT);
299+
300+ glViewport (output->x (),
301+ screen->height () - output->y2 (),
302+ output->width (),
303+ output->height());
304 }
305 }
306
307-UnityFBO::UnityFBO (CompOutput *o)
308+UnityFBO::UnityFBO (CompRect geometry)
309 : mFboStatus (false)
310 , mFBTexture (0)
311- , output (o)
312- , mBoundCnt (0)
313+ , mGeometry (geometry)
314 {
315 (*GL::genFramebuffers) (1, &mFboHandle);
316 }
317
318=== modified file 'plugins/unityshell/src/unityshell.h'
319--- plugins/unityshell/src/unityshell.h 2011-10-03 12:54:22 +0000
320+++ plugins/unityshell/src/unityshell.h 2011-10-12 14:53:30 +0000
321@@ -54,17 +54,16 @@
322
323 typedef boost::shared_ptr <UnityFBO> Ptr;
324
325- UnityFBO (CompOutput *o);
326+ UnityFBO (CompRect r);
327 ~UnityFBO ();
328
329 public:
330
331- void bind ();
332+ void bind (CompOutput *o);
333 void unbind ();
334
335 bool status ();
336- bool bound ();
337- void paint ();
338+ void paint (CompOutput *o);
339
340 GLuint texture () { return mFBTexture; }
341
342@@ -74,7 +73,7 @@
343 GLuint mFboHandle; // actual handle to the framebuffer_ext
344 bool mFboStatus; // did the framebuffer texture bind succeed
345 GLuint mFBTexture;
346- CompOutput *output;
347+ CompRect mGeometry;
348 unsigned int mBoundCnt;
349 };
350
351@@ -234,7 +233,7 @@
352 void NeedsRelayout();
353 void ScheduleRelayout(guint timeout);
354
355- void setActiveFbo (GLuint fbo) { mActiveFbo = fbo; }
356+ void setActiveFbo (GLuint fbo) { _active_fbo = fbo; }
357
358 bool forcePaintOnTop ();
359
360@@ -321,8 +320,8 @@
361
362 unity::BGHash _bghash;
363
364- std::map <CompOutput *, UnityFBO::Ptr> mFbos;
365- GLuint mActiveFbo;
366+ UnityFBO::Ptr _fbo;
367+ GLuint _active_fbo;
368
369 bool queryForShader ();
370