Merge lp:~3v1n0/unity/shadows-on-existing-pixmaps-cleanup into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Andrea Azzarone
Approved revision: no longer in the source branch.
Merged at revision: 4162
Proposed branch: lp:~3v1n0/unity/shadows-on-existing-pixmaps-cleanup
Merge into: lp:unity
Prerequisite: lp:~hikiko/unity/unity.shadows-on-existing-pixmaps
Diff against target: 567 lines (+171/-150)
8 files modified
decorations/DecoratedWindow.cpp (+58/-29)
decorations/DecoratedWindow.h (+1/-0)
decorations/DecorationsManager.cpp (+0/-27)
decorations/DecorationsPriv.h (+5/-3)
decorations/DecorationsShape.cpp (+72/-67)
decorations/DecorationsShape.h (+28/-17)
plugins/unityshell/src/unityshell.cpp (+1/-0)
unity-shared/CompizUtils.cpp (+6/-7)
To merge this branch: bzr merge lp:~3v1n0/unity/shadows-on-existing-pixmaps-cleanup
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
Review via email: mp+301099@code.launchpad.net

Commit message

DecoratedWindow: Cleanup shadows for shaped windows, reduce recomputation

To post a comment you must log in.
Revision history for this message
Andrea Azzarone (azzar1) wrote :

