diff --git a/widget/gtk2/nsWindow.cpp b/widget/gtk2/nsWindow.cpp index 8025a29c78f..2b4cb8fe6c8 100644 --- a/widget/gtk2/nsWindow.cpp +++ b/widget/gtk2/nsWindow.cpp @@ -624,6 +624,13 @@ nsWindow::Destroy(void) } mLayerManager = nsnull; + // It is safe to call DestroyeCompositor several times (here and + // in the parent class) since it will take effect only once. + // The reason we call it here is because on gtk platforms we need + // to destroy the compositor before we destroy the gdk window (which + // destroys the the gl context attached to it). + DestroyCompositor(); + ClearCachedResources(); g_signal_handlers_disconnect_by_func(gtk_settings_get_default(), diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index 558e74d1dd9..b1de09c70ce 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -110,7 +110,7 @@ nsBaseWidget::nsBaseWidget() } -static void DestroyCompositor(CompositorParent* aCompositorParent, +static void DeferredDestroyCompositor(CompositorParent* aCompositorParent, CompositorChild* aCompositorChild, Thread* aCompositorThread) { @@ -120,6 +120,27 @@ static void DestroyCompositor(CompositorParent* aCompositorParent, aCompositorChild->Release(); } +void nsBaseWidget::DestroyCompositor() +{ + if (mCompositorChild) { + mCompositorChild->SendWillStop(); + + // The call just made to SendWillStop can result in IPC from the + // CompositorParent to the CompositorChild (e.g. caused by the destruction + // of shared memory). We need to ensure this gets processed by the + // CompositorChild before it gets destroyed. It suffices to ensure that + // events already in the MessageLoop get processed before the + // CompositorChild is destroyed, so we add a task to the MessageLoop to + // handle compositor desctruction. + MessageLoop::current()->PostTask(FROM_HERE, + NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent, + mCompositorChild, mCompositorThread)); + // The DestroyCompositor task we just added to the MessageLoop will handle + // releasing mCompositorParent and mCompositorChild. + mCompositorParent.forget(); + mCompositorChild.forget(); + } +} //------------------------------------------------------------------------- // @@ -138,25 +159,7 @@ nsBaseWidget::~nsBaseWidget() mLayerManager = nsnull; } - if (mCompositorChild) { - mCompositorChild->SendWillStop(); - - // The call just made to SendWillStop can result in IPC from the - // CompositorParent to the CompositorChild (e.g. caused by the destruction - // of shared memory). We need to ensure this gets processed by the - // CompositorChild before it gets destroyed. It suffices to ensure that - // events already in the MessageLoop get processed before the - // CompositorChild is destroyed, so we add a task to the MessageLoop to - // handle compositor desctruction. - MessageLoop::current()-> - PostTask(FROM_HERE, - NewRunnableFunction(DestroyCompositor, mCompositorParent, - mCompositorChild, mCompositorThread)); - // The DestroyCompositor task we just added to the MessageLoop will handle - // releasing mCompositorParent and mCompositorChild. - mCompositorParent.forget(); - mCompositorChild.forget(); - } + DestroyCompositor(); #ifdef NOISY_WIDGET_LEAKS gNumWidgets--; diff --git a/widget/xpwidgets/nsBaseWidget.h b/widget/xpwidgets/nsBaseWidget.h index c84fa9eb7bf..0ccb932cc10 100644 --- a/widget/xpwidgets/nsBaseWidget.h +++ b/widget/xpwidgets/nsBaseWidget.h @@ -266,6 +266,17 @@ protected: BasicLayerManager* CreateBasicLayerManager(); protected: + /** + * Starts the OMTC compositor destruction sequence. + * + * When this function returns, the compositor should not be + * able to access the opengl context anymore. + * It is safe to call it several times if platform implementations + * require the compositor to be destroyed before ~nsBaseWidget is + * reached (This is the case with gtk2 for instance). + */ + void DestroyCompositor(); + void* mClientData; ViewWrapper* mViewWrapperPtr; EVENT_CALLBACK mEventCallback;