Merge lp:~smspillaz/unity/unity.less-paint-insanity into lp:unity

Proposed by Sam Spilsbury
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
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.

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?

To post a comment you must log in.
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

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.

Revision history for this message
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?

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

indentation fixed ... will add tests when I have time.

Revision history for this message
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.

review: Approve
Revision history for this message
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.

Revision history for this message
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.

review: Needs Fixing
2374. By Sam Spilsbury

Merge lp:unity

2375. By Sam Spilsbury

Merge lp:~vanvugt/unity/fix-1010348

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 FBOBindingQueryInterface

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 FBOBindingQueryInterface

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plugins/unityshell/src/ScreenEffectFramebufferObject.cpp'
--- plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-05-28 03:19:35 +0000
+++ plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-06-14 09:04:28 +0000
@@ -76,7 +76,6 @@
76 mScreenSize = screenSize;76 mScreenSize = screenSize;
77}77}
7878
79
80void unity::ScreenEffectFramebufferObject::unbind ()79void unity::ScreenEffectFramebufferObject::unbind ()
81{80{
82 if (!mBoundCnt)81 if (!mBoundCnt)
@@ -92,6 +91,8 @@
92 /* Matches the viewport set we did in ::bind () */91 /* Matches the viewport set we did in ::bind () */
93 glPopAttrib ();92 glPopAttrib ();
9493
94 successful_bind_ = true;
95
95}96}
9697
97bool unity::ScreenEffectFramebufferObject::status ()98bool unity::ScreenEffectFramebufferObject::status ()
@@ -106,6 +107,8 @@
106 * Because binding has a severe impact on graphics performance and we107 * Because binding has a severe impact on graphics performance and we
107 * can't afford to do it every frame. (LP: #861061) (LP: #987304)108 * can't afford to do it every frame. (LP: #861061) (LP: #987304)
108 */109 */
110 successful_bind_ = false;
111
109 if (!BackgroundEffectHelper::HasDirtyHelpers())112 if (!BackgroundEffectHelper::HasDirtyHelpers())
110 return;113 return;
111114
@@ -212,6 +215,11 @@
212 mBoundCnt++;215 mBoundCnt++;
213}216}
214217
218bool
219unity::ScreenEffectFramebufferObject::NewContentsValid ()
220{
221 return successful_bind_;
222}
215223
216unity::ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom)224unity::ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom)
217 : getProcAddressGLX (p)225 : getProcAddressGLX (p)
@@ -220,6 +228,7 @@
220 , mGeometry (geom)228 , mGeometry (geom)
221 , mBoundCnt (0)229 , mBoundCnt (0)
222 , mScreenSize (geom)230 , mScreenSize (geom)
231 , successful_bind_ (false)
223{232{
224 activeTexture = (GLActiveTextureProc) (*getProcAddressGLX) ((GLubyte *) "glActiveTexture");233 activeTexture = (GLActiveTextureProc) (*getProcAddressGLX) ((GLubyte *) "glActiveTexture");
225 genFramebuffers = (GLGenFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glGenFramebuffersEXT");234 genFramebuffers = (GLGenFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glGenFramebuffersEXT");
226235
=== modified file 'plugins/unityshell/src/ScreenEffectFramebufferObject.h'
--- plugins/unityshell/src/ScreenEffectFramebufferObject.h 2012-04-06 10:23:49 +0000
+++ plugins/unityshell/src/ScreenEffectFramebufferObject.h 2012-06-14 09:04:28 +0000
@@ -49,6 +49,10 @@
49 49
50 void onScreenSizeChanged (const nux::Geometry &screenSize);50 void onScreenSizeChanged (const nux::Geometry &screenSize);
5151
52 /* Returns true if the fbo was bound, painted into and unbound
53 * successfully */
54 bool NewContentsValid ();
55
52private:56private:
5357
54 FuncPtr getProcAddr (const std::string &);58 FuncPtr getProcAddr (const std::string &);
@@ -82,6 +86,8 @@
82 unsigned int mBoundCnt;86 unsigned int mBoundCnt;
83 87
84 nux::Geometry mScreenSize;88 nux::Geometry mScreenSize;
89
90 bool successful_bind_;
85};91};
86} // namespace unity92} // namespace unity
8793
8894
=== modified file 'plugins/unityshell/src/unityshell.cpp'
--- plugins/unityshell/src/unityshell.cpp 2012-06-13 03:54:37 +0000
+++ plugins/unityshell/src/unityshell.cpp 2012-06-14 09:04:28 +0000
@@ -110,6 +110,8 @@
110 , screen(screen)110 , screen(screen)
111 , cScreen(CompositeScreen::get(screen))111 , cScreen(CompositeScreen::get(screen))
112 , gScreen(GLScreen::get(screen))112 , gScreen(GLScreen::get(screen))
113 , paint_dispatch_ (this,
114 boost::bind (&UnityScreen::GetProhibitedPaintMasks, this))
113 , debugger_(this)115 , debugger_(this)
114 , enable_shortcut_overlay_(true)116 , enable_shortcut_overlay_(true)
115 , gesture_engine_(screen)117 , gesture_engine_(screen)
@@ -117,8 +119,6 @@
117 , _in_paint(false)119 , _in_paint(false)
118 , super_keypressed_(false)120 , super_keypressed_(false)
119 , newFocusedWindow(nullptr)121 , newFocusedWindow(nullptr)
120 , doShellRepaint(false)
121 , allowWindowPaint(false)
122 , damaged(false)122 , damaged(false)
123 , _key_nav_mode_requested(false)123 , _key_nav_mode_requested(false)
124 , _last_output(nullptr)124 , _last_output(nullptr)
@@ -263,8 +263,8 @@
263 if (GL::fbo)263 if (GL::fbo)
264 {264 {
265 nux::Geometry geometry (0, 0, screen->width (), screen->height ());265 nux::Geometry geometry (0, 0, screen->width (), screen->height ());
266 uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));266 uScreen->fbo_ = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
267 uScreen->_fbo->onScreenSizeChanged (geometry);267 uScreen->fbo_->onScreenSizeChanged (geometry);
268 }268 }
269#endif269#endif
270270
@@ -734,16 +734,52 @@
734 panel_texture_has_changed_ = true;734 panel_texture_has_changed_ = true;
735}735}
736736
737#ifdef USE_MODERN_COMPIZ_GL737bool
738void UnityScreen::paintDisplay()738UnityScreen::WasBound ()
739{
740#ifndef USE_MODERN_COMPIZ_GL
741 return fbo_->NewContentsValid ();
739#else742#else
740void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask)743 return true;
741#endif744#endif
745}
746
747unsigned int
748UnityScreen::GetPaintRequestorType ()
749{
750 return ShellPaintRequestorInterface::ScreenPaintRequestor;
751}
752
753bool UnityScreen::PaintBackingFBO (CompOutput *output)
754{
755#ifndef USE_MODERN_COMPIZ_GL
756 fbo_->unbind ();
757 if (fbo_->NewContentsValid ())
758 {
759 GLMatrix sTransform;
760 sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
761 glPushMatrix ();
762 glLoadMatrixf (sTransform.getMatrix ());
763 fbo_->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
764 glPopMatrix ();
765
766 return true;
767 }
768#endif
769 return false;
770}
771
772void UnityScreen::PaintDisplay (FBOBindingQueryInterface *fbo_query)
742{773{
743 CompOutput *output = _last_output;774 CompOutput *output = _last_output;
744775
776 PaintBackingFBO (output);
777
745#ifndef USE_MODERN_COMPIZ_GL778#ifndef USE_MODERN_COMPIZ_GL
746 bool was_bound = _fbo->bound ();779 bool was_bound = fbo_query->WasBound ();
780#else
781 bool was_bound = true;
782#endif
747783
748 if (nux::GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath())784 if (nux::GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath())
749 {785 {
@@ -779,28 +815,18 @@
779 }815 }
780 }816 }
781817
782 _fbo->unbind ();
783
784 /* Draw the bit of the relevant framebuffer for each output */818 /* Draw the bit of the relevant framebuffer for each output */
785819
786 if (was_bound)820 GLuint fbo_texture_name = 0;
787 {821#ifndef USE_MODERN_COMPIZ_GL
788 GLMatrix sTransform;822 fbo_texture_name = fbo_->texture();
789 sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);823#else
790 glPushMatrix ();824 fbo_texture_name = gScreen->fbo ()->tex ()->name ();
791 glLoadMatrixf (sTransform.getMatrix ());825#endif
792 _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
793 glPopMatrix ();
794 }
795826
796 nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture =827 nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture =
797 nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),828 nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(fbo_texture_name,
798 screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);829 screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
799#else
800 nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
801 nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (),
802 output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
803#endif
804830
805 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;831 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
806832
@@ -823,7 +849,7 @@
823849
824 for (Window tray_xid : panel_controller_->GetTrayXids())850 for (Window tray_xid : panel_controller_->GetTrayXids())
825 {851 {
826 if (tray_xid && !allowWindowPaint)852 if (tray_xid && (no_paint_allowed_mask_ & ShellPaintRequestorInterface::WindowPaintRequestor))
827 {853 {
828 CompWindow *tray = screen->findWindow (tray_xid);854 CompWindow *tray = screen->findWindow (tray_xid);
829855
@@ -901,15 +927,54 @@
901 }927 }
902 }928 }
903929
904 doShellRepaint = false;
905 damaged = false;930 damaged = false;
906}931}
907932
908bool UnityScreen::forcePaintOnTop ()933unsigned int UnityScreen::GetProhibitedPaintMasks ()
909{934{
910 return !allowWindowPaint ||935 bool unity_force_overlay = switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen();
911 ((switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen())936 bool no_screen_grabs = !(screen->grabbed () && !screen->otherGrabExist (NULL));
912 && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));937 bool fullscreen_windows = !fullscreen_windows_.empty ();
938
939 unsigned int pmask = no_paint_allowed_mask_;
940
941 if (unity_force_overlay &&
942 fullscreen_windows &&
943 no_screen_grabs)
944 pmask |= ShellPaintRequestorInterface::WindowPaintRequestor;
945
946 return pmask;
947}
948
949bool UnityScreen::Paint (ShellPaintRequestorInterface *r,
950 FBOBindingQueryInterface *q)
951{
952 return paint_dispatch_.Paint (r, q);
953}
954
955bool UnityScreen::EnforceRequestor (ShellPaintRequestorInterface *r)
956{
957 return paint_dispatch_.EnforceRequestor (r);
958}
959
960void UnityScreen::ClearRequestorEnforcement ()
961{
962 paint_dispatch_.ClearRequestorEnforcement ();
963}
964
965unsigned int UnityScreen::ProhibitedPaintRequestors ()
966{
967 return paint_dispatch_.ProhibitedPaintRequestors ();
968}
969
970void UnityScreen::RequireShellRepaint ()
971{
972 paint_dispatch_.RequireShellRepaint ();
973}
974
975bool UnityScreen::RepaintPending ()
976{
977 return paint_dispatch_.RepaintPending ();
913}978}
914979
915void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha)980void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha)
@@ -1204,8 +1269,9 @@
1204{1269{
1205 bool ret;1270 bool ret;
12061271
1207 doShellRepaint = true;1272 ClearRequestorEnforcement ();
1208 allowWindowPaint = true;1273 RequireShellRepaint ();
1274 no_paint_allowed_mask_ = 0;
1209 _last_output = output;1275 _last_output = output;
1210 paint_panel_ = false;1276 paint_panel_ = false;
12111277
@@ -1220,16 +1286,13 @@
1220 * attempts to bind it will only increment1286 * attempts to bind it will only increment
1221 * its bind reference so make sure that1287 * its bind reference so make sure that
1222 * you always unbind as much as you bind */1288 * you always unbind as much as you bind */
1223 _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));1289 fbo_->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
1224#endif1290#endif
12251291
1226 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */1292 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
1227 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);1293 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
12281294
1229#ifndef USE_MODERN_COMPIZ_GL1295 Paint (this, this);
1230 if (doShellRepaint)
1231 paintDisplay(region, transform, mask);
1232#endif
12331296
1234 return ret;1297 return ret;
1235}1298}
@@ -1241,7 +1304,7 @@
1241{1304{
1242 bool useFbo = false;1305 bool useFbo = false;
12431306
1244 if (doShellRepaint)1307 if (RepaintPending ())
1245 {1308 {
1246 oldFbo = fbo->bind ();1309 oldFbo = fbo->bind ();
1247 useFbo = fbo->checkStatus () && fbo->tex ();1310 useFbo = fbo->checkStatus () && fbo->tex ();
@@ -1250,7 +1313,7 @@
1250 ::GLFramebufferObject::rebind (oldFbo);1313 ::GLFramebufferObject::rebind (oldFbo);
1251 return;1314 return;
1252 }1315 }
1253 paintDisplay();1316 Paint (this, this);
1254 ::GLFramebufferObject::rebind (oldFbo);1317 ::GLFramebufferObject::rebind (oldFbo);
1255 }1318 }
12561319
@@ -1267,7 +1330,7 @@
1267 CompOutput* output,1330 CompOutput* output,
1268 unsigned int mask)1331 unsigned int mask)
1269{1332{
1270 allowWindowPaint = false;1333 no_paint_allowed_mask_ = ShellPaintRequestorInterface::WindowPaintRequestor;
1271 gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask);1334 gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask);
12721335
1273}1336}
@@ -2124,31 +2187,6 @@
2124 return "Unity";2187 return "Unity";
2125}2188}
21262189
2127bool isNuxWindow (CompWindow* value)
2128{
2129 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
2130 auto id = value->id();
2131
2132 // iterate loop by hand rather than use std::find as this is considerably faster
2133 // we care about performance here becuase of the high frequency in which this function is
2134 // called (nearly every frame)
2135 unsigned int size = xwns.size();
2136 for (unsigned int i = 0; i < size; ++i)
2137 {
2138 if (xwns[i] == id)
2139 return true;
2140 }
2141 return false;
2142}
2143
2144const CompWindowList& UnityScreen::getWindowPaintList()
2145{
2146 CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList();
2147 pl.remove_if(isNuxWindow);
2148
2149 return pl;
2150}
2151
2152void UnityScreen::RaiseInputWindows()2190void UnityScreen::RaiseInputWindows()
2153{2191{
2154 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();2192 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
@@ -2161,13 +2199,11 @@
2161 }2199 }
2162}2200}
21632201
2164/* detect occlusions2202/* we want to paint underneath other windows here,
2165 *2203 * so we need to find if this window is actually
2166 * core passes down the PAINT_WINDOW_OCCLUSION_DETECTION2204 * stacked on top of one of the nux input windows
2167 * mask when it is doing occlusion detection, so use that2205 * and if so paint nux and stop us from painting
2168 * order to fill our occlusion buffer which we'll flip2206 * other windows or on top of the whole screen */
2169 * to nux later
2170 */
2171bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,2207bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,
2172 const GLMatrix& matrix,2208 const GLMatrix& matrix,
2173 const CompRegion& region,2209 const CompRegion& region,
@@ -2187,7 +2223,7 @@
21872223
2188 std::vector<Window> const& tray_xids = uScreen->panel_controller_->GetTrayXids();2224 std::vector<Window> const& tray_xids = uScreen->panel_controller_->GetTrayXids();
2189 if (std::find(tray_xids.begin(), tray_xids.end(), window->id()) != tray_xids.end() &&2225 if (std::find(tray_xids.begin(), tray_xids.end(), window->id()) != tray_xids.end() &&
2190 !uScreen->allowWindowPaint)2226 (uScreen->ProhibitedPaintRequestors () & ShellPaintRequestorInterface::WindowPaintRequestor))
2191 {2227 {
2192 if (!uScreen->painting_tray_)2228 if (!uScreen->painting_tray_)
2193 {2229 {
@@ -2196,26 +2232,7 @@
2196 }2232 }
2197 }2233 }
21982234
2199 return gWindow->glPaint(wAttrib, matrix, region, mask);2235 if (uScreen->RepaintPending () && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask)
2200}
2201
2202/* handle window painting in an opengl context
2203 *
2204 * we want to paint underneath other windows here,
2205 * so we need to find if this window is actually
2206 * stacked on top of one of the nux input windows
2207 * and if so paint nux and stop us from painting
2208 * other windows or on top of the whole screen */
2209bool UnityWindow::glDraw(const GLMatrix& matrix,
2210#ifndef USE_MODERN_COMPIZ_GL
2211 GLFragment::Attrib& attrib,
2212#else
2213 const GLWindowPaintAttrib& attrib,
2214#endif
2215 const CompRegion& region,
2216 unsigned int mask)
2217{
2218 if (uScreen->doShellRepaint && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask)
2219 {2236 {
2220 guint32 id = window->id();2237 guint32 id = window->id();
2221 bool maximized = WindowManager::Default()->IsWindowMaximized(id);2238 bool maximized = WindowManager::Default()->IsWindowMaximized(id);
@@ -2231,29 +2248,63 @@
2231 }2248 }
2232 }2249 }
22332250
2234 if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ())2251 if (IsNuxWindow ())
2235 {2252 {
2236 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();2253 /* Windows are painted in top-to-bottom order
2237 unsigned int size = xwns.size();2254 * with occlusion detection on, so we can
22382255 * find out the top most nux window and paint
2239 for (CompWindow* w = window; w && uScreen->doShellRepaint; w = w->prev)2256 * there */
2240 {2257 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
2241 auto id = w->id();2258 {
22422259 GLWindowPaintAttrib noAlphaAttrib;
2243 for (unsigned int i = 0; i < size; ++i)2260
2244 {2261 noAlphaAttrib.opacity = OPAQUE;
2245 if (xwns[i] == id)2262 noAlphaAttrib.brightness = BRIGHT;
2246 {2263 noAlphaAttrib.saturation = COLOR;
2247#ifdef USE_MODERN_COMPIZ_GL2264
2248 uScreen->paintDisplay();2265 bool status = gWindow->glPaint (noAlphaAttrib,
2266 matrix,
2267 region,
2268 PAINT_WINDOW_OCCLUSION_DETECTION_MASK);
2269
2270 if (status)
2271 uScreen->EnforceRequestor (this);
2272
2273 /* We don't want core to take this window
2274 * into account when doing occlusion detection
2275 * however */
2276 return false;
2277 }
2278 /* Don't care about "fake" paints */
2279 else if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
2280 {
2281 return false;
2282 }
2283 else
2284 {
2285 uScreen->Paint (this, uScreen);
2286
2287 /* Don't paint nux windows on the real paint pass */
2288 return false;
2289 }
2290 }
2291
2292 return gWindow->glPaint(wAttrib, matrix, region, mask);
2293}
2294
2295/* handle window painting in an opengl context
2296 */
2297bool UnityWindow::glDraw(const GLMatrix& matrix,
2298#ifndef USE_MODERN_COMPIZ_GL
2299 GLFragment::Attrib& attrib,
2249#else2300#else
2250 uScreen->paintDisplay(region, matrix, mask);2301 const GLWindowPaintAttrib& attrib,
2251#endif2302#endif
2252 break;2303 const CompRegion& region,
2253 }2304 unsigned int mask)
2254 }2305{
2255 }2306 if (IsNuxWindow ())
2256 }2307 return false;
22572308
2258 if (window->type() == CompWindowTypeDesktopMask)2309 if (window->type() == CompWindowTypeDesktopMask)
2259 uScreen->setPanelShadowMatrix(matrix);2310 uScreen->setPanelShadowMatrix(matrix);
@@ -2272,7 +2323,6 @@
2272 uScreen->paintPanelShadow(matrix);2323 uScreen->paintPanelShadow(matrix);
2273 }2324 }
22742325
2275
2276 return ret;2326 return ret;
2277}2327}
22782328
@@ -2747,8 +2797,8 @@
2747#ifndef USE_MODERN_COMPIZ_GL2797#ifndef USE_MODERN_COMPIZ_GL
2748 if (GL::fbo)2798 if (GL::fbo)
2749 {2799 {
2750 uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));2800 uScreen->fbo_ = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
2751 uScreen->_fbo->onScreenSizeChanged (geometry);2801 uScreen->fbo_->onScreenSizeChanged (geometry);
2752 }2802 }
2753#endif2803#endif
27542804
@@ -2914,6 +2964,18 @@
2914 hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button"));2964 hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button"));
2915}2965}
29162966
2967bool
2968UnityWindow::IsNuxWindow ()
2969{
2970 return is_nux_window_;
2971}
2972
2973unsigned int
2974UnityWindow::GetPaintRequestorType ()
2975{
2976 return ShellPaintRequestorInterface::WindowPaintRequestor;
2977}
2978
2917/* Window init */2979/* Window init */
2918UnityWindow::UnityWindow(CompWindow* window)2980UnityWindow::UnityWindow(CompWindow* window)
2919 : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)2981 : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
@@ -2922,10 +2984,16 @@
2922 , gWindow(GLWindow::get(window))2984 , gWindow(GLWindow::get(window))
2923 , mMinimizeHandler()2985 , mMinimizeHandler()
2924 , mShowdesktopHandler(nullptr)2986 , mShowdesktopHandler(nullptr)
2987 , is_nux_window_ (false)
2925{2988{
2926 WindowInterface::setHandler(window);2989 WindowInterface::setHandler(window);
2927 GLWindowInterface::setHandler(gWindow);2990 GLWindowInterface::setHandler(gWindow);
29282991
2992 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
2993 for (unsigned int i = 0; i < xwns.size(); i++)
2994 if (xwns[i] == window->id ())
2995 is_nux_window_ = true;
2996
2929 if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&2997 if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
2930 window->mapNum ())2998 window->mapNum ())
2931 {2999 {
29323000
=== modified file 'plugins/unityshell/src/unityshell.h'
--- plugins/unityshell/src/unityshell.h 2012-05-30 18:43:17 +0000
+++ plugins/unityshell/src/unityshell.h 2012-06-14 09:04:28 +0000
@@ -52,6 +52,7 @@
52#include "UBusWrapper.h"52#include "UBusWrapper.h"
53#include "UnityshellPrivate.h"53#include "UnityshellPrivate.h"
54#include "UnityShowdesktopHandler.h"54#include "UnityShowdesktopHandler.h"
55#include "ShellPaintSchedule.h"
55#ifndef USE_MODERN_COMPIZ_GL56#ifndef USE_MODERN_COMPIZ_GL
56#include "ScreenEffectFramebufferObject.h"57#include "ScreenEffectFramebufferObject.h"
57#endif58#endif
@@ -68,6 +69,10 @@
6869
69/* base screen class */70/* base screen class */
70class UnityScreen :71class UnityScreen :
72 public FBOBindingQueryInterface,
73 public ShellPaintDispatchInterface,
74 public ShellPaintRequestorInterface,
75 public ShellPaintInterface,
71 public unity::debug::Introspectable,76 public unity::debug::Introspectable,
72 public sigc::trackable,77 public sigc::trackable,
73 public ScreenInterface,78 public ScreenInterface,
@@ -92,11 +97,8 @@
92 void nuxEpilogue();97 void nuxEpilogue();
9398
94 /* nux draw wrapper */99 /* nux draw wrapper */
95#ifdef USE_MODERN_COMPIZ_GL100 bool PaintBackingFBO (CompOutput *output);
96 void paintDisplay();101 void PaintDisplay (FBOBindingQueryInterface *);
97#else
98 void paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask);
99#endif
100 void paintPanelShadow(const GLMatrix& matrix);102 void paintPanelShadow(const GLMatrix& matrix);
101 void setPanelShadowMatrix(const GLMatrix& matrix);103 void setPanelShadowMatrix(const GLMatrix& matrix);
102104
@@ -132,9 +134,6 @@
132 CompOutput*,134 CompOutput*,
133 unsigned int);135 unsigned int);
134136
135 /* Pop our InputOutput windows from the paint list */
136 const CompWindowList& getWindowPaintList();
137
138 /* handle X11 events */137 /* handle X11 events */
139 void handleEvent(XEvent*);138 void handleEvent(XEvent*);
140139
@@ -188,8 +187,6 @@
188 void NeedsRelayout();187 void NeedsRelayout();
189 void ScheduleRelayout(guint timeout);188 void ScheduleRelayout(guint timeout);
190189
191 bool forcePaintOnTop ();
192
193protected:190protected:
194 std::string GetName() const;191 std::string GetName() const;
195 void AddProperties(GVariantBuilder* builder);192 void AddProperties(GVariantBuilder* builder);
@@ -231,6 +228,20 @@
231228
232 void OnPanelStyleChanged();229 void OnPanelStyleChanged();
233230
231 bool WasBound ();
232 unsigned int GetPaintRequestorType ();
233 unsigned int GetProhibitedPaintMasks ();
234
235 bool Paint (ShellPaintRequestorInterface *,
236 FBOBindingQueryInterface *);
237 bool EnforceRequestor (ShellPaintRequestorInterface *);
238 void ClearRequestorEnforcement ();
239 unsigned int ProhibitedPaintRequestors ();
240 void RequireShellRepaint ();
241 bool RepaintPending ();
242
243 ShellPaintDispatch paint_dispatch_;
244
234 Settings dash_settings_;245 Settings dash_settings_;
235 dash::Style dash_style_;246 dash::Style dash_style_;
236 panel::Style panel_style_;247 panel::Style panel_style_;
@@ -270,12 +281,9 @@
270 GLTexture::List _shadow_texture;281 GLTexture::List _shadow_texture;
271282
272 /* handle paint order */283 /* handle paint order */
273 bool doShellRepaint;
274 bool allowWindowPaint;
275 bool damaged;284 bool damaged;
276 bool _key_nav_mode_requested;285 bool _key_nav_mode_requested;
277 CompOutput* _last_output;286 CompOutput* _last_output;
278 CompWindowList _withRemovedNuxWindows;
279287
280 nux::Property<nux::Geometry> primary_monitor_;288 nux::Property<nux::Geometry> primary_monitor_;
281289
@@ -284,7 +292,7 @@
284#ifdef USE_MODERN_COMPIZ_GL292#ifdef USE_MODERN_COMPIZ_GL
285 ::GLFramebufferObject *oldFbo;293 ::GLFramebufferObject *oldFbo;
286#else294#else
287 ScreenEffectFramebufferObject::Ptr _fbo;295 ScreenEffectFramebufferObject::Ptr fbo_;
288 GLuint _active_fbo;296 GLuint _active_fbo;
289#endif297#endif
290298
@@ -311,15 +319,27 @@
311319
312 UBusManager ubus_manager_;320 UBusManager ubus_manager_;
313 glib::SourceManager sources_;321 glib::SourceManager sources_;
322 unsigned int no_paint_allowed_mask_;
314323
315 friend class UnityWindow;324 friend class UnityWindow;
316};325};
317326
327class NuxBridgeWindowInterface
328{
329public:
330
331 virtual ~NuxBridgeWindowInterface () {};
332
333 virtual bool IsNuxWindow () = 0;
334};
335
318class UnityWindow :336class UnityWindow :
319 public WindowInterface,337 public WindowInterface,
320 public GLWindowInterface,338 public GLWindowInterface,
321 public ShowdesktopHandlerWindowInterface,339 public ShowdesktopHandlerWindowInterface,
322 public compiz::WindowInputRemoverLockAcquireInterface,340 public compiz::WindowInputRemoverLockAcquireInterface,
341 public NuxBridgeWindowInterface,
342 public ShellPaintRequestorInterface,
323 public BaseSwitchWindow,343 public BaseSwitchWindow,
324 public PluginClassHandler <UnityWindow, CompWindow>344 public PluginClassHandler <UnityWindow, CompWindow>
325{345{
@@ -417,7 +437,12 @@
417437
418 compiz::WindowInputRemoverLock::Ptr GetInputRemover ();438 compiz::WindowInputRemoverLock::Ptr GetInputRemover ();
419439
440 bool IsNuxWindow ();
441 unsigned int GetPaintRequestorType ();
442
420 compiz::WindowInputRemoverLock::Weak input_remover_;443 compiz::WindowInputRemoverLock::Weak input_remover_;
444
445 bool is_nux_window_;
421 glib::Source::UniquePtr focus_desktop_timeout_;446 glib::Source::UniquePtr focus_desktop_timeout_;
422};447};
423448
424449
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2012-06-12 08:23:23 +0000
+++ tests/CMakeLists.txt 2012-06-14 09:04:28 +0000
@@ -150,6 +150,7 @@
150 test_unityshell_private.cpp150 test_unityshell_private.cpp
151 test_showdesktop_handler.cpp151 test_showdesktop_handler.cpp
152 test_hud_private.cpp152 test_hud_private.cpp
153 test_shell_paint_schedule.cpp
153 ${CMAKE_SOURCE_DIR}/launcher/AbstractLauncherIcon.cpp154 ${CMAKE_SOURCE_DIR}/launcher/AbstractLauncherIcon.cpp
154 ${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp155 ${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp
155 ${UNITY_SRC}/DebugDBusInterface.cpp156 ${UNITY_SRC}/DebugDBusInterface.cpp
@@ -162,6 +163,7 @@
162 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp163 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp
163 ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutModel.cpp164 ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutModel.cpp
164 ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutHintPrivate.cpp165 ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutHintPrivate.cpp
166 ${CMAKE_SOURCE_DIR}/unity-shared/ShellPaintSchedule.cpp
165 ${CMAKE_SOURCE_DIR}/unity-shared/Introspectable.cpp167 ${CMAKE_SOURCE_DIR}/unity-shared/Introspectable.cpp
166 ${CMAKE_SOURCE_DIR}/unity-shared/TextureCache.cpp168 ${CMAKE_SOURCE_DIR}/unity-shared/TextureCache.cpp
167 ${CMAKE_SOURCE_DIR}/unity-shared/Timer.cpp169 ${CMAKE_SOURCE_DIR}/unity-shared/Timer.cpp
168170
=== added file 'tests/test_shell_paint_schedule.cpp'
--- tests/test_shell_paint_schedule.cpp 1970-01-01 00:00:00 +0000
+++ tests/test_shell_paint_schedule.cpp 2012-06-14 09:04:28 +0000
@@ -0,0 +1,284 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * version 3 along with this program. If not, see
15 * <http://www.gnu.org/licenses/>
16 *
17 * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
18 *
19 */
20
21#include <gtest/gtest.h>
22#include <gmock/gmock.h>
23
24using ::testing::StrictMock;
25using ::testing::_;
26using ::testing::AtLeast;
27using ::testing::Return;
28
29#include "ShellPaintSchedule.h"
30
31using namespace unity;
32
33class MockShellPaintRequestor :
34 public ShellPaintRequestorInterface
35{
36public:
37
38 MOCK_METHOD0 (GetPaintRequestorType, unsigned int ());
39
40};
41
42class MockFBOBindingQuery :
43 public FBOBindingQueryInterface
44{
45public:
46
47 MOCK_METHOD0 (WasBound, bool ());
48};
49
50class MockShellPaint :
51 public ShellPaintInterface
52{
53public:
54
55 MOCK_METHOD1 (PaintDisplay, void (FBOBindingQueryInterface *));
56};
57
58class MockShellPaintDispatch
59{
60public:
61
62 MOCK_METHOD2 (Paint, bool (ShellPaintRequestorInterface *, FBOBindingQueryInterface *));
63 MOCK_METHOD1 (EnforceRequestor, void (ShellPaintRequestorInterface *));
64 MOCK_METHOD0 (ClearRequestorEnforcement, void ());
65 MOCK_METHOD0 (ProhibitedPaintRequestors, unsigned int ());
66 MOCK_METHOD0 (RequireShellRepaint, void ());
67 MOCK_METHOD0 (RepaintPending, bool ());
68};
69
70class TestShellPaintSchedule :
71 public ::testing::Test
72{
73};
74
75TEST(TestShellPaintSchedule, NoPaintWhereNotRequired)
76{
77 StrictMock <MockShellPaint> p;
78 MockShellPaintRequestor r;
79 MockFBOBindingQuery q;
80 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
81
82 ShellPaintDispatch dispatch (&p, f);
83
84 dispatch.Paint (&r, &q);
85}
86
87TEST(TestShellPaintSchedule, PaintWhereRequired)
88{
89 StrictMock <MockShellPaint> p;
90 MockShellPaintRequestor r;
91 MockFBOBindingQuery q;
92 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
93
94 ShellPaintDispatch dispatch (&p, f);
95
96 dispatch.RequireShellRepaint ();
97
98 EXPECT_CALL (r, GetPaintRequestorType ());
99 EXPECT_CALL (p, PaintDisplay (&q));
100
101 dispatch.Paint (&r, &q);
102}
103
104TEST(TestShellPaintSchedule, NoPaintTwice)
105{
106 StrictMock <MockShellPaint> p;
107 MockShellPaintRequestor r;
108 MockFBOBindingQuery q;
109 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
110
111 ShellPaintDispatch dispatch (&p, f);
112
113 dispatch.RequireShellRepaint ();
114
115 EXPECT_CALL (r, GetPaintRequestorType ());
116 EXPECT_CALL (p, PaintDisplay (&q));
117
118 dispatch.Paint (&r, &q);
119 dispatch.Paint (&r, &q);
120}
121
122TEST(TestShellPaintSchedule, NoWindowPaintButScreenPaint)
123{
124 StrictMock <MockShellPaint> p;
125 MockShellPaintRequestor r;
126 MockFBOBindingQuery q;
127 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return ShellPaintRequestorInterface::WindowPaintRequestor; } );
128
129 ShellPaintDispatch dispatch (&p, f);
130
131 dispatch.RequireShellRepaint ();
132
133 EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
134
135 dispatch.Paint (&r, &q);
136
137 EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::ScreenPaintRequestor));
138 EXPECT_CALL (p, PaintDisplay (&q));
139
140 dispatch.Paint (&r, &q);
141}
142
143TEST(TestShellPaintSchedule, NoScreenPaintButWindowPaint)
144{
145 StrictMock <MockShellPaint> p;
146 MockShellPaintRequestor r;
147 MockFBOBindingQuery q;
148 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return ShellPaintRequestorInterface::ScreenPaintRequestor; } );
149
150 ShellPaintDispatch dispatch (&p, f);
151
152 dispatch.RequireShellRepaint ();
153
154 EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::ScreenPaintRequestor));
155
156 dispatch.Paint (&r, &q);
157
158 EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
159 EXPECT_CALL (p, PaintDisplay (&q));
160
161 dispatch.Paint (&r, &q);
162}
163
164TEST(TestShellPaintSchedule, TopRequestorOnlyPaints)
165{
166 StrictMock <MockShellPaint> p;
167 MockShellPaintRequestor r_w1, r_w2;
168 MockFBOBindingQuery q;
169 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
170
171 ShellPaintDispatch dispatch (&p, f);
172
173 dispatch.RequireShellRepaint ();
174
175 dispatch.ClearRequestorEnforcement ();
176 dispatch.EnforceRequestor (&r_w2);
177
178 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
179 EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
180
181 dispatch.Paint (&r_w1, &q);
182
183 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
184 EXPECT_CALL (p, PaintDisplay (&q));
185
186 dispatch.Paint (&r_w2, &q);
187}
188
189TEST(TestShellPaintSchedule, SuperveningRequestorOfOtherTypePaints)
190{
191 StrictMock <MockShellPaint> p;
192 MockShellPaintRequestor r_w1, r_w2, r_s1;
193 MockFBOBindingQuery q;
194 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
195
196 ShellPaintDispatch dispatch (&p, f);
197
198 dispatch.RequireShellRepaint ();
199
200 dispatch.ClearRequestorEnforcement ();
201 dispatch.EnforceRequestor (&r_w2);
202
203 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
204 EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
205
206 dispatch.Paint (&r_w1, &q);
207
208 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
209 EXPECT_CALL (r_s1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::ScreenPaintRequestor));
210
211 EXPECT_CALL (p, PaintDisplay (&q));
212
213 dispatch.Paint (&r_s1, &q);
214
215 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
216
217 dispatch.Paint (&r_w2, &q);
218}
219
220TEST(TestShellPaintSchedule, DoubleEnforcementHasNoEffect)
221{
222 StrictMock <MockShellPaint> p;
223 MockShellPaintRequestor r_w1, r_w2;
224 MockFBOBindingQuery q;
225 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
226
227 ShellPaintDispatch dispatch (&p, f);
228
229 dispatch.RequireShellRepaint ();
230
231 dispatch.ClearRequestorEnforcement ();
232 dispatch.EnforceRequestor (&r_w2);
233 dispatch.EnforceRequestor (&r_w1);
234
235 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
236 EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
237
238 dispatch.Paint (&r_w1, &q);
239
240 EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
241 EXPECT_CALL (p, PaintDisplay (&q));
242
243 dispatch.Paint (&r_w2, &q);
244}
245
246TEST(TestShellPaintSchedule, GetPendingRepaint)
247{
248 StrictMock <MockShellPaint> p;
249 MockShellPaintRequestor r;
250 MockFBOBindingQuery q;
251 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> unsigned int { return 0; } );
252
253 ShellPaintDispatch dispatch (&p, f);
254
255 EXPECT_FALSE (dispatch.RepaintPending ());
256
257 dispatch.RequireShellRepaint ();
258
259 EXPECT_TRUE (dispatch.RepaintPending ());
260
261 EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::WindowPaintRequestor));
262 EXPECT_CALL (p, PaintDisplay (&q));
263
264 dispatch.Paint (&r, &q);
265
266 EXPECT_FALSE (dispatch.RepaintPending ());
267}
268
269TEST(TestShellPaintSchedule, GetProhibitedPaintMasks)
270{
271 StrictMock <MockShellPaint> p;
272 MockShellPaintRequestor r;
273 MockFBOBindingQuery q;
274 unsigned int prohibited_paint_mask = 0;
275 ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([&]() -> unsigned int { return prohibited_paint_mask; } );
276
277 ShellPaintDispatch dispatch (&p, f);
278
279 EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ());
280 prohibited_paint_mask = ShellPaintRequestorInterface::WindowPaintRequestor;
281 EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ());
282 prohibited_paint_mask = ShellPaintRequestorInterface::ScreenPaintRequestor;
283 EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ());
284}
0285
=== modified file 'unity-shared/CMakeLists.txt'
--- unity-shared/CMakeLists.txt 2012-05-22 10:15:47 +0000
+++ unity-shared/CMakeLists.txt 2012-06-14 09:04:28 +0000
@@ -47,6 +47,7 @@
47 PanelStyle.cpp47 PanelStyle.cpp
48 SearchBar.cpp48 SearchBar.cpp
49 SearchBarSpinner.cpp49 SearchBarSpinner.cpp
50 ShellPaintSchedule.cpp
50 StaticCairoText.cpp51 StaticCairoText.cpp
51 TextureCache.cpp52 TextureCache.cpp
52 Timer.cpp53 Timer.cpp
5354
=== added file 'unity-shared/ShellPaintSchedule.cpp'
--- unity-shared/ShellPaintSchedule.cpp 1970-01-01 00:00:00 +0000
+++ unity-shared/ShellPaintSchedule.cpp 2012-06-14 09:04:28 +0000
@@ -0,0 +1,91 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#include "ShellPaintSchedule.h"
21
22namespace unity
23{
24
25ShellPaintDispatch::ShellPaintDispatch (ShellPaintInterface *paint_interface,
26 const GetProhibitedPaintMasksFunc &prohibited_func) :
27 shell_repaint_required_ (false),
28 top_requestor_ (nullptr),
29 prohibited_paint_masks_func_ (prohibited_func),
30 paint_interface_ (paint_interface)
31{
32}
33
34bool
35ShellPaintDispatch::Paint (ShellPaintRequestorInterface *requestor,
36 FBOBindingQueryInterface *fbo_query)
37{
38 if (!shell_repaint_required_)
39 return false;
40
41 if (prohibited_paint_masks_func_ () & requestor->GetPaintRequestorType ())
42 return false;
43
44 if (top_requestor_)
45 if ((top_requestor_->GetPaintRequestorType () &
46 requestor->GetPaintRequestorType ()) && top_requestor_ != requestor)
47 return false;
48
49 paint_interface_->PaintDisplay (fbo_query);
50
51 shell_repaint_required_ = false;
52
53 return true;
54}
55
56bool
57ShellPaintDispatch::EnforceRequestor (ShellPaintRequestorInterface *requestor)
58{
59 if (top_requestor_)
60 return false;
61
62 top_requestor_ = requestor;
63
64 return true;
65}
66
67void
68ShellPaintDispatch::ClearRequestorEnforcement ()
69{
70 top_requestor_ = nullptr;
71}
72
73unsigned int
74ShellPaintDispatch::ProhibitedPaintRequestors ()
75{
76 return prohibited_paint_masks_func_ ();
77}
78
79void
80ShellPaintDispatch::RequireShellRepaint ()
81{
82 shell_repaint_required_ = true;
83}
84
85bool
86ShellPaintDispatch::RepaintPending ()
87{
88 return shell_repaint_required_;
89}
90
91}
092
=== added file 'unity-shared/ShellPaintSchedule.h'
--- unity-shared/ShellPaintSchedule.h 1970-01-01 00:00:00 +0000
+++ unity-shared/ShellPaintSchedule.h 2012-06-14 09:04:28 +0000
@@ -0,0 +1,104 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
18 */
19
20#ifndef UNITY_PAINT_SCHEDULE_H
21#define UNITY_PAINT_SCHEDULE_H
22
23#include <boost/bind.hpp>
24#include <boost/function.hpp>
25
26namespace unity
27{
28
29class ShellPaintRequestorInterface
30{
31public:
32
33
34 static const unsigned int WindowPaintRequestor = (1 << 0);
35 static const unsigned int ScreenPaintRequestor = (1 << 1);
36
37 virtual ~ShellPaintRequestorInterface () {}
38
39 virtual unsigned int GetPaintRequestorType () = 0;
40};
41
42class FBOBindingQueryInterface
43{
44public:
45
46 virtual ~FBOBindingQueryInterface () {}
47 virtual bool WasBound () = 0;
48};
49
50class ShellPaintInterface
51{
52public:
53
54 virtual ~ShellPaintInterface () {};
55
56 virtual void PaintDisplay (FBOBindingQueryInterface *) = 0;
57};
58
59class ShellPaintDispatchInterface
60{
61public:
62
63 virtual ~ShellPaintDispatchInterface () {}
64
65 virtual bool Paint (ShellPaintRequestorInterface *,
66 FBOBindingQueryInterface *) = 0;
67 virtual bool EnforceRequestor (ShellPaintRequestorInterface *) = 0;
68 virtual void ClearRequestorEnforcement () = 0;
69 virtual unsigned int ProhibitedPaintRequestors () = 0;
70 virtual void RequireShellRepaint () = 0;
71 virtual bool RepaintPending () = 0;
72
73};
74
75class ShellPaintDispatch :
76 public ShellPaintDispatchInterface
77{
78public:
79
80 typedef boost::function <unsigned int ()> GetProhibitedPaintMasksFunc;
81
82 ShellPaintDispatch (ShellPaintInterface * paint_interface,
83 const GetProhibitedPaintMasksFunc &func);
84
85 bool Paint (ShellPaintRequestorInterface *,
86 FBOBindingQueryInterface *);
87 bool EnforceRequestor (ShellPaintRequestorInterface *);
88 void ClearRequestorEnforcement ();
89 unsigned int ProhibitedPaintRequestors ();
90 void RequireShellRepaint ();
91 bool RepaintPending ();
92
93
94protected:
95
96 bool shell_repaint_required_;
97 ShellPaintRequestorInterface *top_requestor_;
98 GetProhibitedPaintMasksFunc prohibited_paint_masks_func_;
99 ShellPaintInterface *paint_interface_;
100};
101
102}
103
104#endif