Bug 1391136 - Handle context lost in layers-free mode. r=jgilbert
MozReview-Commit-ID: 1J0EggRmM4i
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -6284,17 +6284,17 @@ CanvasRenderingContext2D::GetCanvasLayer
uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
canvasLayer->SetContentFlags(flags);
mResetLayer = false;
return canvasLayer.forget();
}
-void
+bool
CanvasRenderingContext2D::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer,
bool aMirror)
{
CanvasInitializeData data;
data.mSize = GetSize();
data.mHasAlpha = !mOpaque;
data.mPreTransCallback = CanvasRenderingContext2DUserData::PreTransactionCallback;
@@ -6317,16 +6317,17 @@ CanvasRenderingContext2D::InitializeCanv
data.mFrontbufferGLTex = skiaGLTex;
}
}
data.mBufferProvider = mBufferProvider;
aRenderer->Initialize(data);
aRenderer->SetDirty();
+ return true;
}
void
CanvasRenderingContext2D::MarkContextClean()
{
if (mInvalidateCount > 0) {
mPredictManyRedrawCalls = mInvalidateCount > kCanvasMaxInvalidateCount;
}
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -463,17 +463,17 @@ public:
virtual void SetIsOpaque(bool aIsOpaque) override;
bool GetIsOpaque() override { return mOpaque; }
NS_IMETHOD Reset() override;
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer* aOldLayer,
LayerManager* aManager,
bool aMirror = false) override;
- void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer,
bool aMirror = false) override;
virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override;
void MarkContextClean() override;
void MarkContextCleanForFrameCapture() override;
bool IsContextCleanForFrameCapture() override;
NS_IMETHOD SetIsIPC(bool aIsIPC) override;
// this rect is in canvas device space
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1317,19 +1317,16 @@ private:
};
already_AddRefed<layers::Layer>
WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
Layer* oldLayer,
LayerManager* manager,
bool aMirror /*= false*/)
{
- if (IsContextLost())
- return nullptr;
-
if (!mResetLayer && oldLayer &&
oldLayer->HasUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData)) {
RefPtr<layers::Layer> ret = oldLayer;
return ret.forget();
}
RefPtr<CanvasLayer> canvasLayer = manager->CreateCanvasLayer();
if (!canvasLayer) {
@@ -1340,34 +1337,39 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
WebGLContextUserData* userData = nullptr;
if (builder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
userData = new WebGLContextUserData(mCanvasElement);
}
canvasLayer->SetUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData, userData);
CanvasRenderer* canvasRenderer = canvasLayer->CreateOrGetCanvasRenderer();
- InitializeCanvasRenderer(builder, canvasRenderer, aMirror);
+ if (!InitializeCanvasRenderer(builder, canvasRenderer, aMirror))
+ return nullptr;
+
uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
canvasLayer->SetContentFlags(flags);
mResetLayer = false;
// We only wish to update mLayerIsMirror when a new layer is returned.
// If a cached layer is returned above, aMirror is not changing since
// the last cached layer was created and mLayerIsMirror is still valid.
mLayerIsMirror = aMirror;
return canvasLayer.forget();
}
-void
+bool
WebGLContext::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer,
bool aMirror)
{
+ if (IsContextLost())
+ return false;
+
CanvasInitializeData data;
if (aBuilder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
@@ -1386,16 +1388,17 @@ WebGLContext::InitializeCanvasRenderer(n
data.mGLContext = gl;
data.mSize = nsIntSize(mWidth, mHeight);
data.mHasAlpha = gl->Caps().alpha;
data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
data.mIsMirror = aMirror;
aRenderer->Initialize(data);
aRenderer->SetDirty();
+ return true;
}
layers::LayersBackend
WebGLContext::GetCompositorBackendType() const
{
if (mCanvasElement) {
return mCanvasElement->GetCompositorBackendType();
} else if (mOffscreenCanvas) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -457,17 +457,17 @@ public:
}
void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
already_AddRefed<Layer>
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
LayerManager* manager,
bool aMirror = false) override;
- void
+ bool
InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer,
bool aMirror = false) override;
// Note that 'clean' here refers to its invalidation state, not the
// contents of the buffer.
void MarkContextClean() override { mInvalidated = false; }
--- a/dom/canvas/nsICanvasRenderingContextInternal.h
+++ b/dom/canvas/nsICanvasRenderingContextInternal.h
@@ -136,19 +136,19 @@ public:
NS_IMETHOD Reset() = 0;
// Return the CanvasLayer for this context, creating
// one for the given layer manager if not available.
virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
Layer *oldLayer,
LayerManager *manager,
bool aMirror = false) = 0;
- virtual void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ virtual bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer,
- bool aMirror = false) { };
+ bool aMirror = false) { return true; }
// Return true if the canvas should be forced to be "inactive" to ensure
// it can be drawn to the screen even if it's too large to be blitted by
// an accelerated CanvasLayer.
virtual bool ShouldForceInactiveLayer(LayerManager *manager) { return false; }
virtual void MarkContextClean() = 0;
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -1183,39 +1183,45 @@ HTMLCanvasElement::GetCanvasLayer(nsDisp
NS_WARNING("CreateCanvasLayer failed!");
return nullptr;
}
LayerUserData* userData = nullptr;
layer->SetUserData(&sOffscreenCanvasLayerUserDataDummy, userData);
CanvasRenderer* canvasRenderer = layer->CreateOrGetCanvasRenderer();
- InitializeCanvasRenderer(aBuilder, canvasRenderer);
+
+ if (!InitializeCanvasRenderer(aBuilder, canvasRenderer)) {
+ return nullptr;
+ }
layer->Updated();
return layer.forget();
}
return nullptr;
}
-void
+bool
HTMLCanvasElement::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer)
{
if (mCurrentContext) {
- mCurrentContext->InitializeCanvasRenderer(aBuilder, aRenderer);
+ return mCurrentContext->InitializeCanvasRenderer(aBuilder, aRenderer);
}
if (mOffscreenCanvas) {
CanvasInitializeData data;
data.mRenderer = GetAsyncCanvasRenderer();
data.mSize = GetWidthHeight();
aRenderer->Initialize(data);
+ return true;
}
+
+ return true;
}
bool
HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager* aManager)
{
if (mCurrentContext) {
return mCurrentContext->ShouldForceInactiveLayer(aManager);
}
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -305,17 +305,17 @@ public:
/*
* Helpers called by various users of Canvas
*/
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer *aOldLayer,
LayerManager *aManager);
- void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer);
// Should return true if the canvas layer should always be marked inactive.
// We should return true here if we can't do accelerated compositing with
// a non-BasicCanvasLayer.
bool ShouldForceInactiveLayer(LayerManager *aManager);
// Call this whenever we need future changes to the canvas
// to trigger fresh invalidation requests. This needs to be called
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -136,17 +136,20 @@ public:
{
bool isRecycled;
RefPtr<WebRenderCanvasData> canvasData =
aManager->CreateOrRecycleWebRenderUserData<WebRenderCanvasData>(this, &isRecycled);
WebRenderCanvasRendererAsync* data =
static_cast<WebRenderCanvasRendererAsync*>(canvasData->GetCanvasRenderer());
if (!isRecycled) {
- static_cast<nsHTMLCanvasFrame*>(mFrame)->InitializeCanvasRenderer(aDisplayListBuilder, data);
+ nsHTMLCanvasFrame *canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
+ if (!canvasFrame->InitializeCanvasRenderer(aDisplayListBuilder, data)) {
+ return true;
+ }
}
data->UpdateCompositableClient();
// Push IFrame for async image pipeline.
// XXX Remove this once partial display list update is supported.
/* ScrollingLayersHelper scroller(this, aBuilder, aSc); */
@@ -450,22 +453,22 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayL
} else if (layer->GetType() == layers::Layer::TYPE_IMAGE) {
RefPtr<ImageLayer> imageLayer = static_cast<ImageLayer*>(layer.get());
imageLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this));
}
return layer.forget();
}
-void
+bool
nsHTMLCanvasFrame::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer)
{
HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
- element->InitializeCanvasRenderer(aBuilder, aRenderer);
+ return element->InitializeCanvasRenderer(aBuilder, aRenderer);
}
void
nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return;
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -47,17 +47,17 @@ public:
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsDisplayItem* aItem,
const ContainerLayerParameters& aContainerParameters);
- void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer);
/* get the size of the canvas's image */
nsIntSize GetCanvasSize();
virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override;