mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 862556 - Make nsChildView.mm::DrawWindowOverlay thread safe. r=nrc
This commit is contained in:
parent
d54af1672c
commit
4dc092eab6
@ -1160,6 +1160,9 @@ BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags)
|
||||
{
|
||||
if (mWidget) {
|
||||
mWidget->PrepareWindowEffects();
|
||||
}
|
||||
BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
|
||||
ForwardTransaction();
|
||||
|
||||
|
@ -98,6 +98,7 @@ void
|
||||
LayerManagerComposite::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
mCompositor->GetWidget()->CleanupWindowEffects();
|
||||
if (mRoot) {
|
||||
RootLayer()->Destroy();
|
||||
}
|
||||
|
@ -168,6 +168,8 @@ LayerManagerOGL::Destroy()
|
||||
mRoot = nullptr;
|
||||
}
|
||||
|
||||
mWidget->CleanupWindowEffects();
|
||||
|
||||
if (!mGLContext)
|
||||
return;
|
||||
|
||||
@ -849,6 +851,7 @@ LayerManagerOGL::Render()
|
||||
#endif
|
||||
|
||||
// Allow widget to render a custom background.
|
||||
mWidget->PrepareWindowEffects();
|
||||
mWidget->DrawWindowUnderlay(this, rect);
|
||||
|
||||
// Reset some state that might of been clobbered by the underlay.
|
||||
|
@ -523,7 +523,9 @@ public:
|
||||
|
||||
virtual void CreateCompositor();
|
||||
virtual gfxASurface* GetThebesSurface();
|
||||
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect);
|
||||
virtual void PrepareWindowEffects() MOZ_OVERRIDE;
|
||||
virtual void CleanupWindowEffects() MOZ_OVERRIDE;
|
||||
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) MOZ_OVERRIDE;
|
||||
|
||||
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
|
||||
|
||||
@ -610,7 +612,21 @@ protected:
|
||||
nsWeakPtr mAccessible;
|
||||
#endif
|
||||
|
||||
|
||||
nsRefPtr<gfxASurface> mTempThebesSurface;
|
||||
|
||||
mozilla::Mutex mEffectsLock;
|
||||
|
||||
// May be accessed from any thread, protected
|
||||
// by mEffectsLock.
|
||||
bool mShowsResizeIndicator;
|
||||
nsIntRect mResizeIndicatorRect;
|
||||
bool mHasRoundedBottomCorners;
|
||||
int mDevPixelCornerRadius;
|
||||
|
||||
// Compositor thread only
|
||||
bool mFailedResizerImage;
|
||||
bool mFailedCornerMaskImage;
|
||||
nsRefPtr<mozilla::gl::TextureImage> mResizerImage;
|
||||
nsRefPtr<mozilla::gl::TextureImage> mCornerMaskImage;
|
||||
|
||||
@ -623,8 +639,6 @@ protected:
|
||||
// ** We'll need to reinitialize this if the backing resolution changes. **
|
||||
CGFloat mBackingScaleFactor;
|
||||
|
||||
bool mFailedResizerImage;
|
||||
bool mFailedCornerMaskImage;
|
||||
bool mVisible;
|
||||
bool mDrawing;
|
||||
bool mPluginDrawing;
|
||||
|
@ -241,9 +241,12 @@ nsChildView::nsChildView() : nsBaseWidget()
|
||||
, mView(nullptr)
|
||||
, mParentView(nullptr)
|
||||
, mParentWidget(nullptr)
|
||||
, mBackingScaleFactor(0.0)
|
||||
, mEffectsLock("WidgetEffects")
|
||||
, mShowsResizeIndicator(false)
|
||||
, mHasRoundedBottomCorners(false)
|
||||
, mFailedResizerImage(false)
|
||||
, mFailedCornerMaskImage(false)
|
||||
, mBackingScaleFactor(0.0)
|
||||
, mVisible(false)
|
||||
, mDrawing(false)
|
||||
, mPluginDrawing(false)
|
||||
@ -271,8 +274,7 @@ nsChildView::~nsChildView()
|
||||
|
||||
NS_WARN_IF_FALSE(mOnDestroyCalled, "nsChildView object destroyed without calling Destroy()");
|
||||
|
||||
mResizerImage = nullptr;
|
||||
mCornerMaskImage = nullptr;
|
||||
DestroyCompositor();
|
||||
|
||||
// An nsChildView object that was in use can be destroyed without Destroy()
|
||||
// ever being called on it. So we also need to do a quick, safe cleanup
|
||||
@ -1851,6 +1853,24 @@ nsChildView::GetThebesSurface()
|
||||
return mTempThebesSurface;
|
||||
}
|
||||
|
||||
void
|
||||
nsChildView::PrepareWindowEffects()
|
||||
{
|
||||
MutexAutoLock lock(mEffectsLock);
|
||||
mShowsResizeIndicator = ShowsResizeIndicator(&mResizeIndicatorRect);
|
||||
mHasRoundedBottomCorners = [mView isKindOfClass:[ChildView class]] &&
|
||||
[(ChildView*)mView hasRoundedBottomCorners];
|
||||
CGFloat cornerRadius = [(ChildView*)mView bottomCornerRadius];
|
||||
mDevPixelCornerRadius = cornerRadius * BackingScaleFactor();
|
||||
}
|
||||
|
||||
void
|
||||
nsChildView::CleanupWindowEffects()
|
||||
{
|
||||
mResizerImage = nullptr;
|
||||
mCornerMaskImage = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
|
||||
{
|
||||
@ -1899,14 +1919,15 @@ DrawResizer(CGContextRef aCtx)
|
||||
void
|
||||
nsChildView::MaybeDrawResizeIndicator(GLManager* aManager, nsIntRect aRect)
|
||||
{
|
||||
nsIntRect resizeRect;
|
||||
if (!ShowsResizeIndicator(&resizeRect) || mFailedResizerImage) {
|
||||
if (!mShowsResizeIndicator || mFailedResizerImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mResizerImage) {
|
||||
MutexAutoLock lock(mEffectsLock);
|
||||
mResizerImage =
|
||||
aManager->gl()->CreateTextureImage(nsIntSize(resizeRect.width, resizeRect.height),
|
||||
aManager->gl()->CreateTextureImage(nsIntSize(mResizeIndicatorRect.width,
|
||||
mResizeIndicatorRect.height),
|
||||
gfxASurface::CONTENT_COLOR_ALPHA,
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
TextureImage::UseNearestFilter);
|
||||
@ -1915,7 +1936,7 @@ nsChildView::MaybeDrawResizeIndicator(GLManager* aManager, nsIntRect aRect)
|
||||
if (!mResizerImage)
|
||||
return;
|
||||
|
||||
nsIntRegion update(nsIntRect(0, 0, resizeRect.width, resizeRect.height));
|
||||
nsIntRegion update(nsIntRect(0, 0, mResizeIndicatorRect.width, mResizeIndicatorRect.height));
|
||||
gfxASurface *asurf = mResizerImage->BeginUpdate(update);
|
||||
if (!asurf) {
|
||||
mResizerImage = nullptr;
|
||||
@ -1970,17 +1991,16 @@ DrawTopLeftCornerMask(CGContextRef aCtx, int aRadius)
|
||||
void
|
||||
nsChildView::MaybeDrawRoundedBottomCorners(GLManager* aManager, nsIntRect aRect)
|
||||
{
|
||||
if (![mView isKindOfClass:[ChildView class]] ||
|
||||
![(ChildView*)mView hasRoundedBottomCorners] ||
|
||||
if (!mHasRoundedBottomCorners ||
|
||||
mFailedCornerMaskImage)
|
||||
return;
|
||||
|
||||
CGFloat cornerRadius = [(ChildView*)mView bottomCornerRadius];
|
||||
int devPixelCornerRadius = cornerRadius * BackingScaleFactor();
|
||||
MutexAutoLock lock(mEffectsLock);
|
||||
|
||||
if (!mCornerMaskImage) {
|
||||
mCornerMaskImage =
|
||||
aManager->gl()->CreateTextureImage(nsIntSize(devPixelCornerRadius, devPixelCornerRadius),
|
||||
aManager->gl()->CreateTextureImage(nsIntSize(mDevPixelCornerRadius,
|
||||
mDevPixelCornerRadius),
|
||||
gfxASurface::CONTENT_COLOR_ALPHA,
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
TextureImage::UseNearestFilter);
|
||||
@ -1989,7 +2009,7 @@ nsChildView::MaybeDrawRoundedBottomCorners(GLManager* aManager, nsIntRect aRect)
|
||||
if (!mCornerMaskImage)
|
||||
return;
|
||||
|
||||
nsIntRegion update(nsIntRect(0, 0, devPixelCornerRadius, devPixelCornerRadius));
|
||||
nsIntRegion update(nsIntRect(0, 0, mDevPixelCornerRadius, mDevPixelCornerRadius));
|
||||
gfxASurface *asurf = mCornerMaskImage->BeginUpdate(update);
|
||||
if (!asurf) {
|
||||
mCornerMaskImage = nullptr;
|
||||
@ -2007,7 +2027,7 @@ nsChildView::MaybeDrawRoundedBottomCorners(GLManager* aManager, nsIntRect aRect)
|
||||
}
|
||||
nsRefPtr<gfxQuartzSurface> image = static_cast<gfxQuartzSurface*>(asurf);
|
||||
|
||||
DrawTopLeftCornerMask(image->GetCGContext(), devPixelCornerRadius);
|
||||
DrawTopLeftCornerMask(image->GetCGContext(), mDevPixelCornerRadius);
|
||||
|
||||
mCornerMaskImage->EndUpdate();
|
||||
}
|
||||
@ -2019,8 +2039,8 @@ nsChildView::MaybeDrawRoundedBottomCorners(GLManager* aManager, nsIntRect aRect)
|
||||
ShaderProgramOGL *program = aManager->GetProgram(mCornerMaskImage->GetShaderProgramType());
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0, // aRect.x, aRect.y,
|
||||
devPixelCornerRadius,
|
||||
devPixelCornerRadius));
|
||||
mDevPixelCornerRadius,
|
||||
mDevPixelCornerRadius));
|
||||
program->SetLayerOpacity(1.0);
|
||||
program->SetRenderOffset(nsIntPoint(0,0));
|
||||
program->SetTextureUnit(0);
|
||||
|
@ -1153,13 +1153,35 @@ class nsIWidget : public nsISupports {
|
||||
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
|
||||
bool* aAllowRetaining = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* Called before each layer manager transaction to allow any preparation
|
||||
* for DrawWindowUnderlay/Overlay that needs to be on the main thread.
|
||||
*
|
||||
* Always called on the main thread.
|
||||
*/
|
||||
virtual void PrepareWindowEffects() = 0;
|
||||
|
||||
/**
|
||||
* Called when shutting down the LayerManager to clean-up any cached resources.
|
||||
*
|
||||
* Always called from the compositing thread, which may be the main-thread if
|
||||
* OMTC is not enabled.
|
||||
*/
|
||||
virtual void CleanupWindowEffects() = 0;
|
||||
|
||||
/**
|
||||
* Called before the LayerManager draws the layer tree.
|
||||
*
|
||||
* Always called from the compositing thread, which may be the main-thread if
|
||||
* OMTC is not enabled.
|
||||
*/
|
||||
virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) = 0;
|
||||
|
||||
/**
|
||||
* Called after the LayerManager draws the layer tree
|
||||
*
|
||||
* Always called from the compositing thread, which may be the main-thread if
|
||||
* OMTC is not enabled.
|
||||
*/
|
||||
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) = 0;
|
||||
|
||||
|
@ -113,6 +113,8 @@ public:
|
||||
virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight);
|
||||
virtual void CreateCompositor();
|
||||
virtual void CreateCompositor(int aWidth, int aHeight);
|
||||
virtual void PrepareWindowEffects() {}
|
||||
virtual void CleanupWindowEffects() {}
|
||||
virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
|
||||
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
|
||||
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
|
||||
|
Loading…
Reference in New Issue
Block a user