The changes to the prerequiste make sense to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'decorations/DecoratedWindow.cpp'
2--- decorations/DecoratedWindow.cpp 2016-07-27 10:19:12 +0000
3+++ decorations/DecoratedWindow.cpp 2016-07-27 10:19:13 +0000
4@@ -31,8 +31,6 @@
5 #include "WindowManager.h"
6 #include "UnitySettings.h"
7
8-#include <X11/extensions/shape.h>
9-
10 namespace unity
11 {
12 namespace decoration
13@@ -40,6 +38,7 @@
14 namespace
15 {
16 const std::string MENUS_PANEL_NAME = "WindowLIM";
17+const int SHADOW_BLUR_MARGIN_FACTOR = 2;
18 }
19
20 Window::Impl::Impl(Window* parent, CompWindow* win)
21@@ -504,13 +503,21 @@
22 return (win_->frame() || win_->hasUnmapReference()) && FullyDecorated();
23 }
24
25+bool Window::Impl::IsRectangular() const
26+{
27+ return win_->region().numRects() == 1;
28+}
29+
30 GLTexture* Window::Impl::ShadowTexture() const
31 {
32+ if (!IsRectangular())
33+ return shaped_shadow_pixmap_->texture();
34+
35 auto const& mi = manager_->impl_;
36 if (active() || parent_->scaled())
37- return win_->region().numRects() > 1 ? shaped_shadow_pixmap_->texture() : mi->active_shadow_pixmap_->texture();
38+ return mi->active_shadow_pixmap_->texture();
39
40- return win_->region().numRects() > 1 ? shaped_shadow_pixmap_->texture() : mi->inactive_shadow_pixmap_->texture();
41+ return mi->inactive_shadow_pixmap_->texture();
42 }
43
44 unsigned Window::Impl::ShadowRadius() const
45@@ -678,6 +685,26 @@
46 }
47 }
48
49+cu::PixmapTexture::Ptr Window::Impl::BuildShapedShadowTexture(nux::Size const& size, unsigned radius, nux::Color const& color, Shape const& shape) {
50+ nux::CairoGraphics img(CAIRO_FORMAT_ARGB32, size.width, size.height);
51+ auto* img_ctx = img.GetInternalContext();
52+
53+ for (auto const& rect : shape.GetRectangles())
54+ {
55+ cairo_rectangle(img_ctx, rect.x + radius * SHADOW_BLUR_MARGIN_FACTOR - shape.XOffset(), rect.y + radius * SHADOW_BLUR_MARGIN_FACTOR - shape.YOffset(), rect.width, rect.height);
56+ cairo_set_source_rgba(img_ctx, color.red, color.green, color.blue, color.alpha);
57+ cairo_fill(img_ctx);
58+ }
59+
60+ img.BlurSurface(radius);
61+
62+ cu::CairoContext shadow_ctx(size.width, size.height);
63+ cairo_set_source_surface(shadow_ctx, img.GetSurface(), 0, 0);
64+ cairo_paint(shadow_ctx);
65+
66+ return shadow_ctx;
67+}
68+
69 void Window::Impl::ComputeShapedShadowQuad()
70 {
71 if (!(deco_elements_ & cu::DecorationElement::SHADOW))
72@@ -690,23 +717,26 @@
73
74 nux::Color color = active() ? manager_->active_shadow_color() : manager_->inactive_shadow_color();
75 unsigned int radius = active() ? manager_->active_shadow_radius() : manager_->inactive_shadow_radius();
76- DecorationsShape shape;
77- shape.initShape(win_->id());
78- shaped_shadow_pixmap_ = manager_->impl_->BuildShapedShadowTexture(radius, color, shape);
79-
80- const auto* texture = ShadowTexture();
81+
82+ Shape shape(win_->id());
83+ auto const& border = win_->borderRect();
84+ auto const& shadow_offset = manager_->shadow_offset();
85+
86+ // Ideally it would be shape.getWidth + radius * 2 but Cairographics::BlurSurface
87+ // isn't bounded by the radius and we need to compensate by using a larger texture.
88+ int width = shape.Width() + radius * 2 * SHADOW_BLUR_MARGIN_FACTOR;
89+ int height = shape.Height() + radius * 2 * SHADOW_BLUR_MARGIN_FACTOR;
90+
91+ if (width != last_shadow_rect_.width() || height != last_shadow_rect_.height())
92+ shaped_shadow_pixmap_ = BuildShapedShadowTexture({width, height}, radius, color, shape);
93+
94+ const auto* texture = shaped_shadow_pixmap_->texture();
95
96 if (!texture || !texture->width() || !texture->height())
97 return;
98
99- CompRect border = win_->borderRect();
100- nux::Point2D<int> shadow_offset = manager_->shadow_offset();
101-// ideally it would be -radius for the *2 part see comment in Manager::Impl::BuildShapedShadowTexture
102-// in DecorationsManager.cpp Make sure to keep these factors in sync.
103- int x = border.x() + shadow_offset.x - radius * 2 + shape.getXoffs();
104- int y = border.y() + shadow_offset.y - radius * 2 + shape.getYoffs();
105- int width = texture->width();
106- int height = texture->height();
107+ int x = border.x() + shadow_offset.x - radius * 2 + shape.XOffset();
108+ int y = border.y() + shadow_offset.y - radius * 2 + shape.YOffset();
109
110 auto* quad = &shadow_quads_[Quads::Pos(0)];
111 quad->box.setGeometry(x, y, width, height);
112@@ -715,14 +745,14 @@
113 quad->matrix.y0 = -COMP_TEX_COORD_Y(quad->matrix, quad->box.y1());
114
115 CompRect shaped_shadow_rect(x, y, width, height);
116- if (shaped_shadow_rect != last_shadow_rect_) {
117+ if (shaped_shadow_rect != last_shadow_rect_)
118+ {
119 auto const& win_region = win_->region();
120 quad->region = CompRegion(quad->box) - win_region;
121
122 last_shadow_rect_ = shaped_shadow_rect;
123 win_->updateWindowOutputExtents();
124 }
125- cwin_->addDamage(true);
126 }
127
128 void Window::Impl::Paint(GLMatrix const& transformation,
129@@ -763,11 +793,7 @@
130
131 glwin_->vertexBuffer()->begin();
132
133- // numRects is != 1 when the window is shaped
134- unsigned int num_quads = shadow_quads_.size();
135- if (win_->region().numRects() != 1)
136- num_quads = 1;
137-
138+ unsigned int num_quads = IsRectangular() ? shadow_quads_.size() : 1;
139 for (unsigned int i = 0; i < num_quads; ++i)
140 {
141 auto& quad = shadow_quads_[Quads::Pos(i)];
142@@ -775,7 +801,10 @@
143 }
144
145 if (glwin_->vertexBuffer()->end())
146- glwin_->glDrawTexture(ShadowTexture(), transformation, attrib, mask);
147+ {
148+ if (GLTexture* texture = ShadowTexture())
149+ glwin_->glDrawTexture(texture, transformation, attrib, mask);
150+ }
151
152 for (auto const& dtex : bg_textures_)
153 {
154@@ -800,6 +829,9 @@
155
156 void Window::Impl::RedrawDecorations()
157 {
158+ if (!win_->isMapped())
159+ return;
160+
161 dirty_geo_ = true;
162 cwin_->damageOutputExtents();
163 }
164@@ -1003,10 +1035,7 @@
165 void Window::UpdateDecorationPosition()
166 {
167 impl_->UpdateMonitor();
168- if (impl_->win_->region().numRects() > 1)
169- impl_->ComputeShapedShadowQuad();
170- else
171- impl_->ComputeShadowQuads();
172+ impl_->IsRectangular() ? impl_->ComputeShadowQuads() : impl_->ComputeShapedShadowQuad();
173 impl_->UpdateWindowEdgesGeo();
174 impl_->UpdateDecorationTextures();
175 impl_->UpdateForceQuitDialogPosition();
176
177=== modified file 'decorations/DecoratedWindow.h'
178--- decorations/DecoratedWindow.h 2015-08-07 18:54:07 +0000
179+++ decorations/DecoratedWindow.h 2016-07-27 10:19:13 +0000
180@@ -21,6 +21,7 @@
181 #define UNITY_DECORATED_WINDOW
182
183 #include "Introspectable.h"
184+#include <NuxCore/Property.h>
185 #include <memory>
186
187 class CompRegion;
188
189=== modified file 'decorations/DecorationsManager.cpp'
190--- decorations/DecorationsManager.cpp 2016-07-27 10:19:12 +0000
191+++ decorations/DecorationsManager.cpp 2016-07-27 10:19:13 +0000
192@@ -20,10 +20,8 @@
193 #include "DecorationsPriv.h"
194
195 #include <core/atoms.h>
196-#include <NuxGraphics/CairoGraphics.h>
197 #include <UnityCore/DBusIndicators.h>
198 #include <X11/Xatom.h>
199-#include <X11/extensions/shape.h>
200
201 #include "WindowManager.h"
202
203@@ -82,31 +80,6 @@
204 return shadow_ctx;
205 }
206
207-cu::PixmapTexture::Ptr Manager::Impl::BuildShapedShadowTexture(unsigned int radius, nux::Color const& color, DecorationsShape const& shape) {
208- //Ideally it would be shape.getWidth + radius * 2 but Cairographics::BlurSurface isn't bounded by the radius
209- //and we need to compensate by using a larger texture. Make sure to modify Window::Impl::ComputeShapedShadowQuad in
210- //DecoratedWindow.cpp if you change the factor.
211- int blur_margin_factor = 2;
212- int img_width = shape.getWidth() + radius * 2 * blur_margin_factor;
213- int img_height = shape.getHeight() + radius * 2 * blur_margin_factor;
214- nux::CairoGraphics img(CAIRO_FORMAT_ARGB32, img_width, img_height);
215- auto* img_ctx = img.GetInternalContext();
216-
217- for (int i=0; i<shape.getRectangleCount(); i++) {
218- XRectangle rect = shape.getRectangle(i);
219- cairo_rectangle(img_ctx, rect.x + radius * blur_margin_factor - shape.getXoffs(), rect.y + radius * blur_margin_factor - shape.getYoffs(), rect.width, rect.height);
220- cairo_set_source_rgba(img_ctx, color.red, color.green, color.blue, color.alpha);
221- cairo_fill(img_ctx);
222- }
223- img.BlurSurface(radius);
224-
225- cu::CairoContext shadow_ctx(img_width, img_height);
226- cairo_set_source_surface(shadow_ctx, img.GetSurface(), 0, 0);
227- cairo_paint(shadow_ctx);
228-
229- return shadow_ctx;
230-}
231-
232 void Manager::Impl::BuildActiveShadowTexture()
233 {
234 active_shadow_pixmap_ = BuildShadowTexture(manager_->active_shadow_radius(), manager_->active_shadow_color());
235
236=== modified file 'decorations/DecorationsPriv.h'
237--- decorations/DecorationsPriv.h 2016-07-27 10:19:12 +0000
238+++ decorations/DecorationsPriv.h 2016-07-27 10:19:13 +0000
239@@ -23,11 +23,13 @@
240 #include <unordered_map>
241 #include <NuxCore/NuxCore.h>
242 #include <NuxCore/Rect.h>
243+#include <NuxGraphics/CairoGraphics.h>
244 #include <UnityCore/ConnectionManager.h>
245 #include <UnityCore/Indicators.h>
246 #include <core/core.h>
247 #include <opengl/opengl.h>
248 #include <composite/composite.h>
249+#include <X11/extensions/shape.h>
250
251 #include "DecorationsShape.h"
252 #include "DecorationsDataPool.h"
253@@ -116,6 +118,7 @@
254 void SyncXShapeWithFrameRegion();
255 void SyncMenusGeometries() const;
256 bool ShouldBeDecorated() const;
257+ bool IsRectangular() const;
258 GLTexture* ShadowTexture() const;
259 unsigned ShadowRadius() const;
260 std::string const& GetMenusPanelID() const;
261@@ -126,6 +129,7 @@
262 void UpdateWindowEdgesGeo();
263 void UpdateForceQuitDialogPosition();
264 void RenderDecorationTexture(Side, nux::Geometry const&);
265+ cu::PixmapTexture::Ptr BuildShapedShadowTexture(nux::Size const&, unsigned radius, nux::Color const&, Shape const&);
266 void Paint(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask);
267 void Draw(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask);
268
269@@ -156,6 +160,7 @@
270 std::string last_title_;
271 std::string panel_id_;
272 std::vector<cu::SimpleTextureQuad> bg_textures_;
273+ cu::PixmapTexture::Ptr shaped_shadow_pixmap_;
274 std::shared_ptr<ForceQuitDialog> force_quit_;
275 InputMixer::Ptr input_mixer_;
276 Layout::Ptr top_layout_;
277@@ -166,8 +171,6 @@
278 Item::Ptr edge_borders_;
279
280 EMConverter::Ptr cv_;
281-
282- cu::PixmapTexture::Ptr shaped_shadow_pixmap_;
283 };
284
285 struct Manager::Impl : sigc::trackable
286@@ -192,7 +195,6 @@
287 void BuildActiveShadowTexture();
288 void BuildInactiveShadowTexture();
289 cu::PixmapTexture::Ptr BuildShadowTexture(unsigned radius, nux::Color const&);
290- cu::PixmapTexture::Ptr BuildShapedShadowTexture(unsigned int radius, nux::Color const& color, DecorationsShape const& shape);
291 void OnShadowOptionsChanged(bool active);
292 void OnWindowFrameChanged(bool, ::Window, std::weak_ptr<decoration::Window> const&);
293 bool OnMenuKeyActivated(std::string const&);
294
295=== modified file 'decorations/DecorationsShape.cpp'
296--- decorations/DecorationsShape.cpp 2016-07-27 10:19:12 +0000
297+++ decorations/DecorationsShape.cpp 2016-07-27 10:19:13 +0000
298@@ -17,86 +17,91 @@
299 * Authored by: Eleni Maria Stea <elenimaria.stea@canonical.com>
300 */
301
302-#include <string.h>
303+#include "DecorationsShape.h"
304+
305+#include <core/core.h>
306+#include <NuxCore/Logger.h>
307 #include <X11/extensions/shape.h>
308-#include "DecoratedWindow.h"
309-#include "DecorationsShape.h"
310-
311-bool DecorationsShape::initShape(XID win)
312+
313+namespace unity
314+{
315+namespace decoration
316+{
317+namespace
318+{
319+DECLARE_LOGGER(logger, "unity.decoration.shape");
320+}
321+
322+Shape::Shape(Window xid)
323 {
324 Bool buse, cuse;
325 int bx, by, cx, cy;
326 unsigned int bw, bh, cw, ch;
327 Display *dpy = screen->dpy();
328
329- XShapeQueryExtents(dpy, win, &buse, &bx, &by, &bw, &bh, &cuse, &cx, &cy, &cw, &ch);
330+ XShapeQueryExtents(dpy, xid, &buse, &bx, &by, &bw, &bh, &cuse, &cx, &cy, &cw, &ch);
331
332 int kind;
333- if (buse) {
334- width = bw;
335- height = bh;
336- xoffs = bx;
337- yoffs = by;
338+
339+ if (buse)
340+ {
341+ width_ = bw;
342+ height_ = bh;
343+ xoffs_ = bx;
344+ yoffs_ = by;
345 kind = ShapeBounding;
346 }
347- else if (cuse) {
348- width = cw;
349- height = ch;
350- xoffs = cx;
351- yoffs = cy;
352+ else if (cuse)
353+ {
354+ width_ = cw;
355+ height_ = ch;
356+ xoffs_ = cx;
357+ yoffs_ = cy;
358 kind = ShapeClip;
359 }
360- else {
361- fprintf(stderr, "XShapeQueryExtend returned no extends.\n");
362- return false;
363+ else
364+ {
365+ LOG_ERROR(logger) << "XShapeQueryExtend returned no extents";
366+ return;
367 }
368
369 int rect_count, rect_order;
370- XRectangle *rectangles;
371- if (!(rectangles = XShapeGetRectangles(dpy, win, kind, &rect_count, &rect_order))) {
372- fprintf(stderr, "Failed to get shape rectangles\n");
373- return false;
374- }
375-
376- for (int i=0; i< rect_count; i++) {
377- rects.push_back(rectangles[i]);
378- }
379-
380- XFree(rectangles);
381- return true;
382-}
383-
384-const XRectangle& DecorationsShape::getRectangle(int idx) const
385-{
386- return rects[idx];
387-}
388-
389-int DecorationsShape::getRectangleCount() const
390-{
391- return (int)rects.size();
392-}
393-
394-int DecorationsShape::getWidth() const
395-{
396- return width;
397-}
398-
399-int DecorationsShape::getHeight() const
400-{
401- return height;
402-}
403-
404-int DecorationsShape::getXoffs() const
405-{
406- return xoffs;
407-}
408-
409-int DecorationsShape::getYoffs() const
410-{
411- return yoffs;
412-}
413-void DecorationsShape::clear()
414-{
415- width = height = 0;
416- rects.clear();
417-}
418+ std::unique_ptr<XRectangle[], int(*)(void*)> rectangles(XShapeGetRectangles(dpy, xid, kind, &rect_count, &rect_order), XFree);
419+
420+ if (!rectangles)
421+ {
422+ LOG_ERROR(logger) << "Failed to get shape rectangles";
423+ return;
424+ }
425+
426+ for (int i = 0; i < rect_count; ++i)
427+ rectangles_.push_back(rectangles[i]);
428+}
429+
430+std::vector<XRectangle> const& Shape::GetRectangles() const
431+{
432+ return rectangles_;
433+}
434+
435+int Shape::Width() const
436+{
437+ return width_;
438+}
439+
440+int Shape::Height() const
441+{
442+ return height_;
443+}
444+
445+int Shape::XOffset() const
446+{
447+ return xoffs_;
448+}
449+
450+int Shape::YOffset() const
451+{
452+ return yoffs_;
453+}
454+
455+} // decoration namespace
456+} // unity namespace
457
458=== modified file 'decorations/DecorationsShape.h'
459--- decorations/DecorationsShape.h 2016-07-27 10:19:12 +0000
460+++ decorations/DecorationsShape.h 2016-07-27 10:19:13 +0000
461@@ -20,24 +20,35 @@
462 #ifndef DECORATIONS_SHAPE_H_
463 #define DECORATIONS_SHAPE_H_
464
465-#include "WindowManager.h"
466-#include "DecoratedWindow.h"
467-
468-class DecorationsShape
469-{
470+#include <X11/Xlib.h>
471+#include <vector>
472+
473+namespace unity
474+{
475+namespace decoration
476+{
477+class Shape
478+{
479+public:
480+ Shape(Window);
481+
482+ int Width() const;
483+ int Height() const;
484+ int XOffset() const;
485+ int YOffset() const;
486+
487+ std::vector<XRectangle> const& GetRectangles() const;
488+
489 private:
490- std::vector<XRectangle> rects;
491- int width, height;
492- int xoffs, yoffs;
493+ int width_;
494+ int height_;
495+ int xoffs_;
496+ int yoffs_;
497
498-public:
499- bool initShape(XID win);
500- const XRectangle& getRectangle(int idx) const;
501- int getRectangleCount() const;
502- int getWidth() const;
503- int getHeight() const;
504- int getXoffs() const;
505- int getYoffs() const;
506- void clear();
507+ std::vector<XRectangle> rectangles_;
508 };
509+
510+} // decoration namespace
511+} // unity namespace
512+
513 #endif //DECORATIONS_SHAPE_H_
514
515=== modified file 'plugins/unityshell/src/unityshell.cpp'
516--- plugins/unityshell/src/unityshell.cpp 2016-07-27 10:19:12 +0000
517+++ plugins/unityshell/src/unityshell.cpp 2016-07-27 10:19:13 +0000
518@@ -3357,6 +3357,7 @@
519 PluginAdapter::Default().UpdateShowDesktopState();
520 break;
521 case CompWindowNotifyBeforeDestroy:
522+ deco_win_->Undecorate();
523 being_destroyed.emit();
524 break;
525 case CompWindowNotifyMinimize:
526
527=== modified file 'unity-shared/CompizUtils.cpp'
528--- unity-shared/CompizUtils.cpp 2016-07-27 10:19:12 +0000
529+++ unity-shared/CompizUtils.cpp 2016-07-27 10:19:13 +0000
530@@ -190,11 +190,7 @@
531 if (win->wmType() & (CompWindowTypeDockMask | CompWindowTypeDesktopMask))
532 return elements;
533
534- auto const& region = win->region();
535- bool rectangular = (region.numRects() == 1);
536- bool alpha = win->alpha();
537-
538- if (alpha)
539+ if (win->alpha())
540 {
541 if (wf == WindowFilter::CLIENTSIDE_DECORATED)
542 {
543@@ -205,7 +201,7 @@
544
545 return elements;
546 }
547- else if (!rectangular) // Non-rectangular windows with alpha channel
548+ else if (win->region().numRects() != 1) // Non-rectangular windows with alpha channel
549 {
550 return elements;
551 }
552@@ -220,11 +216,14 @@
553 if (win->actions() & CompWindowActionResizeMask)
554 elements |= DecorationElement::EDGE;
555
556+ auto const& region = win->region();
557+ bool rectangular = (region.numRects() == 1);
558+
559 if (rectangular && (win->mwmDecor() & (MwmDecorAll | MwmDecorTitle)))
560 elements |= DecorationElement::BORDER;
561 }
562
563- if (alpha && !(elements & DecorationElement::BORDER) && !(win->mwmDecor() & MwmDecorBorder))
564+ if (win->alpha() && !(elements & DecorationElement::BORDER) && !(win->mwmDecor() & MwmDecorBorder))
565 elements &= ~DecorationElement::SHADOW;
566
567 return elements;