Merge lp:~3v1n0/unity/keep-texture-pixmap-friends into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Neil J. Patel
Approved revision: no longer in the source branch.
Merged at revision: 2798
Proposed branch: lp:~3v1n0/unity/keep-texture-pixmap-friends
Merge into: lp:unity
Diff against target: 253 lines (+81/-55)
2 files modified
plugins/unityshell/src/unityshell.cpp (+77/-53)
plugins/unityshell/src/unityshell.h (+4/-2)
To merge this branch: bzr merge lp:~3v1n0/unity/keep-texture-pixmap-friends
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Review via email: mp+128019@code.launchpad.net

Commit message

UnityWindow: add PixmapTexture struct: never separate a binded texture to its pixmap

Or it will lead to crashes. Now we cache both the GLTexture and the binded XPixmap, so
that we delete both together and there won't be crashes.

Texutures binded to Pixmaps should not be alive when the binded pixmap has been
destroyed. So, now we have a new PixmapTexture struct that keeps both the data
structures alive.
We now use a smart pointer of PixmapTexture to cache both the temporary decorations,
inside a CairoContext, and the ones at class level.

Description of the change

Texutures binded to Pixmaps should not be alive when the binded pixmap has been destroyed. So, now we have a new PixmapTexture struct that keeps both the data structures alive.
We now use a smart pointer of PixmapTexture to cache both the temporary decorations, inside a CairoContext, and the ones at class level.

