Bug 1724839 - Don't use BasicLayerManager for painting ImageBitmap <canvas> elements. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D122171
This commit is contained in:
Matt Woodrow 2021-08-10 03:38:40 +00:00
Родитель a1d0abeb81
Коммит 8a447ade17
5 изменённых файлов: 65 добавлений и 0 удалений

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

@ -81,6 +81,9 @@ class ImageBitmapRenderingContext final
virtual already_AddRefed<Layer> GetCanvasLayer(
nsDisplayListBuilder* aBuilder, Layer* aOldLayer,
LayerManager* aManager) override;
virtual already_AddRefed<layers::Image> GetAsImage() override {
return ClipToIntrinsicSize();
}
bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData) override;
virtual void MarkContextClean() override;

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

@ -39,6 +39,7 @@ class CanvasLayer;
class CanvasRenderer;
class CompositableHandle;
class Layer;
class Image;
class LayerManager;
class LayerTransactionChild;
class PersistentBufferProvider;
@ -146,6 +147,9 @@ class nsICanvasRenderingContextInternal : public nsISupports,
virtual already_AddRefed<Layer> GetCanvasLayer(
mozilla::nsDisplayListBuilder* builder, Layer* oldLayer,
LayerManager* manager) = 0;
virtual already_AddRefed<mozilla::layers::Image> GetAsImage() {
return nullptr;
}
virtual bool UpdateWebRenderCanvasData(
mozilla::nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData) {

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

@ -1142,6 +1142,18 @@ already_AddRefed<Layer> HTMLCanvasElement::GetCanvasLayer(
return nullptr;
}
already_AddRefed<Image> HTMLCanvasElement::GetAsImage() {
if (mCurrentContext) {
return mCurrentContext->GetAsImage();
}
if (mOffscreenCanvas) {
MOZ_CRASH("todo");
}
return nullptr;
}
bool HTMLCanvasElement::UpdateWebRenderCanvasData(
nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) {
if (mCurrentContext) {

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

@ -301,6 +301,7 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer* aOldLayer,
LayerManager* aManager);
already_AddRefed<layers::Image> GetAsImage();
bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData);
bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,

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

@ -307,6 +307,51 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
virtual void Paint(nsDisplayListBuilder* aBuilder,
gfxContext* aCtx) override {
nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(Frame());
HTMLCanvasElement* canvas = HTMLCanvasElement::FromNode(f->GetContent());
nsRect area = f->GetContentRectRelativeToSelf() + ToReferenceFrame();
nsIntSize canvasSizeInPx = f->GetCanvasSize();
nsPresContext* presContext = f->PresContext();
canvas->HandlePrintCallback(presContext);
if (canvasSizeInPx.width <= 0 || canvasSizeInPx.height <= 0 ||
area.IsEmpty()) {
return;
}
IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
AspectRatio intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx);
nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
area, intrinsicSize, intrinsicRatio, f->StylePosition());
gfxRect destGFXRect = presContext->AppUnitsToGfxUnits(dest);
// Transform the canvas into the right place
gfxPoint p = destGFXRect.TopLeft();
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width,
destGFXRect.Height() / canvasSizeInPx.height);
if (RefPtr<layers::Image> image = canvas->GetAsImage()) {
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
if (!surface || !surface->IsValid()) {
return;
}
gfxContextMatrixAutoSaveRestore saveMatrix(aCtx);
aCtx->Multiply(transform);
gfx::IntSize size = surface->GetSize();
aCtx->GetDrawTarget()->FillRect(
Rect(0, 0, size.width, size.height),
SurfacePattern(surface, ExtendMode::CLAMP, Matrix(),
nsLayoutUtils::GetSamplingFilterForFrame(f)));
return;
}
// This currently uses BasicLayerManager to re-use the code for extracting
// the current CanvasRenderer/Image and generating DrawTarget rendering
// commands for it.