Merge lp:~smspillaz/unity/unity.less-paint-insanity into lp:unity
- unity.less-paint-insanity
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~smspillaz/unity/unity.less-paint-insanity |
Merge into: | lp:unity |
Diff against target: |
1221 lines (+724/-134) 9 files modified
plugins/unityshell/src/ScreenEffectFramebufferObject.cpp (+10/-1) plugins/unityshell/src/ScreenEffectFramebufferObject.h (+6/-0) plugins/unityshell/src/unityshell.cpp (+187/-119) plugins/unityshell/src/unityshell.h (+39/-14) tests/CMakeLists.txt (+2/-0) tests/test_shell_paint_schedule.cpp (+284/-0) unity-shared/CMakeLists.txt (+1/-0) unity-shared/ShellPaintSchedule.cpp (+91/-0) unity-shared/ShellPaintSchedule.h (+104/-0) |
To merge this branch: | bzr merge lp:~smspillaz/unity/unity.less-paint-insanity |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sam Spilsbury (community) | Needs Fixing | ||
Daniel van Vugt | Approve | ||
Jason Smith | Pending | ||
Marco Trevisan (Treviño) | Pending | ||
Review via email: mp+109757@code.launchpad.net |
This proposal supersedes a proposal from 2012-06-07.
This proposal has been superseded by a proposal from 2012-06-14.
Commit message
Description of the change
Removes the whole scanning of the list thing in getWindowPaintList and the whole "trying to figure out where the window was because we don't actually know" in glDraw by scanning the paint list again and again.
There's a much better way of doing this - just hook glPaint, skip the wrap chain to core (eg every single plugin skipped) and tell core not to do anything with the window.
I have no idea why there is a bunch of logic about whether or not to paint the panel in glDraw (that was moved to glPaint). Someone enlighten me?
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Works for me. Though there are some indentation/tab mismatches around line 107. Looks like your tabs are not 8 characters wide like they should be?
Sam Spilsbury (smspillaz) wrote : | # |
indentation fixed ... will add tests when I have time.
Daniel van Vugt (vanvugt) wrote : | # |
Manual testing -> Works well.
This branch also appears to solve the problem of my missing panel shadow when running dev builds of Unity. But that's just a bonus.
Daniel van Vugt (vanvugt) wrote : | # |
Whoops. It turns out this branch is tricking the decor plugin into painting (proper) shadows for the panel and launcher. It looks awesome so I hope we can keep it. But it's probably a mistake.
Sam Spilsbury (smspillaz) wrote : | # |
> Whoops. It turns out this branch is tricking the decor plugin into painting
> (proper) shadows for the panel and launcher. It looks awesome so I hope we can
> keep it. But it's probably a mistake.
It probably is, thanks for catching that.
- 2374. By Sam Spilsbury
-
Merge lp:unity
- 2375. By Sam Spilsbury
- 2376. By Sam Spilsbury
-
Make the code slightly more sane, use some interfaces to demonstrate
what is happening and break dependencies a little - 2377. By Sam Spilsbury
-
Ensure that we always paint on top of the topmost nux window
- 2378. By Sam Spilsbury
-
Also return false if someone tries to paint us with PAINT_WINDOW_
NO_CORE_ INSTANCE_ MASK - 2379. By Sam Spilsbury
-
Implement top window detection in terms of paint requestor
- 2380. By Sam Spilsbury
-
Merge lp:unity
- 2381. By Sam Spilsbury
-
Move paint requestor enforcement to UnityPaintDispatch
- 2382. By Sam Spilsbury
-
Move paint mask prohibition into UnityPaintDispatch through strategy
- 2383. By Sam Spilsbury
-
Ensure that the backing fbo is painted too
- 2384. By Sam Spilsbury
-
Work correctly with USE_MODERN_
COMPIZ_ GL too - 2385. By Sam Spilsbury
-
Move UnityPaintDispatch to separate file
- 2386. By Sam Spilsbury
-
Use UnityPaintDispatch by composition
- 2387. By Sam Spilsbury
-
Rename variable
- 2388. By Sam Spilsbury
-
UnityPaint* -> ShellPaint*
- 2389. By Sam Spilsbury
-
mv UnityPaintSchedule -> ShellPaintSchedule
- 2390. By Sam Spilsbury
-
Initial tests for ShellPaintSchedule
- 2391. By Sam Spilsbury
-
Basic paint tests
- 2392. By Sam Spilsbury
-
Basic prohibition test
- 2393. By Sam Spilsbury
-
Inverse prohibition test case
- 2394. By Sam Spilsbury
-
Basic top requestor tests
- 2395. By Sam Spilsbury
-
Test suprvening requestor behaviour
- 2396. By Sam Spilsbury
-
Tests for RepaintPending value
- 2397. By Sam Spilsbury
-
Test prohibited paint requestor retreival
- 2398. By Sam Spilsbury
-
Merge lp:unity
- 2399. By Sam Spilsbury
-
Merge lp:unity
- 2400. By Sam Spilsbury
-
Change namespace to unity::compiz
- 2401. By Sam Spilsbury
-
unsigned int -> enum && move namespace compiz {} to namespace unity::compiz
- 2402. By Sam Spilsbury
-
Nuke FBOBindingQuery
Interface - 2403. By Sam Spilsbury
-
Basic documentation, not really a substitute for better code ...
- 2404. By Sam Spilsbury
-
Merge lp:unity
- 2405. By Sam Spilsbury
-
Remove unused method and rename methods to make more sense
Unmerged revisions
- 2405. By Sam Spilsbury
-
Remove unused method and rename methods to make more sense
- 2404. By Sam Spilsbury
-
Merge lp:unity
- 2403. By Sam Spilsbury
-
Basic documentation, not really a substitute for better code ...
- 2402. By Sam Spilsbury
-
Nuke FBOBindingQuery
Interface - 2401. By Sam Spilsbury
-
unsigned int -> enum && move namespace compiz {} to namespace unity::compiz
- 2400. By Sam Spilsbury
-
Change namespace to unity::compiz
- 2399. By Sam Spilsbury
-
Merge lp:unity
- 2398. By Sam Spilsbury
-
Merge lp:unity
- 2397. By Sam Spilsbury
-
Test prohibited paint requestor retreival
- 2396. By Sam Spilsbury
-
Tests for RepaintPending value
Preview Diff
1 | === modified file 'plugins/unityshell/src/ScreenEffectFramebufferObject.cpp' |
2 | --- plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-05-28 03:19:35 +0000 |
3 | +++ plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-06-14 09:04:28 +0000 |
4 | @@ -76,7 +76,6 @@ |
5 | mScreenSize = screenSize; |
6 | } |
7 | |
8 | - |
9 | void unity::ScreenEffectFramebufferObject::unbind () |
10 | { |
11 | if (!mBoundCnt) |
12 | @@ -92,6 +91,8 @@ |
13 | /* Matches the viewport set we did in ::bind () */ |
14 | glPopAttrib (); |
15 | |
16 | + successful_bind_ = true; |
17 | + |
18 | } |
19 | |
20 | bool unity::ScreenEffectFramebufferObject::status () |
21 | @@ -106,6 +107,8 @@ |
22 | * Because binding has a severe impact on graphics performance and we |
23 | * can't afford to do it every frame. (LP: #861061) (LP: #987304) |
24 | */ |
25 | + successful_bind_ = false; |
26 | + |
27 | if (!BackgroundEffectHelper::HasDirtyHelpers()) |
28 | return; |
29 | |
30 | @@ -212,6 +215,11 @@ |
31 | mBoundCnt++; |
32 | } |
33 | |
34 | +bool |
35 | +unity::ScreenEffectFramebufferObject::NewContentsValid () |
36 | +{ |
37 | + return successful_bind_; |
38 | +} |
39 | |
40 | unity::ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom) |
41 | : getProcAddressGLX (p) |
42 | @@ -220,6 +228,7 @@ |
43 | , mGeometry (geom) |
44 | , mBoundCnt (0) |
45 | , mScreenSize (geom) |
46 | + , successful_bind_ (false) |
47 | { |
48 | activeTexture = (GLActiveTextureProc) (*getProcAddressGLX) ((GLubyte *) "glActiveTexture"); |
49 | genFramebuffers = (GLGenFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glGenFramebuffersEXT"); |
50 | |
51 | === modified file 'plugins/unityshell/src/ScreenEffectFramebufferObject.h' |
52 | --- plugins/unityshell/src/ScreenEffectFramebufferObject.h 2012-04-06 10:23:49 +0000 |
53 | +++ plugins/unityshell/src/ScreenEffectFramebufferObject.h 2012-06-14 09:04:28 +0000 |
54 | @@ -49,6 +49,10 @@ |
55 | |
56 | void onScreenSizeChanged (const nux::Geometry &screenSize); |
57 | |
58 | + /* Returns true if the fbo was bound, painted into and unbound |
59 | + * successfully */ |
60 | + bool NewContentsValid (); |
61 | + |
62 | private: |
63 | |
64 | FuncPtr getProcAddr (const std::string &); |
65 | @@ -82,6 +86,8 @@ |
66 | unsigned int mBoundCnt; |
67 | |
68 | nux::Geometry mScreenSize; |
69 | + |
70 | + bool successful_bind_; |
71 | }; |
72 | } // namespace unity |
73 | |
74 | |
75 | === modified file 'plugins/unityshell/src/unityshell.cpp' |
76 | --- plugins/unityshell/src/unityshell.cpp 2012-06-13 03:54:37 +0000 |
77 | +++ plugins/unityshell/src/unityshell.cpp 2012-06-14 09:04:28 +0000 |
78 | @@ -110,6 +110,8 @@ |
79 | , screen(screen) |
80 | , cScreen(CompositeScreen::get(screen)) |
81 | , gScreen(GLScreen::get(screen)) |
82 | + , paint_dispatch_ (this, |
83 | + boost::bind (&UnityScreen::GetProhibitedPaintMasks, this)) |
84 | , debugger_(this) |
85 | , enable_shortcut_overlay_(true) |
86 | , gesture_engine_(screen) |
87 | @@ -117,8 +119,6 @@ |
88 | , _in_paint(false) |
89 | , super_keypressed_(false) |
90 | , newFocusedWindow(nullptr) |
91 | - , doShellRepaint(false) |
92 | - , allowWindowPaint(false) |
93 | , damaged(false) |
94 | , _key_nav_mode_requested(false) |
95 | , _last_output(nullptr) |
96 | @@ -263,8 +263,8 @@ |
97 | if (GL::fbo) |
98 | { |
99 | nux::Geometry geometry (0, 0, screen->width (), screen->height ()); |
100 | - uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry)); |
101 | - uScreen->_fbo->onScreenSizeChanged (geometry); |
102 | + uScreen->fbo_ = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry)); |
103 | + uScreen->fbo_->onScreenSizeChanged (geometry); |
104 | } |
105 | #endif |
106 | |
107 | @@ -734,16 +734,52 @@ |
108 | panel_texture_has_changed_ = true; |
109 | } |
110 | |
111 | -#ifdef USE_MODERN_COMPIZ_GL |
112 | -void UnityScreen::paintDisplay() |
113 | +bool |
114 | +UnityScreen::WasBound () |
115 | +{ |
116 | +#ifndef USE_MODERN_COMPIZ_GL |
117 | + return fbo_->NewContentsValid (); |
118 | #else |
119 | -void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask) |
120 | -#endif |
121 | + return true; |
122 | +#endif |
123 | +} |
124 | + |
125 | +unsigned int |
126 | +UnityScreen::GetPaintRequestorType () |
127 | +{ |
128 | + return ShellPaintRequestorInterface::ScreenPaintRequestor; |
129 | +} |
130 | + |
131 | +bool UnityScreen::PaintBackingFBO (CompOutput *output) |
132 | +{ |
133 | +#ifndef USE_MODERN_COMPIZ_GL |
134 | + fbo_->unbind (); |
135 | + if (fbo_->NewContentsValid ()) |
136 | + { |
137 | + GLMatrix sTransform; |
138 | + sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA); |
139 | + glPushMatrix (); |
140 | + glLoadMatrixf (sTransform.getMatrix ()); |
141 | + fbo_->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ())); |
142 | + glPopMatrix (); |
143 | + |
144 | + return true; |
145 | + } |
146 | +#endif |
147 | + return false; |
148 | +} |
149 | + |
150 | +void UnityScreen::PaintDisplay (FBOBindingQueryInterface *fbo_query) |
151 | { |
152 | CompOutput *output = _last_output; |
153 | |
154 | + PaintBackingFBO (output); |
155 | + |
156 | #ifndef USE_MODERN_COMPIZ_GL |
157 | - bool was_bound = _fbo->bound (); |
158 | + bool was_bound = fbo_query->WasBound (); |
159 | +#else |
160 | + bool was_bound = true; |
161 | +#endif |
162 | |
163 | if (nux::GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath()) |
164 | { |
165 | @@ -779,28 +815,18 @@ |
166 | } |
167 | } |
168 | |
169 | - _fbo->unbind (); |
170 | - |
171 | /* Draw the bit of the relevant framebuffer for each output */ |
172 | |
173 | - if (was_bound) |
174 | - { |
175 | - GLMatrix sTransform; |
176 | - sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA); |
177 | - glPushMatrix (); |
178 | - glLoadMatrixf (sTransform.getMatrix ()); |
179 | - _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ())); |
180 | - glPopMatrix (); |
181 | - } |
182 | + GLuint fbo_texture_name = 0; |
183 | +#ifndef USE_MODERN_COMPIZ_GL |
184 | + fbo_texture_name = fbo_->texture(); |
185 | +#else |
186 | + fbo_texture_name = gScreen->fbo ()->tex ()->name (); |
187 | +#endif |
188 | |
189 | nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture = |
190 | - nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(), |
191 | + nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(fbo_texture_name, |
192 | screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8); |
193 | -#else |
194 | - nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture = |
195 | - nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (), |
196 | - output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8); |
197 | -#endif |
198 | |
199 | nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture; |
200 | |
201 | @@ -823,7 +849,7 @@ |
202 | |
203 | for (Window tray_xid : panel_controller_->GetTrayXids()) |
204 | { |
205 | - if (tray_xid && !allowWindowPaint) |
206 | + if (tray_xid && (no_paint_allowed_mask_ & ShellPaintRequestorInterface::WindowPaintRequestor)) |
207 | { |
208 | CompWindow *tray = screen->findWindow (tray_xid); |
209 | |
210 | @@ -901,15 +927,54 @@ |
211 | } |
212 | } |
213 | |
214 | - doShellRepaint = false; |
215 | damaged = false; |
216 | } |
217 | |
218 | -bool UnityScreen::forcePaintOnTop () |
219 | -{ |
220 | - return !allowWindowPaint || |
221 | - ((switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen()) |
222 | - && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL)))); |
223 | +unsigned int UnityScreen::GetProhibitedPaintMasks () |
224 | +{ |
225 | + bool unity_force_overlay = switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen(); |
226 | + bool no_screen_grabs = !(screen->grabbed () && !screen->otherGrabExist (NULL)); |
227 | + bool fullscreen_windows = !fullscreen_windows_.empty (); |
228 | + |
229 | + unsigned int pmask = no_paint_allowed_mask_; |
230 | + |
231 | + if (unity_force_overlay && |
232 | + fullscreen_windows && |
233 | + no_screen_grabs) |
234 | + pmask |= ShellPaintRequestorInterface::WindowPaintRequestor; |
235 | + |
236 | + return pmask; |
237 | +} |
238 | + |
239 | +bool UnityScreen::Paint (ShellPaintRequestorInterface *r, |
240 | + FBOBindingQueryInterface *q) |
241 | +{ |
242 | + return paint_dispatch_.Paint (r, q); |
243 | +} |
244 | + |
245 | +bool UnityScreen::EnforceRequestor (ShellPaintRequestorInterface *r) |
246 | +{ |
247 | + return paint_dispatch_.EnforceRequestor (r); |
248 | +} |
249 | + |
250 | +void UnityScreen::ClearRequestorEnforcement () |
251 | +{ |
252 | + paint_dispatch_.ClearRequestorEnforcement (); |
253 | +} |
254 | + |
255 | +unsigned int UnityScreen::ProhibitedPaintRequestors () |
256 | +{ |
257 | + return paint_dispatch_.ProhibitedPaintRequestors (); |
258 | +} |
259 | + |
260 | +void UnityScreen::RequireShellRepaint () |
261 | +{ |
262 | + paint_dispatch_.RequireShellRepaint (); |
263 | +} |
264 | + |
265 | +bool UnityScreen::RepaintPending () |
266 | +{ |
267 | + return paint_dispatch_.RepaintPending (); |
268 | } |
269 | |
270 | void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha) |
271 | @@ -1204,8 +1269,9 @@ |
272 | { |
273 | bool ret; |
274 | |
275 | - doShellRepaint = true; |
276 | - allowWindowPaint = true; |
277 | + ClearRequestorEnforcement (); |
278 | + RequireShellRepaint (); |
279 | + no_paint_allowed_mask_ = 0; |
280 | _last_output = output; |
281 | paint_panel_ = false; |
282 | |
283 | @@ -1220,16 +1286,13 @@ |
284 | * attempts to bind it will only increment |
285 | * its bind reference so make sure that |
286 | * you always unbind as much as you bind */ |
287 | - _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ())); |
288 | + fbo_->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ())); |
289 | #endif |
290 | |
291 | /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */ |
292 | ret = gScreen->glPaintOutput(attrib, transform, region, output, mask); |
293 | |
294 | -#ifndef USE_MODERN_COMPIZ_GL |
295 | - if (doShellRepaint) |
296 | - paintDisplay(region, transform, mask); |
297 | -#endif |
298 | + Paint (this, this); |
299 | |
300 | return ret; |
301 | } |
302 | @@ -1241,7 +1304,7 @@ |
303 | { |
304 | bool useFbo = false; |
305 | |
306 | - if (doShellRepaint) |
307 | + if (RepaintPending ()) |
308 | { |
309 | oldFbo = fbo->bind (); |
310 | useFbo = fbo->checkStatus () && fbo->tex (); |
311 | @@ -1250,7 +1313,7 @@ |
312 | ::GLFramebufferObject::rebind (oldFbo); |
313 | return; |
314 | } |
315 | - paintDisplay(); |
316 | + Paint (this, this); |
317 | ::GLFramebufferObject::rebind (oldFbo); |
318 | } |
319 | |
320 | @@ -1267,7 +1330,7 @@ |
321 | CompOutput* output, |
322 | unsigned int mask) |
323 | { |
324 | - allowWindowPaint = false; |
325 | + no_paint_allowed_mask_ = ShellPaintRequestorInterface::WindowPaintRequestor; |
326 | gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask); |
327 | |
328 | } |
329 | @@ -2124,31 +2187,6 @@ |
330 | return "Unity"; |
331 | } |
332 | |
333 | -bool isNuxWindow (CompWindow* value) |
334 | -{ |
335 | - std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList(); |
336 | - auto id = value->id(); |
337 | - |
338 | - // iterate loop by hand rather than use std::find as this is considerably faster |
339 | - // we care about performance here becuase of the high frequency in which this function is |
340 | - // called (nearly every frame) |
341 | - unsigned int size = xwns.size(); |
342 | - for (unsigned int i = 0; i < size; ++i) |
343 | - { |
344 | - if (xwns[i] == id) |
345 | - return true; |
346 | - } |
347 | - return false; |
348 | -} |
349 | - |
350 | -const CompWindowList& UnityScreen::getWindowPaintList() |
351 | -{ |
352 | - CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList(); |
353 | - pl.remove_if(isNuxWindow); |
354 | - |
355 | - return pl; |
356 | -} |
357 | - |
358 | void UnityScreen::RaiseInputWindows() |
359 | { |
360 | std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList(); |
361 | @@ -2161,13 +2199,11 @@ |
362 | } |
363 | } |
364 | |
365 | -/* detect occlusions |
366 | - * |
367 | - * core passes down the PAINT_WINDOW_OCCLUSION_DETECTION |
368 | - * mask when it is doing occlusion detection, so use that |
369 | - * order to fill our occlusion buffer which we'll flip |
370 | - * to nux later |
371 | - */ |
372 | +/* we want to paint underneath other windows here, |
373 | + * so we need to find if this window is actually |
374 | + * stacked on top of one of the nux input windows |
375 | + * and if so paint nux and stop us from painting |
376 | + * other windows or on top of the whole screen */ |
377 | bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib, |
378 | const GLMatrix& matrix, |
379 | const CompRegion& region, |
380 | @@ -2187,7 +2223,7 @@ |
381 | |
382 | std::vector<Window> const& tray_xids = uScreen->panel_controller_->GetTrayXids(); |
383 | if (std::find(tray_xids.begin(), tray_xids.end(), window->id()) != tray_xids.end() && |
384 | - !uScreen->allowWindowPaint) |
385 | + (uScreen->ProhibitedPaintRequestors () & ShellPaintRequestorInterface::WindowPaintRequestor)) |
386 | { |
387 | if (!uScreen->painting_tray_) |
388 | { |
389 | @@ -2196,26 +2232,7 @@ |
390 | } |
391 | } |
392 | |
393 | - return gWindow->glPaint(wAttrib, matrix, region, mask); |
394 | -} |
395 | - |
396 | -/* handle window painting in an opengl context |
397 | - * |
398 | - * we want to paint underneath other windows here, |
399 | - * so we need to find if this window is actually |
400 | - * stacked on top of one of the nux input windows |
401 | - * and if so paint nux and stop us from painting |
402 | - * other windows or on top of the whole screen */ |
403 | -bool UnityWindow::glDraw(const GLMatrix& matrix, |
404 | -#ifndef USE_MODERN_COMPIZ_GL |
405 | - GLFragment::Attrib& attrib, |
406 | -#else |
407 | - const GLWindowPaintAttrib& attrib, |
408 | -#endif |
409 | - const CompRegion& region, |
410 | - unsigned int mask) |
411 | -{ |
412 | - if (uScreen->doShellRepaint && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask) |
413 | + if (uScreen->RepaintPending () && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask) |
414 | { |
415 | guint32 id = window->id(); |
416 | bool maximized = WindowManager::Default()->IsWindowMaximized(id); |
417 | @@ -2231,29 +2248,63 @@ |
418 | } |
419 | } |
420 | |
421 | - if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ()) |
422 | + if (IsNuxWindow ()) |
423 | { |
424 | - std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList(); |
425 | - unsigned int size = xwns.size(); |
426 | - |
427 | - for (CompWindow* w = window; w && uScreen->doShellRepaint; w = w->prev) |
428 | - { |
429 | - auto id = w->id(); |
430 | - |
431 | - for (unsigned int i = 0; i < size; ++i) |
432 | - { |
433 | - if (xwns[i] == id) |
434 | - { |
435 | -#ifdef USE_MODERN_COMPIZ_GL |
436 | - uScreen->paintDisplay(); |
437 | + /* Windows are painted in top-to-bottom order |
438 | + * with occlusion detection on, so we can |
439 | + * find out the top most nux window and paint |
440 | + * there */ |
441 | + if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) |
442 | + { |
443 | + GLWindowPaintAttrib noAlphaAttrib; |
444 | + |
445 | + noAlphaAttrib.opacity = OPAQUE; |
446 | + noAlphaAttrib.brightness = BRIGHT; |
447 | + noAlphaAttrib.saturation = COLOR; |
448 | + |
449 | + bool status = gWindow->glPaint (noAlphaAttrib, |
450 | + matrix, |
451 | + region, |
452 | + PAINT_WINDOW_OCCLUSION_DETECTION_MASK); |
453 | + |
454 | + if (status) |
455 | + uScreen->EnforceRequestor (this); |
456 | + |
457 | + /* We don't want core to take this window |
458 | + * into account when doing occlusion detection |
459 | + * however */ |
460 | + return false; |
461 | + } |
462 | + /* Don't care about "fake" paints */ |
463 | + else if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK) |
464 | + { |
465 | + return false; |
466 | + } |
467 | + else |
468 | + { |
469 | + uScreen->Paint (this, uScreen); |
470 | + |
471 | + /* Don't paint nux windows on the real paint pass */ |
472 | + return false; |
473 | + } |
474 | + } |
475 | + |
476 | + return gWindow->glPaint(wAttrib, matrix, region, mask); |
477 | +} |
478 | + |
479 | +/* handle window painting in an opengl context |
480 | + */ |
481 | +bool UnityWindow::glDraw(const GLMatrix& matrix, |
482 | +#ifndef USE_MODERN_COMPIZ_GL |
483 | + GLFragment::Attrib& attrib, |
484 | #else |
485 | - uScreen->paintDisplay(region, matrix, mask); |
486 | + const GLWindowPaintAttrib& attrib, |
487 | #endif |
488 | - break; |
489 | - } |
490 | - } |
491 | - } |
492 | - } |
493 | + const CompRegion& region, |
494 | + unsigned int mask) |
495 | +{ |
496 | + if (IsNuxWindow ()) |
497 | + return false; |
498 | |
499 | if (window->type() == CompWindowTypeDesktopMask) |
500 | uScreen->setPanelShadowMatrix(matrix); |
501 | @@ -2272,7 +2323,6 @@ |
502 | uScreen->paintPanelShadow(matrix); |
503 | } |
504 | |
505 | - |
506 | return ret; |
507 | } |
508 | |
509 | @@ -2747,8 +2797,8 @@ |
510 | #ifndef USE_MODERN_COMPIZ_GL |
511 | if (GL::fbo) |
512 | { |
513 | - uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry)); |
514 | - uScreen->_fbo->onScreenSizeChanged (geometry); |
515 | + uScreen->fbo_ = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry)); |
516 | + uScreen->fbo_->onScreenSizeChanged (geometry); |
517 | } |
518 | #endif |
519 | |
520 | @@ -2914,6 +2964,18 @@ |
521 | hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button")); |
522 | } |
523 | |
524 | +bool |
525 | +UnityWindow::IsNuxWindow () |
526 | +{ |
527 | + return is_nux_window_; |
528 | +} |
529 | + |
530 | +unsigned int |
531 | +UnityWindow::GetPaintRequestorType () |
532 | +{ |
533 | + return ShellPaintRequestorInterface::WindowPaintRequestor; |
534 | +} |
535 | + |
536 | /* Window init */ |
537 | UnityWindow::UnityWindow(CompWindow* window) |
538 | : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window) |
539 | @@ -2922,10 +2984,16 @@ |
540 | , gWindow(GLWindow::get(window)) |
541 | , mMinimizeHandler() |
542 | , mShowdesktopHandler(nullptr) |
543 | + , is_nux_window_ (false) |
544 | { |
545 | WindowInterface::setHandler(window); |
546 | GLWindowInterface::setHandler(gWindow); |
547 | |
548 | + std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList(); |
549 | + for (unsigned int i = 0; i < xwns.size(); i++) |
550 | + if (xwns[i] == window->id ()) |
551 | + is_nux_window_ = true; |
552 | + |
553 | if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () && |
554 | window->mapNum ()) |
555 | { |
556 | |
557 | === modified file 'plugins/unityshell/src/unityshell.h' |
558 | --- plugins/unityshell/src/unityshell.h 2012-05-30 18:43:17 +0000 |
559 | +++ plugins/unityshell/src/unityshell.h 2012-06-14 09:04:28 +0000 |
560 | @@ -52,6 +52,7 @@ |
561 | #include "UBusWrapper.h" |
562 | #include "UnityshellPrivate.h" |
563 | #include "UnityShowdesktopHandler.h" |
564 | +#include "ShellPaintSchedule.h" |
565 | #ifndef USE_MODERN_COMPIZ_GL |
566 | #include "ScreenEffectFramebufferObject.h" |
567 | #endif |
568 | @@ -68,6 +69,10 @@ |
569 | |
570 | /* base screen class */ |
571 | class UnityScreen : |
572 | + public FBOBindingQueryInterface, |
573 | + public ShellPaintDispatchInterface, |
574 | + public ShellPaintRequestorInterface, |
575 | + public ShellPaintInterface, |
576 | public unity::debug::Introspectable, |
577 | public sigc::trackable, |
578 | public ScreenInterface, |
579 | @@ -92,11 +97,8 @@ |
580 | void nuxEpilogue(); |
581 | |
582 | /* nux draw wrapper */ |
583 | -#ifdef USE_MODERN_COMPIZ_GL |
584 | - void paintDisplay(); |
585 | -#else |
586 | - void paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask); |
587 | -#endif |
588 | + bool PaintBackingFBO (CompOutput *output); |
589 | + void PaintDisplay (FBOBindingQueryInterface *); |
590 | void paintPanelShadow(const GLMatrix& matrix); |
591 | void setPanelShadowMatrix(const GLMatrix& matrix); |
592 | |
593 | @@ -132,9 +134,6 @@ |
594 | CompOutput*, |
595 | unsigned int); |
596 | |
597 | - /* Pop our InputOutput windows from the paint list */ |
598 | - const CompWindowList& getWindowPaintList(); |
599 | - |
600 | /* handle X11 events */ |
601 | void handleEvent(XEvent*); |
602 | |
603 | @@ -188,8 +187,6 @@ |
604 | void NeedsRelayout(); |
605 | void ScheduleRelayout(guint timeout); |
606 | |
607 | - bool forcePaintOnTop (); |
608 | - |
609 | protected: |
610 | std::string GetName() const; |
611 | void AddProperties(GVariantBuilder* builder); |
612 | @@ -231,6 +228,20 @@ |
613 | |
614 | void OnPanelStyleChanged(); |
615 | |
616 | + bool WasBound (); |
617 | + unsigned int GetPaintRequestorType (); |
618 | + unsigned int GetProhibitedPaintMasks (); |
619 | + |
620 | + bool Paint (ShellPaintRequestorInterface *, |
621 | + FBOBindingQueryInterface *); |
622 | + bool EnforceRequestor (ShellPaintRequestorInterface *); |
623 | + void ClearRequestorEnforcement (); |
624 | + unsigned int ProhibitedPaintRequestors (); |
625 | + void RequireShellRepaint (); |
626 | + bool RepaintPending (); |
627 | + |
628 | + ShellPaintDispatch paint_dispatch_; |
629 | + |
630 | Settings dash_settings_; |
631 | dash::Style dash_style_; |
632 | panel::Style panel_style_; |
633 | @@ -270,12 +281,9 @@ |
634 | GLTexture::List _shadow_texture; |
635 | |
636 | /* handle paint order */ |
637 | - bool doShellRepaint; |
638 | - bool allowWindowPaint; |
639 | bool damaged; |
640 | bool _key_nav_mode_requested; |
641 | CompOutput* _last_output; |
642 | - CompWindowList _withRemovedNuxWindows; |
643 | |
644 | nux::Property<nux::Geometry> primary_monitor_; |
645 | |
646 | @@ -284,7 +292,7 @@ |
647 | #ifdef USE_MODERN_COMPIZ_GL |
648 | ::GLFramebufferObject *oldFbo; |
649 | #else |
650 | - ScreenEffectFramebufferObject::Ptr _fbo; |
651 | + ScreenEffectFramebufferObject::Ptr fbo_; |
652 | GLuint _active_fbo; |
653 | #endif |
654 | |
655 | @@ -311,15 +319,27 @@ |
656 | |
657 | UBusManager ubus_manager_; |
658 | glib::SourceManager sources_; |
659 | + unsigned int no_paint_allowed_mask_; |
660 | |
661 | friend class UnityWindow; |
662 | }; |
663 | |
664 | +class NuxBridgeWindowInterface |
665 | +{ |
666 | +public: |
667 | + |
668 | + virtual ~NuxBridgeWindowInterface () {}; |
669 | + |
670 | + virtual bool IsNuxWindow () = 0; |
671 | +}; |
672 | + |
673 | class UnityWindow : |
674 | public WindowInterface, |
675 | public GLWindowInterface, |
676 | public ShowdesktopHandlerWindowInterface, |
677 | public compiz::WindowInputRemoverLockAcquireInterface, |
678 | + public NuxBridgeWindowInterface, |
679 | + public ShellPaintRequestorInterface, |
680 | public BaseSwitchWindow, |
681 | public PluginClassHandler <UnityWindow, CompWindow> |
682 | { |
683 | @@ -417,7 +437,12 @@ |
684 | |
685 | compiz::WindowInputRemoverLock::Ptr GetInputRemover (); |
686 | |
687 | + bool IsNuxWindow (); |
688 | + unsigned int GetPaintRequestorType (); |
689 | + |
690 | compiz::WindowInputRemoverLock::Weak input_remover_; |
691 | + |
692 | + bool is_nux_window_; |
693 | glib::Source::UniquePtr focus_desktop_timeout_; |
694 | }; |
695 | |
696 | |
697 | === modified file 'tests/CMakeLists.txt' |
698 | --- tests/CMakeLists.txt 2012-06-12 08:23:23 +0000 |
699 | +++ tests/CMakeLists.txt 2012-06-14 09:04:28 +0000 |
700 | @@ -150,6 +150,7 @@ |
701 | test_unityshell_private.cpp |
702 | test_showdesktop_handler.cpp |
703 | test_hud_private.cpp |
704 | + test_shell_paint_schedule.cpp |
705 | ${CMAKE_SOURCE_DIR}/launcher/AbstractLauncherIcon.cpp |
706 | ${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp |
707 | ${UNITY_SRC}/DebugDBusInterface.cpp |
708 | @@ -162,6 +163,7 @@ |
709 | ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp |
710 | ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutModel.cpp |
711 | ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutHintPrivate.cpp |
712 | + ${CMAKE_SOURCE_DIR}/unity-shared/ShellPaintSchedule.cpp |
713 | ${CMAKE_SOURCE_DIR}/unity-shared/Introspectable.cpp |
714 | ${CMAKE_SOURCE_DIR}/unity-shared/TextureCache.cpp |
715 | ${CMAKE_SOURCE_DIR}/unity-shared/Timer.cpp |
716 | |
717 | === added file 'tests/test_shell_paint_schedule.cpp' |
718 | --- tests/test_shell_paint_schedule.cpp 1970-01-01 00:00:00 +0000 |
719 | +++ tests/test_shell_paint_schedule.cpp 2012-06-14 09:04:28 +0000 |
720 | @@ -0,0 +1,284 @@ |
721 | +/* |
722 | + * Copyright 2012 Canonical Ltd. |
723 | + * |
724 | + * This program is free software: you can redistribute it and/or modify it |
725 | + * under the terms of the GNU General Public License version 3, as published |
726 | + * by the Free Software Foundation. |
727 | + * |
728 | + * This program is distributed in the hope that it will be useful, but |
729 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
730 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
731 | + * PURPOSE. See the GNU General Public License for more details. |
732 | + * |
733 | + * You should have received a copy of the GNU General Public License |
734 | + * version 3 along with this program. If not, see |
735 | + * <http://www.gnu.org/licenses/> |
736 | + * |
737 | + * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com> |
738 | + * |
739 | + */ |
740 | + |
741 | +#include <gtest/gtest.h> |
742 | +#include <gmock/gmock.h> |
743 | + |
744 | +using ::testing::StrictMock; |
745 | +using ::testing::_; |
746 | +using ::testing::AtLeast; |
747 | +using ::testing::Return; |
748 | + |
749 | +#include "ShellPaintSchedule.h" |
750 | + |
751 | +using namespace unity; |
752 | + |
753 | +class MockShellPaintRequestor : |
754 | + public ShellPaintRequestorInterface |
755 | +{ |
756 | +public: |
757 | + |
758 | + MOCK_METHOD0 (GetPaintRequestorType, unsigned int ()); |
759 | + |
760 | +}; |
761 | + |
762 | +class MockFBOBindingQuery : |
763 | + public FBOBindingQueryInterface |
764 | +{ |
765 | +public: |
766 | + |
767 | + MOCK_METHOD0 (WasBound, bool ()); |
768 | +}; |
769 | + |
770 | +class MockShellPaint : |
771 | + public ShellPaintInterface |
772 | +{ |
773 | +public: |
774 | + |
775 | + MOCK_METHOD1 (PaintDisplay, void (FBOBindingQueryInterface *)); |
776 | +}; |
777 | + |
778 | +class MockShellPaintDispatch |
779 | +{ |
780 | +public: |
781 | + |
782 | + MOCK_METHOD2 (Paint, bool (ShellPaintRequestorInterface *, FBOBindingQueryInterface *)); |
783 | + MOCK_METHOD1 (EnforceRequestor, void (ShellPaintRequestorInterface *)); |
784 | + MOCK_METHOD0 (ClearRequestorEnforcement, void ()); |
785 | + MOCK_METHOD0 (ProhibitedPaintRequestors, unsigned int ()); |
786 | + MOCK_METHOD0 (RequireShellRepaint, void ()); |
787 | + MOCK_METHOD0 (RepaintPending, bool ()); |
788 | +}; |
789 | + |
790 | +class TestShellPaintSchedule : |
791 | + public ::testing::Test |
792 | +{ |
793 | +}; |
794 | + |
795 | +TEST(TestShellPaintSchedule, NoPaintWhereNotRequired) |
796 | +{ |
797 | + StrictMock <MockShellPaint> p; |
798 | + MockShellPaintRequestor r; |
799 | + MockFBOBindingQuery q; |
800 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
801 | + |
802 | + ShellPaintDispatch dispatch (&p, f); |
803 | + |
804 | + dispatch.Paint (&r, &q); |
805 | +} |
806 | + |
807 | +TEST(TestShellPaintSchedule, PaintWhereRequired) |
808 | +{ |
809 | + StrictMock <MockShellPaint> p; |
810 | + MockShellPaintRequestor r; |
811 | + MockFBOBindingQuery q; |
812 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
813 | + |
814 | + ShellPaintDispatch dispatch (&p, f); |
815 | + |
816 | + dispatch.RequireShellRepaint (); |
817 | + |
818 | + EXPECT_CALL (r, GetPaintRequestorType ()); |
819 | + EXPECT_CALL (p, PaintDisplay (&q)); |
820 | + |
821 | + dispatch.Paint (&r, &q); |
822 | +} |
823 | + |
824 | +TEST(TestShellPaintSchedule, NoPaintTwice) |
825 | +{ |
826 | + StrictMock <MockShellPaint> p; |
827 | + MockShellPaintRequestor r; |
828 | + MockFBOBindingQuery q; |
829 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
830 | + |
831 | + ShellPaintDispatch dispatch (&p, f); |
832 | + |
833 | + dispatch.RequireShellRepaint (); |
834 | + |
835 | + EXPECT_CALL (r, GetPaintRequestorType ()); |
836 | + EXPECT_CALL (p, PaintDisplay (&q)); |
837 | + |
838 | + dispatch.Paint (&r, &q); |
839 | + dispatch.Paint (&r, &q); |
840 | +} |
841 | + |
842 | +TEST(TestShellPaintSchedule, NoWindowPaintButScreenPaint) |
843 | +{ |
844 | + StrictMock <MockShellPaint> p; |
845 | + MockShellPaintRequestor r; |
846 | + MockFBOBindingQuery q; |
847 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return ShellPaintRequestorInterface::WindowPaintRequestor; } ); |
848 | + |
849 | + ShellPaintDispatch dispatch (&p, f); |
850 | + |
851 | + dispatch.RequireShellRepaint (); |
852 | + |
853 | + EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
854 | + |
855 | + dispatch.Paint (&r, &q); |
856 | + |
857 | + EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::ScreenPaintRequestor)); |
858 | + EXPECT_CALL (p, PaintDisplay (&q)); |
859 | + |
860 | + dispatch.Paint (&r, &q); |
861 | +} |
862 | + |
863 | +TEST(TestShellPaintSchedule, NoScreenPaintButWindowPaint) |
864 | +{ |
865 | + StrictMock <MockShellPaint> p; |
866 | + MockShellPaintRequestor r; |
867 | + MockFBOBindingQuery q; |
868 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return ShellPaintRequestorInterface::ScreenPaintRequestor; } ); |
869 | + |
870 | + ShellPaintDispatch dispatch (&p, f); |
871 | + |
872 | + dispatch.RequireShellRepaint (); |
873 | + |
874 | + EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::ScreenPaintRequestor)); |
875 | + |
876 | + dispatch.Paint (&r, &q); |
877 | + |
878 | + EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
879 | + EXPECT_CALL (p, PaintDisplay (&q)); |
880 | + |
881 | + dispatch.Paint (&r, &q); |
882 | +} |
883 | + |
884 | +TEST(TestShellPaintSchedule, TopRequestorOnlyPaints) |
885 | +{ |
886 | + StrictMock <MockShellPaint> p; |
887 | + MockShellPaintRequestor r_w1, r_w2; |
888 | + MockFBOBindingQuery q; |
889 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
890 | + |
891 | + ShellPaintDispatch dispatch (&p, f); |
892 | + |
893 | + dispatch.RequireShellRepaint (); |
894 | + |
895 | + dispatch.ClearRequestorEnforcement (); |
896 | + dispatch.EnforceRequestor (&r_w2); |
897 | + |
898 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
899 | + EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
900 | + |
901 | + dispatch.Paint (&r_w1, &q); |
902 | + |
903 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
904 | + EXPECT_CALL (p, PaintDisplay (&q)); |
905 | + |
906 | + dispatch.Paint (&r_w2, &q); |
907 | +} |
908 | + |
909 | +TEST(TestShellPaintSchedule, SuperveningRequestorOfOtherTypePaints) |
910 | +{ |
911 | + StrictMock <MockShellPaint> p; |
912 | + MockShellPaintRequestor r_w1, r_w2, r_s1; |
913 | + MockFBOBindingQuery q; |
914 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
915 | + |
916 | + ShellPaintDispatch dispatch (&p, f); |
917 | + |
918 | + dispatch.RequireShellRepaint (); |
919 | + |
920 | + dispatch.ClearRequestorEnforcement (); |
921 | + dispatch.EnforceRequestor (&r_w2); |
922 | + |
923 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
924 | + EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
925 | + |
926 | + dispatch.Paint (&r_w1, &q); |
927 | + |
928 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
929 | + EXPECT_CALL (r_s1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::ScreenPaintRequestor)); |
930 | + |
931 | + EXPECT_CALL (p, PaintDisplay (&q)); |
932 | + |
933 | + dispatch.Paint (&r_s1, &q); |
934 | + |
935 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
936 | + |
937 | + dispatch.Paint (&r_w2, &q); |
938 | +} |
939 | + |
940 | +TEST(TestShellPaintSchedule, DoubleEnforcementHasNoEffect) |
941 | +{ |
942 | + StrictMock <MockShellPaint> p; |
943 | + MockShellPaintRequestor r_w1, r_w2; |
944 | + MockFBOBindingQuery q; |
945 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
946 | + |
947 | + ShellPaintDispatch dispatch (&p, f); |
948 | + |
949 | + dispatch.RequireShellRepaint (); |
950 | + |
951 | + dispatch.ClearRequestorEnforcement (); |
952 | + dispatch.EnforceRequestor (&r_w2); |
953 | + dispatch.EnforceRequestor (&r_w1); |
954 | + |
955 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
956 | + EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
957 | + |
958 | + dispatch.Paint (&r_w1, &q); |
959 | + |
960 | + EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
961 | + EXPECT_CALL (p, PaintDisplay (&q)); |
962 | + |
963 | + dispatch.Paint (&r_w2, &q); |
964 | +} |
965 | + |
966 | +TEST(TestShellPaintSchedule, GetPendingRepaint) |
967 | +{ |
968 | + StrictMock <MockShellPaint> p; |
969 | + MockShellPaintRequestor r; |
970 | + MockFBOBindingQuery q; |
971 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } ); |
972 | + |
973 | + ShellPaintDispatch dispatch (&p, f); |
974 | + |
975 | + EXPECT_FALSE (dispatch.RepaintPending ()); |
976 | + |
977 | + dispatch.RequireShellRepaint (); |
978 | + |
979 | + EXPECT_TRUE (dispatch.RepaintPending ()); |
980 | + |
981 | + EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor)); |
982 | + EXPECT_CALL (p, PaintDisplay (&q)); |
983 | + |
984 | + dispatch.Paint (&r, &q); |
985 | + |
986 | + EXPECT_FALSE (dispatch.RepaintPending ()); |
987 | +} |
988 | + |
989 | +TEST(TestShellPaintSchedule, GetProhibitedPaintMasks) |
990 | +{ |
991 | + StrictMock <MockShellPaint> p; |
992 | + MockShellPaintRequestor r; |
993 | + MockFBOBindingQuery q; |
994 | + unsigned int prohibited_paint_mask = 0; |
995 | + ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([&]() -> unsigned int { return prohibited_paint_mask; } ); |
996 | + |
997 | + ShellPaintDispatch dispatch (&p, f); |
998 | + |
999 | + EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ()); |
1000 | + prohibited_paint_mask = ShellPaintRequestorInterface::WindowPaintRequestor; |
1001 | + EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ()); |
1002 | + prohibited_paint_mask = ShellPaintRequestorInterface::ScreenPaintRequestor; |
1003 | + EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ()); |
1004 | +} |
1005 | |
1006 | === modified file 'unity-shared/CMakeLists.txt' |
1007 | --- unity-shared/CMakeLists.txt 2012-05-22 10:15:47 +0000 |
1008 | +++ unity-shared/CMakeLists.txt 2012-06-14 09:04:28 +0000 |
1009 | @@ -47,6 +47,7 @@ |
1010 | PanelStyle.cpp |
1011 | SearchBar.cpp |
1012 | SearchBarSpinner.cpp |
1013 | + ShellPaintSchedule.cpp |
1014 | StaticCairoText.cpp |
1015 | TextureCache.cpp |
1016 | Timer.cpp |
1017 | |
1018 | === added file 'unity-shared/ShellPaintSchedule.cpp' |
1019 | --- unity-shared/ShellPaintSchedule.cpp 1970-01-01 00:00:00 +0000 |
1020 | +++ unity-shared/ShellPaintSchedule.cpp 2012-06-14 09:04:28 +0000 |
1021 | @@ -0,0 +1,91 @@ |
1022 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1023 | +/* |
1024 | + * Copyright (C) 2012 Canonical Ltd |
1025 | + * |
1026 | + * This program is free software: you can redistribute it and/or modify |
1027 | + * it under the terms of the GNU General Public License version 3 as |
1028 | + * published by the Free Software Foundation. |
1029 | + * |
1030 | + * This program is distributed in the hope that it will be useful, |
1031 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1032 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1033 | + * GNU General Public License for more details. |
1034 | + * |
1035 | + * You should have received a copy of the GNU General Public License |
1036 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1037 | + * |
1038 | + * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com> |
1039 | + */ |
1040 | + |
1041 | +#include "ShellPaintSchedule.h" |
1042 | + |
1043 | +namespace unity |
1044 | +{ |
1045 | + |
1046 | +ShellPaintDispatch::ShellPaintDispatch (ShellPaintInterface *paint_interface, |
1047 | + const GetProhibitedPaintMasksFunc &prohibited_func) : |
1048 | + shell_repaint_required_ (false), |
1049 | + top_requestor_ (nullptr), |
1050 | + prohibited_paint_masks_func_ (prohibited_func), |
1051 | + paint_interface_ (paint_interface) |
1052 | +{ |
1053 | +} |
1054 | + |
1055 | +bool |
1056 | +ShellPaintDispatch::Paint (ShellPaintRequestorInterface *requestor, |
1057 | + FBOBindingQueryInterface *fbo_query) |
1058 | +{ |
1059 | + if (!shell_repaint_required_) |
1060 | + return false; |
1061 | + |
1062 | + if (prohibited_paint_masks_func_ () & requestor->GetPaintRequestorType ()) |
1063 | + return false; |
1064 | + |
1065 | + if (top_requestor_) |
1066 | + if ((top_requestor_->GetPaintRequestorType () & |
1067 | + requestor->GetPaintRequestorType ()) && top_requestor_ != requestor) |
1068 | + return false; |
1069 | + |
1070 | + paint_interface_->PaintDisplay (fbo_query); |
1071 | + |
1072 | + shell_repaint_required_ = false; |
1073 | + |
1074 | + return true; |
1075 | +} |
1076 | + |
1077 | +bool |
1078 | +ShellPaintDispatch::EnforceRequestor (ShellPaintRequestorInterface *requestor) |
1079 | +{ |
1080 | + if (top_requestor_) |
1081 | + return false; |
1082 | + |
1083 | + top_requestor_ = requestor; |
1084 | + |
1085 | + return true; |
1086 | +} |
1087 | + |
1088 | +void |
1089 | +ShellPaintDispatch::ClearRequestorEnforcement () |
1090 | +{ |
1091 | + top_requestor_ = nullptr; |
1092 | +} |
1093 | + |
1094 | +unsigned int |
1095 | +ShellPaintDispatch::ProhibitedPaintRequestors () |
1096 | +{ |
1097 | + return prohibited_paint_masks_func_ (); |
1098 | +} |
1099 | + |
1100 | +void |
1101 | +ShellPaintDispatch::RequireShellRepaint () |
1102 | +{ |
1103 | + shell_repaint_required_ = true; |
1104 | +} |
1105 | + |
1106 | +bool |
1107 | +ShellPaintDispatch::RepaintPending () |
1108 | +{ |
1109 | + return shell_repaint_required_; |
1110 | +} |
1111 | + |
1112 | +} |
1113 | |
1114 | === added file 'unity-shared/ShellPaintSchedule.h' |
1115 | --- unity-shared/ShellPaintSchedule.h 1970-01-01 00:00:00 +0000 |
1116 | +++ unity-shared/ShellPaintSchedule.h 2012-06-14 09:04:28 +0000 |
1117 | @@ -0,0 +1,104 @@ |
1118 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1119 | +/* |
1120 | + * Copyright (C) 2012 Canonical Ltd |
1121 | + * |
1122 | + * This program is free software: you can redistribute it and/or modify |
1123 | + * it under the terms of the GNU General Public License version 3 as |
1124 | + * published by the Free Software Foundation. |
1125 | + * |
1126 | + * This program is distributed in the hope that it will be useful, |
1127 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1128 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1129 | + * GNU General Public License for more details. |
1130 | + * |
1131 | + * You should have received a copy of the GNU General Public License |
1132 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1133 | + * |
1134 | + * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com> |
1135 | + */ |
1136 | + |
1137 | +#ifndef UNITY_PAINT_SCHEDULE_H |
1138 | +#define UNITY_PAINT_SCHEDULE_H |
1139 | + |
1140 | +#include <boost/bind.hpp> |
1141 | +#include <boost/function.hpp> |
1142 | + |
1143 | +namespace unity |
1144 | +{ |
1145 | + |
1146 | +class ShellPaintRequestorInterface |
1147 | +{ |
1148 | +public: |
1149 | + |
1150 | + |
1151 | + static const unsigned int WindowPaintRequestor = (1 << 0); |
1152 | + static const unsigned int ScreenPaintRequestor = (1 << 1); |
1153 | + |
1154 | + virtual ~ShellPaintRequestorInterface () {} |
1155 | + |
1156 | + virtual unsigned int GetPaintRequestorType () = 0; |
1157 | +}; |
1158 | + |
1159 | +class FBOBindingQueryInterface |
1160 | +{ |
1161 | +public: |
1162 | + |
1163 | + virtual ~FBOBindingQueryInterface () {} |
1164 | + virtual bool WasBound () = 0; |
1165 | +}; |
1166 | + |
1167 | +class ShellPaintInterface |
1168 | +{ |
1169 | +public: |
1170 | + |
1171 | + virtual ~ShellPaintInterface () {}; |
1172 | + |
1173 | + virtual void PaintDisplay (FBOBindingQueryInterface *) = 0; |
1174 | +}; |
1175 | + |
1176 | +class ShellPaintDispatchInterface |
1177 | +{ |
1178 | +public: |
1179 | + |
1180 | + virtual ~ShellPaintDispatchInterface () {} |
1181 | + |
1182 | + virtual bool Paint (ShellPaintRequestorInterface *, |
1183 | + FBOBindingQueryInterface *) = 0; |
1184 | + virtual bool EnforceRequestor (ShellPaintRequestorInterface *) = 0; |
1185 | + virtual void ClearRequestorEnforcement () = 0; |
1186 | + virtual unsigned int ProhibitedPaintRequestors () = 0; |
1187 | + virtual void RequireShellRepaint () = 0; |
1188 | + virtual bool RepaintPending () = 0; |
1189 | + |
1190 | +}; |
1191 | + |
1192 | +class ShellPaintDispatch : |
1193 | + public ShellPaintDispatchInterface |
1194 | +{ |
1195 | +public: |
1196 | + |
1197 | + typedef boost::function <unsigned int ()> GetProhibitedPaintMasksFunc; |
1198 | + |
1199 | + ShellPaintDispatch (ShellPaintInterface * paint_interface, |
1200 | + const GetProhibitedPaintMasksFunc &func); |
1201 | + |
1202 | + bool Paint (ShellPaintRequestorInterface *, |
1203 | + FBOBindingQueryInterface *); |
1204 | + bool EnforceRequestor (ShellPaintRequestorInterface *); |
1205 | + void ClearRequestorEnforcement (); |
1206 | + unsigned int ProhibitedPaintRequestors (); |
1207 | + void RequireShellRepaint (); |
1208 | + bool RepaintPending (); |
1209 | + |
1210 | + |
1211 | +protected: |
1212 | + |
1213 | + bool shell_repaint_required_; |
1214 | + ShellPaintRequestorInterface *top_requestor_; |
1215 | + GetProhibitedPaintMasksFunc prohibited_paint_masks_func_; |
1216 | + ShellPaintInterface *paint_interface_; |
1217 | +}; |
1218 | + |
1219 | +} |
1220 | + |
1221 | +#endif |
Bump?
I'd like to see this go in, because it should reduce lots of list copying within unity and also lots of unecessary list traversal, which should represent a nice speed boost. In addition, its far simpler in its implementation and far less bug prone.
I'm sure testing is probably an issue. I'll have another quick look at the code and see if I can think of a way to get it under test.