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

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Neil J. Patel
Approved revision: no longer in the source branch.
Merged at revision: 2764
Proposed branch: lp:~3v1n0/unity/keep-texture-pixmap-friends-6.0
Merge into: lp:unity/6.0
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-6.0
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Review via email: mp+128018@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.

This is safer and cleaner than the previously added workaround.

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
=== modified file 'plugins/unityshell/src/unityshell.cpp'
--- plugins/unityshell/src/unityshell.cpp 2012-10-02 14:09:06 +0000
+++ plugins/unityshell/src/unityshell.cpp 2012-10-04 14:10:28 +0000
@@ -200,18 +200,18 @@
200 failed = true;200 failed = true;
201 }201 }
202 }202 }
203 203
204 //In case of software rendering then enable lowgfx mode.204 //In case of software rendering then enable lowgfx mode.
205 std::string renderer = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_RENDERER)));205 std::string renderer = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_RENDERER)));
206 206
207 if (strstr(renderer.c_str(), "Software Rasterizer") ||207 if (renderer.find("Software Rasterizer") != std::string::npos ||
208 strstr(renderer.c_str(), "Mesa X11") ||208 renderer.find("Mesa X11") != std::string::npos ||
209 strstr(renderer.c_str(), "LLVM") ||209 renderer.find("LLVM") != std::string::npos ||
210 strstr(renderer.c_str(), "on softpipe") ||210 renderer.find("on softpipe") != std::string::npos ||
211 (getenv("UNITY_LOW_GFX_MODE") != NULL && atoi(getenv("UNITY_LOW_GFX_MODE")) == 1))211 (getenv("UNITY_LOW_GFX_MODE") != NULL && atoi(getenv("UNITY_LOW_GFX_MODE")) == 1))
212 {212 {
213 Settings::Instance().SetLowGfxMode(true);213 Settings::Instance().SetLowGfxMode(true);
214 }214 }
215#endif215#endif
216216
217 if (!failed)217 if (!failed)
@@ -3406,32 +3406,51 @@
3406}3406}
3407}3407}
34083408
3409struct UnityWindow::PixmapTexture
3410{
3411 PixmapTexture(unsigned width, unsigned height)
3412 : w_(width)
3413 , h_(height)
3414 , pixmap_(XCreatePixmap(screen->dpy(), screen->root(), w_, h_, 32))
3415 , texture_(GLTexture::bindPixmapToTexture(pixmap_, w_, h_, 32))
3416 {}
3417
3418 ~PixmapTexture()
3419 {
3420 texture_.clear();
3421
3422 if (pixmap_)
3423 XFreePixmap(screen->dpy(), pixmap_);
3424 }
3425
3426 unsigned w_;
3427 unsigned h_;
3428 Pixmap pixmap_;
3429 GLTexture::List texture_;
3430};
3431
3409struct UnityWindow::CairoContext3432struct UnityWindow::CairoContext
3410{3433{
3411 CairoContext(unsigned width, unsigned height)3434 CairoContext(unsigned width, unsigned height)
3412 : w_(width)3435 : w_(width)
3413 , h_(height)3436 , h_(height)
3414 , pixmap_(XCreatePixmap(screen->dpy(), screen->root(), w_, h_, 32))3437 , pixmap_texture_(std::make_shared<PixmapTexture>(w_, h_))
3415 , texture_(GLTexture::bindPixmapToTexture(pixmap_, w_, h_, 32, compiz::opengl::ExternallyManaged)) //FIXME: This is a workaround, should create a new wrapper class which owns the texture and the cairo context.
3416 , surface_(nullptr)3438 , surface_(nullptr)
3417 , cr_(nullptr)3439 , cr_(nullptr)
3418 {3440 {
3419 Screen *xscreen = ScreenOfDisplay(screen->dpy(), screen->screenNum());3441 Screen *xscreen = ScreenOfDisplay(screen->dpy(), screen->screenNum());
3420 XRenderPictFormat* format = XRenderFindStandardFormat(screen->dpy(), PictStandardARGB32);3442 XRenderPictFormat* format = XRenderFindStandardFormat(screen->dpy(), PictStandardARGB32);
34213443 surface_ = cairo_xlib_surface_create_with_xrender_format(screen->dpy(),
3422 if (texture_.empty())3444 pixmap_texture_->pixmap_,
3423 return;3445 xscreen, format,
34243446 w_, h_);
3425 surface_ = cairo_xlib_surface_create_with_xrender_format(screen->dpy(), pixmap_,3447 cr_ = cairo_create(surface_);
3426 xscreen, format,3448
3427 width, height);3449 // clear
3428 cr_ = cairo_create(surface_);3450 cairo_save(cr_);
34293451 cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
3430 // clear3452 cairo_paint(cr_);
3431 cairo_save(cr_);3453 cairo_restore(cr_);
3432 cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
3433 cairo_paint(cr_);
3434 cairo_restore(cr_);
3435 }3454 }
34363455
3437 ~CairoContext()3456 ~CairoContext()
@@ -3441,15 +3460,11 @@
34413460
3442 if (surface_)3461 if (surface_)
3443 cairo_surface_destroy(surface_);3462 cairo_surface_destroy(surface_);
3444
3445 if (pixmap_)
3446 XFreePixmap(screen->dpy(), pixmap_);
3447 }3463 }
34483464
3449 unsigned w_;3465 unsigned w_;
3450 unsigned h_;3466 unsigned h_;
3451 Pixmap pixmap_;3467 PixmapTexturePtr pixmap_texture_;
3452 GLTexture::List texture_;
3453 cairo_surface_t* surface_;3468 cairo_surface_t* surface_;
3454 cairo_t *cr_;3469 cairo_t *cr_;
3455};3470};
@@ -3665,16 +3680,16 @@
36653680
3666void UnityWindow::BuildDecorationTexture()3681void UnityWindow::BuildDecorationTexture()
3667{3682{
3668 if (!decoration_tex_.empty())3683 if (decoration_tex_)
3669 return;3684 return;
36703685
3671 auto const& border_extents = window->border();3686 auto const& border_extents = window->border();
36723687
3673 if (WindowManager::Default()->IsWindowDecorated(window->id()) && border_extents.top > 0)3688 if (WindowManager::Default()->IsWindowDecorated(window->id()) && border_extents.top > 0)
3674 {3689 {
3675 CairoContext context(window->borderRect().width(), border_extents.top);3690 CairoContext context(window->borderRect().width(), window->border().top);
3676 RenderDecoration(context);3691 RenderDecoration(context);
3677 decoration_tex_ = context.texture_;3692 decoration_tex_ = context.pixmap_texture_;
3678 }3693 }
3679}3694}
36803695
@@ -3726,8 +3741,8 @@
37263741
3727void UnityWindow::CleanupCachedTextures()3742void UnityWindow::CleanupCachedTextures()
3728{3743{
3729 decoration_tex_.clear();3744 decoration_tex_.reset();
3730 decoration_selected_tex_.clear();3745 decoration_selected_tex_.reset();
3731 decoration_title_.clear();3746 decoration_title_.clear();
3732}3747}
37333748
@@ -3736,7 +3751,7 @@
3736 CompRegion const& region,3751 CompRegion const& region,
3737 unsigned int mask)3752 unsigned int mask)
3738{3753{
3739 ScaleWindow *scale_win = ScaleWindow::get(window);3754 ScaleWindow* scale_win = ScaleWindow::get(window);
3740 scale_win->scalePaintDecoration(attrib, transform, region, mask);3755 scale_win->scalePaintDecoration(attrib, transform, region, mask);
37413756
3742 if (!scale_win->hasSlot()) // animation not finished3757 if (!scale_win->hasSlot()) // animation not finished
@@ -3760,21 +3775,22 @@
3760 if (!highlighted)3775 if (!highlighted)
3761 {3776 {
3762 BuildDecorationTexture();3777 BuildDecorationTexture();
3763 DrawTexture(decoration_tex_, attrib, transform, mask, x, y, pos.scale);3778
3779 if (decoration_tex_)
3780 DrawTexture(decoration_tex_->texture_, attrib, transform, mask, x, y, pos.scale);
3781
3764 close_button_geo_.Set(0, 0, 0, 0);3782 close_button_geo_.Set(0, 0, 0, 0);
3765 }3783 }
3766 else3784 else
3767 {3785 {
3768 auto const& decoration_extents = window->border();3786 auto const& decoration_extents = window->border();
3769 int width = scaled_geo.width;3787 unsigned width = scaled_geo.width;
3770 int height = decoration_extents.top;3788 unsigned height = decoration_extents.top;
3771 bool redraw_decoration = true;3789 bool redraw_decoration = true;
37723790
3773 if (!decoration_selected_tex_.empty())3791 if (decoration_selected_tex_)
3774 {3792 {
3775 GLTexture* texture = decoration_selected_tex_.front();3793 if (decoration_selected_tex_->w_ == width && decoration_selected_tex_->h_ == height)
3776
3777 if (texture->width() == width && texture->height() == height)
3778 {3794 {
3779 if (decoration_title_ == WindowManager::Default()->GetWindowName(window->id()))3795 if (decoration_title_ == WindowManager::Default()->GetWindowName(window->id()))
3780 redraw_decoration = false;3796 redraw_decoration = false;
@@ -3783,16 +3799,24 @@
37833799
3784 if (redraw_decoration)3800 if (redraw_decoration)
3785 {3801 {
3786 CairoContext context(width, height);3802 if (width != 0 && height != 0)
3787 RenderDecoration(context, pos.scale);3803 {
3804 CairoContext context(width, height);
3805 RenderDecoration(context, pos.scale);
37883806
3789 // Draw window title3807 // Draw window title
3790 int text_x = scale::decoration::ITEMS_PADDING * 2 + scale::decoration::CLOSE_SIZE;3808 int text_x = scale::decoration::ITEMS_PADDING * 2 + scale::decoration::CLOSE_SIZE;
3791 RenderText(context, text_x, 0.0, width - scale::decoration::ITEMS_PADDING, height);3809 RenderText(context, text_x, 0.0, width - scale::decoration::ITEMS_PADDING, height);
3792 decoration_selected_tex_ = context.texture_;3810 decoration_selected_tex_ = context.pixmap_texture_;
3811 }
3812 else
3813 {
3814 decoration_selected_tex_.reset();
3815 }
3793 }3816 }
37943817
3795 DrawTexture(decoration_selected_tex_, attrib, transform, mask, x, y);3818 if (decoration_selected_tex_)
3819 DrawTexture(decoration_selected_tex_->texture_, attrib, transform, mask, x, y);
37963820
3797 x += scale::decoration::ITEMS_PADDING;3821 x += scale::decoration::ITEMS_PADDING;
3798 y += (height - scale::decoration::CLOSE_SIZE) / 2.0f;3822 y += (height - scale::decoration::CLOSE_SIZE) / 2.0f;
@@ -3819,7 +3843,7 @@
38193843
3820nux::Geometry UnityWindow::GetScaledGeometry()3844nux::Geometry UnityWindow::GetScaledGeometry()
3821{3845{
3822 ScaleWindow *scale_win = ScaleWindow::get(window);3846 ScaleWindow* scale_win = ScaleWindow::get(window);
38233847
3824 ScalePosition const& pos = scale_win->getCurrentPosition();3848 ScalePosition const& pos = scale_win->getCurrentPosition();
3825 auto const& border_rect = window->borderRect();3849 auto const& border_rect = window->borderRect();
38263850
=== modified file 'plugins/unityshell/src/unityshell.h'
--- plugins/unityshell/src/unityshell.h 2012-09-28 22:33:55 +0000
+++ plugins/unityshell/src/unityshell.h 2012-10-04 14:10:28 +0000
@@ -406,6 +406,8 @@
406private:406private:
407 typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>407 typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>
408 UnityMinimizedHandler;408 UnityMinimizedHandler;
409 struct PixmapTexture;
410 typedef std::shared_ptr<PixmapTexture> PixmapTexturePtr;
409 struct CairoContext;411 struct CairoContext;
410412
411 void DoEnableFocus ();413 void DoEnableFocus ();
@@ -460,8 +462,8 @@
460 static GLTexture::List close_normal_tex_;462 static GLTexture::List close_normal_tex_;
461 static GLTexture::List close_prelight_tex_;463 static GLTexture::List close_prelight_tex_;
462 static GLTexture::List close_pressed_tex_;464 static GLTexture::List close_pressed_tex_;
463 GLTexture::List decoration_tex_;465 PixmapTexturePtr decoration_tex_;
464 GLTexture::List decoration_selected_tex_;466 PixmapTexturePtr decoration_selected_tex_;
465 std::string decoration_title_;467 std::string decoration_title_;
466 compiz::WindowInputRemoverLock::Weak input_remover_;468 compiz::WindowInputRemoverLock::Weak input_remover_;
467 panel::WindowState close_icon_state_;469 panel::WindowState close_icon_state_;

Subscribers

People subscribed via source and target branches