To post a comment you must log in.
Revision history for this message
Neil J. Patel (njpatel) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/unityshell.cpp'
2--- plugins/unityshell/src/unityshell.cpp 2012-10-01 23:32:49 +0000
3+++ plugins/unityshell/src/unityshell.cpp 2012-10-04 14:11:27 +0000
4@@ -214,18 +214,18 @@
5 failed = true;
6 }
7 }
8-
9+
10 //In case of software rendering then enable lowgfx mode.
11 std::string renderer = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_RENDERER)));
12-
13- if (strstr(renderer.c_str(), "Software Rasterizer") ||
14- strstr(renderer.c_str(), "Mesa X11") ||
15- strstr(renderer.c_str(), "LLVM") ||
16- strstr(renderer.c_str(), "on softpipe") ||
17+
18+ if (renderer.find("Software Rasterizer") != std::string::npos ||
19+ renderer.find("Mesa X11") != std::string::npos ||
20+ renderer.find("LLVM") != std::string::npos ||
21+ renderer.find("on softpipe") != std::string::npos ||
22 (getenv("UNITY_LOW_GFX_MODE") != NULL && atoi(getenv("UNITY_LOW_GFX_MODE")) == 1))
23- {
24- Settings::Instance().SetLowGfxMode(true);
25- }
26+ {
27+ Settings::Instance().SetLowGfxMode(true);
28+ }
29 #endif
30
31 if (!failed)
32@@ -3438,32 +3438,51 @@
33 GLTexture::List UnityWindow::close_pressed_tex_;
34 GLTexture::List UnityWindow::glow_texture_;
35
36+struct UnityWindow::PixmapTexture
37+{
38+ PixmapTexture(unsigned width, unsigned height)
39+ : w_(width)
40+ , h_(height)
41+ , pixmap_(XCreatePixmap(screen->dpy(), screen->root(), w_, h_, 32))
42+ , texture_(GLTexture::bindPixmapToTexture(pixmap_, w_, h_, 32))
43+ {}
44+
45+ ~PixmapTexture()
46+ {
47+ texture_.clear();
48+
49+ if (pixmap_)
50+ XFreePixmap(screen->dpy(), pixmap_);
51+ }
52+
53+ unsigned w_;
54+ unsigned h_;
55+ Pixmap pixmap_;
56+ GLTexture::List texture_;
57+};
58+
59 struct UnityWindow::CairoContext
60 {
61 CairoContext(unsigned width, unsigned height)
62 : w_(width)
63 , h_(height)
64- , pixmap_(XCreatePixmap(screen->dpy(), screen->root(), w_, h_, 32))
65- , texture_(GLTexture::bindPixmapToTexture(pixmap_, w_, h_, 32))
66+ , pixmap_texture_(std::make_shared<PixmapTexture>(w_, h_))
67 , surface_(nullptr)
68 , cr_(nullptr)
69 {
70- Screen *xscreen = ScreenOfDisplay(screen->dpy(), screen->screenNum());
71- XRenderPictFormat* format = XRenderFindStandardFormat(screen->dpy(), PictStandardARGB32);
72-
73- if (texture_.empty())
74- return;
75-
76- surface_ = cairo_xlib_surface_create_with_xrender_format(screen->dpy(), pixmap_,
77- xscreen, format,
78- width, height);
79- cr_ = cairo_create(surface_);
80-
81- // clear
82- cairo_save(cr_);
83- cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
84- cairo_paint(cr_);
85- cairo_restore(cr_);
86+ Screen *xscreen = ScreenOfDisplay(screen->dpy(), screen->screenNum());
87+ XRenderPictFormat* format = XRenderFindStandardFormat(screen->dpy(), PictStandardARGB32);
88+ surface_ = cairo_xlib_surface_create_with_xrender_format(screen->dpy(),
89+ pixmap_texture_->pixmap_,
90+ xscreen, format,
91+ w_, h_);
92+ cr_ = cairo_create(surface_);
93+
94+ // clear
95+ cairo_save(cr_);
96+ cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
97+ cairo_paint(cr_);
98+ cairo_restore(cr_);
99 }
100
101 ~CairoContext()
102@@ -3473,15 +3492,11 @@
103
104 if (surface_)
105 cairo_surface_destroy(surface_);
106-
107- if (pixmap_)
108- XFreePixmap(screen->dpy(), pixmap_);
109 }
110
111 unsigned w_;
112 unsigned h_;
113- Pixmap pixmap_;
114- GLTexture::List texture_;
115+ PixmapTexturePtr pixmap_texture_;
116 cairo_surface_t* surface_;
117 cairo_t *cr_;
118 };
119@@ -3697,16 +3712,16 @@
120
121 void UnityWindow::BuildDecorationTexture()
122 {
123- if (!decoration_tex_.empty())
124+ if (decoration_tex_)
125 return;
126
127 auto const& border_extents = window->border();
128
129 if (WindowManager::Default()->IsWindowDecorated(window->id()) && border_extents.top > 0)
130 {
131- CairoContext context(window->borderRect().width(), border_extents.top);
132+ CairoContext context(window->borderRect().width(), window->border().top);
133 RenderDecoration(context);
134- decoration_tex_ = context.texture_;
135+ decoration_tex_ = context.pixmap_texture_;
136 }
137 }
138
139@@ -3765,8 +3780,8 @@
140
141 void UnityWindow::CleanupCachedTextures()
142 {
143- decoration_tex_.clear();
144- decoration_selected_tex_.clear();
145+ decoration_tex_.reset();
146+ decoration_selected_tex_.reset();
147 decoration_title_.clear();
148 }
149
150@@ -3775,7 +3790,7 @@
151 CompRegion const& region,
152 unsigned int mask)
153 {
154- ScaleWindow *scale_win = ScaleWindow::get(window);
155+ ScaleWindow* scale_win = ScaleWindow::get(window);
156 scale_win->scalePaintDecoration(attrib, transform, region, mask);
157
158 if (!scale_win->hasSlot()) // animation not finished
159@@ -3799,21 +3814,22 @@
160 if (!highlighted)
161 {
162 BuildDecorationTexture();
163- DrawTexture(decoration_tex_, attrib, transform, mask, x, y, pos.scale);
164+
165+ if (decoration_tex_)
166+ DrawTexture(decoration_tex_->texture_, attrib, transform, mask, x, y, pos.scale);
167+
168 close_button_geo_.Set(0, 0, 0, 0);
169 }
170 else
171 {
172 auto const& decoration_extents = window->border();
173- int width = scaled_geo.width;
174- int height = decoration_extents.top;
175+ unsigned width = scaled_geo.width;
176+ unsigned height = decoration_extents.top;
177 bool redraw_decoration = true;
178
179- if (!decoration_selected_tex_.empty())
180+ if (decoration_selected_tex_)
181 {
182- GLTexture* texture = decoration_selected_tex_.front();
183-
184- if (texture->width() == width && texture->height() == height)
185+ if (decoration_selected_tex_->w_ == width && decoration_selected_tex_->h_ == height)
186 {
187 if (decoration_title_ == WindowManager::Default()->GetWindowName(window->id()))
188 redraw_decoration = false;
189@@ -3822,16 +3838,24 @@
190
191 if (redraw_decoration)
192 {
193- CairoContext context(width, height);
194- RenderDecoration(context, pos.scale);
195+ if (width != 0 && height != 0)
196+ {
197+ CairoContext context(width, height);
198+ RenderDecoration(context, pos.scale);
199
200- // Draw window title
201- int text_x = scale::decoration::ITEMS_PADDING * 2 + scale::decoration::CLOSE_SIZE;
202- RenderText(context, text_x, 0.0, width - scale::decoration::ITEMS_PADDING, height);
203- decoration_selected_tex_ = context.texture_;
204+ // Draw window title
205+ int text_x = scale::decoration::ITEMS_PADDING * 2 + scale::decoration::CLOSE_SIZE;
206+ RenderText(context, text_x, 0.0, width - scale::decoration::ITEMS_PADDING, height);
207+ decoration_selected_tex_ = context.pixmap_texture_;
208+ }
209+ else
210+ {
211+ decoration_selected_tex_.reset();
212+ }
213 }
214
215- DrawTexture(decoration_selected_tex_, attrib, transform, mask, x, y);
216+ if (decoration_selected_tex_)
217+ DrawTexture(decoration_selected_tex_->texture_, attrib, transform, mask, x, y);
218
219 x += scale::decoration::ITEMS_PADDING;
220 y += (height - scale::decoration::CLOSE_SIZE) / 2.0f;
221@@ -3858,7 +3882,7 @@
222
223 nux::Geometry UnityWindow::GetScaledGeometry()
224 {
225- ScaleWindow *scale_win = ScaleWindow::get(window);
226+ ScaleWindow* scale_win = ScaleWindow::get(window);
227
228 ScalePosition const& pos = scale_win->getCurrentPosition();
229 auto const& border_rect = window->borderRect();
230
231=== modified file 'plugins/unityshell/src/unityshell.h'
232--- plugins/unityshell/src/unityshell.h 2012-10-01 22:25:28 +0000
233+++ plugins/unityshell/src/unityshell.h 2012-10-04 14:11:27 +0000
234@@ -408,6 +408,8 @@
235 private:
236 typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>
237 UnityMinimizedHandler;
238+ struct PixmapTexture;
239+ typedef std::shared_ptr<PixmapTexture> PixmapTexturePtr;
240 struct CairoContext;
241
242 void DoEnableFocus ();
243@@ -467,8 +469,8 @@
244 static GLTexture::List close_prelight_tex_;
245 static GLTexture::List close_pressed_tex_;
246 static GLTexture::List glow_texture_;
247- GLTexture::List decoration_tex_;
248- GLTexture::List decoration_selected_tex_;
249+ PixmapTexturePtr decoration_tex_;
250+ PixmapTexturePtr decoration_selected_tex_;
251 std::string decoration_title_;
252 compiz::WindowInputRemoverLock::Weak input_remover_;
253 panel::WindowState close_icon_state_;