Bug 1401609 - Add UpdateWebRenderCanvasData() to handle CanvasRenderer re-creation r=jrmuizel,mstange

This commit is contained in:
sotaro 2017-10-28 19:07:27 +09:00
Родитель 831f2ed98f
Коммит 23069babc9
13 изменённых файлов: 164 добавлений и 19 удалений

Просмотреть файл

@ -127,6 +127,8 @@
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/layers/WebRenderUserData.h"
#include "mozilla/layers/WebRenderCanvasRenderer.h"
#include "mozilla/ServoCSSParser.h"
#undef free // apparently defined by some windows header, clashing with a free()
@ -6217,6 +6219,64 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
return canvasLayer.forget();
}
bool
CanvasRenderingContext2D::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData)
{
if (mOpaque || mIsSkiaGL) {
// If we're opaque then make sure we have a surface so we paint black
// instead of transparent.
// If we're using SkiaGL, then SkiaGLTex() below needs the target to
// be accessible.
EnsureTarget();
}
// Don't call EnsureTarget() ... if there isn't already a surface, then
// we have nothing to paint and there is no need to create a surface just
// to paint nothing. Also, EnsureTarget() can cause creation of a persistent
// layer manager which must NOT happen during a paint.
if (!mBufferProvider && !IsTargetValid()) {
// No DidTransactionCallback will be received, so mark the context clean
// now so future invalidations will be dispatched.
MarkContextClean();
// Clear CanvasRenderer of WebRenderCanvasData
aCanvasData->ClearCanvasRenderer();
return false;
}
CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer();
if(!mResetLayer && renderer) {
CanvasInitializeData data;
if (mIsSkiaGL) {
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
}
}
data.mBufferProvider = mBufferProvider;
if (renderer->IsDataValid(data)) {
return true;
}
}
renderer = aCanvasData->CreateCanvasRenderer();
if (!InitializeCanvasRenderer(aBuilder, renderer)) {
// Clear CanvasRenderer of WebRenderCanvasData
aCanvasData->ClearCanvasRenderer();
return false;
}
MOZ_ASSERT(renderer);
mResetLayer = false;
return true;
}
bool
CanvasRenderingContext2D::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer)

Просмотреть файл

@ -467,6 +467,10 @@ public:
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer* aOldLayer,
LayerManager* aManager) override;
bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData) override;
bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer) override;
virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override;

Просмотреть файл

@ -50,6 +50,8 @@
#include "ScopedGLHelpers.h"
#include "VRManagerChild.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/WebRenderUserData.h"
#include "mozilla/layers/WebRenderCanvasRenderer.h"
// Local
#include "CanvasUtils.h"
@ -1350,6 +1352,28 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
return canvasLayer.forget();
}
bool
WebGLContext::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData)
{
CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer();
if(!mResetLayer && renderer) {
return true;
}
renderer = aCanvasData->CreateCanvasRenderer();
if (!InitializeCanvasRenderer(aBuilder, renderer)) {
// Clear CanvasRenderer of WebRenderCanvasData
aCanvasData->ClearCanvasRenderer();
return false;
}
MOZ_ASSERT(renderer);
mResetLayer = false;
return true;
}
bool
WebGLContext::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer)

Просмотреть файл

@ -434,6 +434,11 @@ public:
already_AddRefed<Layer>
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
LayerManager* manager) override;
bool
UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData) override;
bool
InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer) override;

Просмотреть файл

@ -29,6 +29,7 @@ class CanvasLayer;
class CanvasRenderer;
class Layer;
class LayerManager;
class WebRenderCanvasData;
} // namespace layers
namespace gfx {
class SourceSurface;
@ -44,6 +45,7 @@ public:
typedef mozilla::layers::CanvasRenderer CanvasRenderer;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::WebRenderCanvasData WebRenderCanvasData;
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
@ -140,6 +142,8 @@ public:
virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
Layer *oldLayer,
LayerManager *manager) = 0;
virtual bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData) { return false; }
virtual bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer) { return true; }

Просмотреть файл

@ -1219,6 +1219,37 @@ HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
return nullptr;
}
bool
HTMLCanvasElement::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData)
{
if (mCurrentContext) {
return mCurrentContext->UpdateWebRenderCanvasData(aBuilder, aCanvasData);
}
if (mOffscreenCanvas) {
CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer();
if(!mResetLayer && renderer) {
return true;
}
renderer = aCanvasData->CreateCanvasRenderer();
if (!InitializeCanvasRenderer(aBuilder, renderer)) {
// Clear CanvasRenderer of WebRenderCanvasData
aCanvasData->ClearCanvasRenderer();
return false;
}
MOZ_ASSERT(renderer);
mResetLayer = false;
return true;
}
// Clear CanvasRenderer of WebRenderCanvasData
aCanvasData->ClearCanvasRenderer();
return false;
}
bool
HTMLCanvasElement::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer)
@ -1235,7 +1266,7 @@ HTMLCanvasElement::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
return true;
}
return true;
return false;
}
bool

Просмотреть файл

@ -35,6 +35,7 @@ class Image;
class Layer;
class LayerManager;
class SharedSurfaceTextureClient;
class WebRenderCanvasData;
} // namespace layers
namespace gfx {
class SourceSurface;
@ -127,6 +128,7 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
typedef layers::CanvasLayer CanvasLayer;
typedef layers::Layer Layer;
typedef layers::LayerManager LayerManager;
typedef layers::WebRenderCanvasData WebRenderCanvasData;
public:
explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
@ -306,6 +308,8 @@ public:
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer *aOldLayer,
LayerManager *aManager);
bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData);
bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer);
// Should return true if the canvas layer should always be marked inactive.

Просмотреть файл

@ -40,7 +40,9 @@ WebRenderCommandBuilder::EmptyTransaction()
for (auto iter = mLastCanvasDatas.Iter(); !iter.Done(); iter.Next()) {
RefPtr<WebRenderCanvasData> canvasData = iter.Get()->GetKey();
WebRenderCanvasRendererAsync* canvas = canvasData->GetCanvasRenderer();
canvas->UpdateCompositableClient();
if (canvas) {
canvas->UpdateCompositableClient();
}
}
}

Просмотреть файл

@ -255,13 +255,22 @@ WebRenderCanvasData::ClearCachedResources()
}
}
void
WebRenderCanvasData::ClearCanvasRenderer()
{
mCanvasRenderer = nullptr;
}
WebRenderCanvasRendererAsync*
WebRenderCanvasData::GetCanvasRenderer()
{
if (!mCanvasRenderer) {
mCanvasRenderer = MakeUnique<WebRenderCanvasRendererAsync>(mWRManager);
}
return mCanvasRenderer.get();
}
WebRenderCanvasRendererAsync*
WebRenderCanvasData::CreateCanvasRenderer()
{
mCanvasRenderer = MakeUnique<WebRenderCanvasRendererAsync>(mWRManager);
return mCanvasRenderer.get();
}

Просмотреть файл

@ -159,7 +159,9 @@ public:
virtual UserDataType GetType() override { return UserDataType::eCanvas; }
static UserDataType Type() { return UserDataType::eCanvas; }
void ClearCanvasRenderer();
WebRenderCanvasRendererAsync* GetCanvasRenderer();
WebRenderCanvasRendererAsync* CreateCanvasRenderer();
void ClearCachedResources() override;
protected:
UniquePtr<WebRenderCanvasRendererAsync> mCanvasRenderer;

Просмотреть файл

@ -141,16 +141,13 @@ public:
bool isRecycled;
RefPtr<WebRenderCanvasData> canvasData =
aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderCanvasData>(this, &isRecycled);
nsHTMLCanvasFrame* canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
if (!canvasFrame->UpdateWebRenderCanvasData(aDisplayListBuilder, canvasData)) {
return true;
}
WebRenderCanvasRendererAsync* data =
static_cast<WebRenderCanvasRendererAsync*>(canvasData->GetCanvasRenderer());
if (!isRecycled) {
nsHTMLCanvasFrame* canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
if (!canvasFrame->InitializeCanvasRenderer(aDisplayListBuilder, data)) {
return true;
}
}
MOZ_ASSERT(data);
data->UpdateCompositableClient();
// Push IFrame for async image pipeline.
@ -461,11 +458,11 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
}
bool
nsHTMLCanvasFrame::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer)
nsHTMLCanvasFrame::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData)
{
HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
return element->InitializeCanvasRenderer(aBuilder, aRenderer);
return element->UpdateWebRenderCanvasData(aBuilder, aCanvasData);
}
void

Просмотреть файл

@ -18,6 +18,7 @@ namespace mozilla {
namespace layers {
class Layer;
class LayerManager;
class WebRenderCanvasData;
} // namespace layers
} // namespace mozilla
@ -32,6 +33,7 @@ public:
typedef mozilla::layers::CanvasRenderer CanvasRenderer;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::WebRenderCanvasData WebRenderCanvasData;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
NS_DECL_QUERYFRAME
@ -53,8 +55,9 @@ public:
LayerManager* aManager,
nsDisplayItem* aItem,
const ContainerLayerParameters& aContainerParameters);
bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
CanvasRenderer* aRenderer);
bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData);
/* get the size of the canvas's image */
nsIntSize GetCanvasSize();

Просмотреть файл

@ -6,7 +6,7 @@ fuzzy-if(Android,8,1000) == size-1.html size-1-ref.html
== image-rendering-test.html image-rendering-ref.html
== image-shadow.html image-shadow-ref.html
asserts-if(cocoaWidget,0-2) fails-if(webrender) == size-change-1.html size-change-1-ref.html
asserts-if(cocoaWidget,0-2) == size-change-1.html size-change-1-ref.html
random-if(cocoaWidget) == subpixel-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards