зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1727423 - Remove BasicLayerManager. r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D123555
This commit is contained in:
Родитель
15827952f9
Коммит
7755c29fd8
|
@ -56,7 +56,6 @@ class DrawTarget;
|
|||
namespace layers {
|
||||
|
||||
class AsyncPanZoomController;
|
||||
class BasicLayerManager;
|
||||
class ClientLayerManager;
|
||||
class HostLayerManager;
|
||||
class Layer;
|
||||
|
@ -165,7 +164,6 @@ class LayerManager : public WindowRenderer {
|
|||
|
||||
virtual LayerManagerComposite* AsLayerManagerComposite() { return nullptr; }
|
||||
|
||||
virtual BasicLayerManager* AsBasicLayerManager() { return nullptr; }
|
||||
virtual HostLayerManager* AsHostLayerManager() { return nullptr; }
|
||||
|
||||
virtual WebRenderLayerManager* AsWebRenderLayerManager() { return nullptr; }
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
#include <algorithm> // for max
|
||||
#include <utility> // for Move
|
||||
|
||||
#include "BasicImplData.h" // for BasicImplData
|
||||
#include "BasicLayersImpl.h" // for ToData
|
||||
#include "Layers.h" // for PaintedLayer, Layer, etc
|
||||
#include "Layers.h" // for PaintedLayer, Layer, etc
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
|
@ -203,36 +201,6 @@ static bool IsClippingCheap(gfx::DrawTarget* aTarget,
|
|||
aRegion.GetNumRects() <= 1;
|
||||
}
|
||||
|
||||
void RotatedBuffer::DrawTo(PaintedLayer* aLayer, DrawTarget* aTarget,
|
||||
float aOpacity, CompositionOp aOp,
|
||||
SourceSurface* aMask, const Matrix* aMaskTransform) {
|
||||
bool clipped = false;
|
||||
|
||||
// If the entire buffer is valid, we can just draw the whole thing,
|
||||
// no need to clip. But we'll still clip if clipping is cheap ---
|
||||
// that might let us copy a smaller region of the buffer.
|
||||
// Also clip to the visible region if we're told to.
|
||||
if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
|
||||
(ToData(aLayer)->GetClipToVisibleRegion() &&
|
||||
!aLayer->GetVisibleRegion().ToUnknownRegion().Contains(BufferRect())) ||
|
||||
IsClippingCheap(aTarget,
|
||||
aLayer->GetLocalVisibleRegion().ToUnknownRegion())) {
|
||||
// We don't want to draw invalid stuff, so we need to clip. Might as
|
||||
// well clip to the smallest area possible --- the visible region.
|
||||
// Bug 599189 if there is a non-integer-translation transform in aTarget,
|
||||
// we might sample pixels outside GetLocalVisibleRegion(), which is wrong
|
||||
// and may cause gray lines.
|
||||
gfxUtils::ClipToRegion(aTarget,
|
||||
aLayer->GetLocalVisibleRegion().ToUnknownRegion());
|
||||
clipped = true;
|
||||
}
|
||||
|
||||
DrawBufferWithRotation(aTarget, aOpacity, aOp, aMask, aMaskTransform);
|
||||
if (clipped) {
|
||||
aTarget->PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
void RotatedBuffer::UpdateDestinationFrom(const RotatedBuffer& aSource,
|
||||
const gfx::IntRect& aUpdateRect) {
|
||||
DrawIterator iter;
|
||||
|
|
|
@ -98,15 +98,6 @@ class RotatedBuffer : public BorrowDrawTarget {
|
|||
gfx::SourceSurface* aMask = nullptr,
|
||||
const gfx::Matrix* aMaskTransform = nullptr) const;
|
||||
|
||||
/**
|
||||
* Complete the drawing operation. The region to draw must have been
|
||||
* drawn before this is called. The contents of the buffer are drawn
|
||||
* to aTarget.
|
||||
*/
|
||||
void DrawTo(PaintedLayer* aLayer, gfx::DrawTarget* aTarget, float aOpacity,
|
||||
gfx::CompositionOp aOp, gfx::SourceSurface* aMask,
|
||||
const gfx::Matrix* aMaskTransform);
|
||||
|
||||
/**
|
||||
* Update the specified region of this rotated buffer with the contents
|
||||
* of a source rotated buffer.
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BasicCanvasLayer.h"
|
||||
#include "basic/BasicLayers.h" // for BasicLayerManager
|
||||
#include "basic/BasicLayersImpl.h" // for GetEffectiveOperator
|
||||
#include "CanvasRenderer.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
|
||||
#include "gfx2DGlue.h"
|
||||
#include "GLScreenBuffer.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "mozilla/layers/PersistentBufferProvider.h"
|
||||
#include "client/TextureClientSharedSurface.h"
|
||||
|
||||
class gfxContext;
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void BasicCanvasLayer::Paint(DrawTarget* aDT, const Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) {
|
||||
if (IsHidden()) return;
|
||||
// Ignore IsDirty().
|
||||
|
||||
MOZ_ASSERT(mCanvasRenderer);
|
||||
mCanvasRenderer->FirePreTransactionCallback();
|
||||
|
||||
const auto snapshot = mCanvasRenderer->BorrowSnapshot();
|
||||
if (!snapshot) return;
|
||||
const auto& surface = snapshot->mSurf;
|
||||
|
||||
Maybe<Matrix> oldTM;
|
||||
if (!mCanvasRenderer->YIsDown()) {
|
||||
// y-flip
|
||||
oldTM = Some(aDT->GetTransform());
|
||||
aDT->SetTransform(Matrix(*oldTM)
|
||||
.PreTranslate(0.0f, mBounds.Height())
|
||||
.PreScale(1.0f, -1.0f));
|
||||
}
|
||||
|
||||
FillRectWithMask(
|
||||
aDT, aDeviceOffset, Rect(0, 0, mBounds.Width(), mBounds.Height()),
|
||||
surface, mSamplingFilter,
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
|
||||
if (oldTM) {
|
||||
aDT->SetTransform(*oldTM);
|
||||
}
|
||||
|
||||
mCanvasRenderer->FireDidTransactionCallback();
|
||||
|
||||
Painted();
|
||||
}
|
||||
|
||||
RefPtr<CanvasRenderer> BasicCanvasLayer::CreateCanvasRendererInternal() {
|
||||
return new CanvasRenderer();
|
||||
}
|
||||
|
||||
already_AddRefed<CanvasLayer> BasicLayerManager::CreateCanvasLayer() {
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
RefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_BASICCANVASLAYER_H
|
||||
#define GFX_BASICCANVASLAYER_H
|
||||
|
||||
#include "BasicImplData.h" // for BasicImplData
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "Layers.h" // for CanvasLayer, etc
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BasicCanvasLayer : public CanvasLayer, public BasicImplData {
|
||||
public:
|
||||
explicit BasicCanvasLayer(BasicLayerManager* aLayerManager)
|
||||
: CanvasLayer(aLayerManager, static_cast<BasicImplData*>(this)) {}
|
||||
|
||||
void SetVisibleRegion(const LayerIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
CanvasLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
void Paint(gfx::DrawTarget* aDT, const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) override;
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager() {
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
|
||||
RefPtr<CanvasRenderer> CreateCanvasRendererInternal() override;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -1,75 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BasicLayersImpl.h" // for FillRectWithMask, etc
|
||||
#include "Layers.h" // for ColorLayer, etc
|
||||
#include "BasicImplData.h" // for BasicImplData
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "gfxContext.h" // for gfxContext, etc
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
|
||||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BasicColorLayer : public ColorLayer, public BasicImplData {
|
||||
public:
|
||||
explicit BasicColorLayer(BasicLayerManager* aLayerManager)
|
||||
: ColorLayer(aLayerManager, static_cast<BasicImplData*>(this)) {
|
||||
MOZ_COUNT_CTOR(BasicColorLayer);
|
||||
}
|
||||
|
||||
protected:
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(BasicColorLayer)
|
||||
|
||||
public:
|
||||
void SetVisibleRegion(const LayerIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
ColorLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
void Paint(DrawTarget* aDT, const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) override {
|
||||
if (IsHidden()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect snapped(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height());
|
||||
MaybeSnapToDevicePixels(snapped, *aDT, true);
|
||||
|
||||
// Clip drawing in case we're using (unbounded) operator source.
|
||||
aDT->PushClipRect(snapped);
|
||||
FillRectWithMask(
|
||||
aDT, aDeviceOffset, snapped, mColor,
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
aDT->PopClip();
|
||||
}
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager() {
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<ColorLayer> BasicLayerManager::CreateColorLayer() {
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
RefPtr<ColorLayer> layer = new BasicColorLayer(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,162 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BasicContainerLayer.h"
|
||||
#include <sys/types.h> // for int32_t
|
||||
#include "BasicLayersImpl.h" // for ToData
|
||||
#include "basic/BasicImplData.h" // for BasicImplData
|
||||
#include "basic/BasicLayers.h" // for BasicLayerManager
|
||||
#include "mozilla/gfx/BaseRect.h" // for BaseRect
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
BasicContainerLayer::~BasicContainerLayer() {
|
||||
ContainerLayer::RemoveAllChildren();
|
||||
MOZ_COUNT_DTOR(BasicContainerLayer);
|
||||
}
|
||||
|
||||
void BasicContainerLayer::ComputeEffectiveTransforms(
|
||||
const Matrix4x4& aTransformToSurface) {
|
||||
// We push groups for container layers if we need to, which always
|
||||
// are aligned in device space, so it doesn't really matter how we snap
|
||||
// containers.
|
||||
Matrix residual;
|
||||
Matrix4x4 transformToSurface = aTransformToSurface;
|
||||
bool participate3DCtx = Extend3DContext() || Is3DContextLeaf();
|
||||
if (!participate3DCtx && GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
|
||||
// For backface-hidden layers
|
||||
transformToSurface.ProjectTo2D();
|
||||
}
|
||||
Matrix4x4 idealTransform = GetLocalTransform() * transformToSurface;
|
||||
if (!participate3DCtx && !(GetContentFlags() & CONTENT_BACKFACE_HIDDEN)) {
|
||||
// For non-backface-hidden layers,
|
||||
// 3D components are required to handle CONTENT_BACKFACE_HIDDEN.
|
||||
idealTransform.ProjectTo2D();
|
||||
}
|
||||
|
||||
if (!idealTransform.CanDraw2D()) {
|
||||
if (!Extend3DContext()) {
|
||||
mEffectiveTransform = idealTransform;
|
||||
ComputeEffectiveTransformsForChildren(Matrix4x4());
|
||||
ComputeEffectiveTransformForMaskLayers(Matrix4x4());
|
||||
mUseIntermediateSurface = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mEffectiveTransform = idealTransform;
|
||||
ComputeEffectiveTransformsForChildren(idealTransform);
|
||||
ComputeEffectiveTransformForMaskLayers(idealTransform);
|
||||
mUseIntermediateSurface = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// With 2D transform or extended 3D context.
|
||||
|
||||
Layer* child = GetFirstChild();
|
||||
bool hasSingleBlendingChild = false;
|
||||
if (!HasMultipleChildren() && child) {
|
||||
hasSingleBlendingChild = child->GetMixBlendMode() != CompositionOp::OP_OVER;
|
||||
}
|
||||
|
||||
/* If we have a single childand it is not blending,, it can just inherit our
|
||||
* opacity, otherwise we need a PushGroup and we need to mark ourselves as
|
||||
* using an intermediate surface so our children don't inherit our opacity via
|
||||
* GetEffectiveOpacity. Having a mask layer always forces our own push group
|
||||
* Having a blend mode also always forces our own push group
|
||||
*/
|
||||
mUseIntermediateSurface =
|
||||
GetMaskLayer() || GetForceIsolatedGroup() ||
|
||||
(GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
|
||||
(GetEffectiveOpacity() != 1.0 &&
|
||||
((HasMultipleChildren() && !Extend3DContext()) ||
|
||||
hasSingleBlendingChild));
|
||||
|
||||
mEffectiveTransform =
|
||||
!mUseIntermediateSurface
|
||||
? idealTransform
|
||||
: (!(GetContentFlags() & CONTENT_BACKFACE_HIDDEN)
|
||||
? SnapTransformTranslation(idealTransform, &residual)
|
||||
: SnapTransformTranslation3D(idealTransform, &residual));
|
||||
Matrix4x4 childTransformToSurface =
|
||||
(!mUseIntermediateSurface ||
|
||||
(mUseIntermediateSurface && !Extend3DContext() /* 2D */))
|
||||
? idealTransform
|
||||
: Matrix4x4::From2D(residual);
|
||||
ComputeEffectiveTransformsForChildren(childTransformToSurface);
|
||||
|
||||
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
|
||||
}
|
||||
|
||||
bool BasicContainerLayer::ChildrenPartitionVisibleRegion(
|
||||
const gfx::IntRect& aInRect) {
|
||||
Matrix transform;
|
||||
if (!GetEffectiveTransform().CanDraw2D(&transform) ||
|
||||
ThebesMatrix(transform).HasNonIntegerTranslation())
|
||||
return false;
|
||||
|
||||
nsIntPoint offset(int32_t(transform._31), int32_t(transform._32));
|
||||
gfx::IntRect rect = aInRect.Intersect(
|
||||
GetLocalVisibleRegion().GetBounds().ToUnknownRect() + offset);
|
||||
nsIntRegion covered;
|
||||
|
||||
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
|
||||
if (ToData(l)->IsHidden()) continue;
|
||||
|
||||
Matrix childTransform;
|
||||
if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) ||
|
||||
ThebesMatrix(childTransform).HasNonIntegerTranslation() ||
|
||||
l->GetEffectiveOpacity() != 1.0)
|
||||
return false;
|
||||
nsIntRegion childRegion = l->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
childRegion.MoveBy(int32_t(childTransform._31),
|
||||
int32_t(childTransform._32));
|
||||
childRegion.And(childRegion, rect);
|
||||
if (l->GetClipRect()) {
|
||||
childRegion.And(childRegion, l->GetClipRect()->ToUnknownRect() + offset);
|
||||
}
|
||||
nsIntRegion intersection;
|
||||
intersection.And(covered, childRegion);
|
||||
if (!intersection.IsEmpty()) return false;
|
||||
covered.Or(covered, childRegion);
|
||||
}
|
||||
|
||||
return covered.Contains(rect);
|
||||
}
|
||||
|
||||
void BasicContainerLayer::Validate(
|
||||
LayerManager::DrawPaintedLayerCallback aCallback, void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) {
|
||||
ReadbackProcessor readback;
|
||||
if (BasicManager()->IsRetained()) {
|
||||
readback.BuildUpdates(this);
|
||||
}
|
||||
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
|
||||
BasicImplData* data = ToData(l);
|
||||
data->Validate(aCallback, aCallbackData, &readback);
|
||||
if (l->GetMaskLayer()) {
|
||||
data = ToData(l->GetMaskLayer());
|
||||
data->Validate(aCallback, aCallbackData, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ContainerLayer> BasicLayerManager::CreateContainerLayer() {
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
RefPtr<ContainerLayer> layer = new BasicContainerLayer(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,103 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_BASICCONTAINERLAYER_H
|
||||
#define GFX_BASICCONTAINERLAYER_H
|
||||
|
||||
#include "BasicImplData.h" // for BasicImplData
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "Layers.h" // for Layer, ContainerLayer
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR
|
||||
#include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BasicContainerLayer : public ContainerLayer, public BasicImplData {
|
||||
public:
|
||||
explicit BasicContainerLayer(BasicLayerManager* aManager)
|
||||
: ContainerLayer(aManager, static_cast<BasicImplData*>(this)) {
|
||||
MOZ_COUNT_CTOR(BasicContainerLayer);
|
||||
mSupportsComponentAlphaChildren = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~BasicContainerLayer();
|
||||
|
||||
public:
|
||||
void SetVisibleRegion(const LayerIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
ContainerLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
bool InsertAfter(Layer* aChild, Layer* aAfter) override {
|
||||
if (!BasicManager()->InConstruction()) {
|
||||
NS_ERROR("Can only set properties in construction phase");
|
||||
return false;
|
||||
}
|
||||
return ContainerLayer::InsertAfter(aChild, aAfter);
|
||||
}
|
||||
|
||||
bool RemoveChild(Layer* aChild) override {
|
||||
if (!BasicManager()->InConstruction()) {
|
||||
NS_ERROR("Can only set properties in construction phase");
|
||||
return false;
|
||||
}
|
||||
return ContainerLayer::RemoveChild(aChild);
|
||||
}
|
||||
|
||||
bool RepositionChild(Layer* aChild, Layer* aAfter) override {
|
||||
if (!BasicManager()->InConstruction()) {
|
||||
NS_ERROR("Can only set properties in construction phase");
|
||||
return false;
|
||||
}
|
||||
return ContainerLayer::RepositionChild(aChild, aAfter);
|
||||
}
|
||||
|
||||
void ComputeEffectiveTransforms(
|
||||
const gfx::Matrix4x4& aTransformToSurface) override;
|
||||
|
||||
/**
|
||||
* Returns true when:
|
||||
* a) no (non-hidden) childrens' visible areas overlap in
|
||||
* (aInRect intersected with this layer's visible region).
|
||||
* b) the (non-hidden) childrens' visible areas cover
|
||||
* (aInRect intersected with this layer's visible region).
|
||||
* c) this layer and all (non-hidden) children have transforms that are
|
||||
* translations by integers. aInRect is in the root coordinate system. Child
|
||||
* layers with opacity do not contribute to the covered area in check b). This
|
||||
* method can be conservative; it's OK to return false under any
|
||||
* circumstances.
|
||||
*/
|
||||
bool ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect);
|
||||
|
||||
void ForceIntermediateSurface() { mUseIntermediateSurface = true; }
|
||||
|
||||
void SetSupportsComponentAlphaChildren(bool aSupports) {
|
||||
mSupportsComponentAlphaChildren = aSupports;
|
||||
}
|
||||
|
||||
void Validate(LayerManager::DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData, ReadbackProcessor* aReadback) override;
|
||||
|
||||
/**
|
||||
* We don't really have a hard restriction for max layer size, but we pick
|
||||
* 4096 to avoid excessive memory usage.
|
||||
*/
|
||||
int32_t GetMaxLayerSize() override { return 4096; }
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager() {
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BasicLayersImpl.h" // for FillRectWithMask, etc
|
||||
#include "ImageContainer.h" // for AutoLockImage, etc
|
||||
#include "ImageLayers.h" // for ImageLayer
|
||||
#include "Layers.h" // for Layer (ptr only), etc
|
||||
#include "basic/BasicImplData.h" // for BasicImplData
|
||||
#include "basic/BasicLayers.h" // for BasicLayerManager
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for gfxPattern::Release, etc
|
||||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla::layers {
|
||||
|
||||
class BasicImageLayer : public ImageLayer, public BasicImplData {
|
||||
public:
|
||||
explicit BasicImageLayer(BasicLayerManager* aLayerManager)
|
||||
: ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)),
|
||||
mSize(-1, -1) {
|
||||
MOZ_COUNT_CTOR(BasicImageLayer);
|
||||
}
|
||||
|
||||
protected:
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(BasicImageLayer)
|
||||
|
||||
public:
|
||||
void SetVisibleRegion(const LayerIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
ImageLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
void Paint(DrawTarget* aDT, const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) override;
|
||||
|
||||
already_AddRefed<SourceSurface> GetAsSourceSurface() override;
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager() {
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
|
||||
gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
void BasicImageLayer::Paint(DrawTarget* aDT, const gfx::Point& aDeviceOffset,
|
||||
Layer* aMaskLayer) {
|
||||
if (IsHidden() || !mContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ImageFactory> originalIF = mContainer->GetImageFactory();
|
||||
mContainer->SetImageFactory(mManager->IsCompositingCheap()
|
||||
? nullptr
|
||||
: BasicManager()->GetImageFactory());
|
||||
|
||||
AutoLockImage autoLock(mContainer);
|
||||
Image* image = autoLock.GetImage(BasicManager()->GetCompositionTime());
|
||||
if (!image) {
|
||||
mContainer->SetImageFactory(originalIF);
|
||||
return;
|
||||
}
|
||||
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
|
||||
if (!surface || !surface->IsValid()) {
|
||||
mContainer->SetImageFactory(originalIF);
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::IntSize size = mSize = surface->GetSize();
|
||||
FillRectWithMask(
|
||||
aDT, aDeviceOffset, Rect(0, 0, size.width, size.height), surface,
|
||||
mSamplingFilter,
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
|
||||
mContainer->SetImageFactory(originalIF);
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface> BasicImageLayer::GetAsSourceSurface() {
|
||||
if (!mContainer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoLockImage lockImage(mContainer);
|
||||
Image* image = lockImage.GetImage();
|
||||
if (!image) {
|
||||
return nullptr;
|
||||
}
|
||||
return image->GetAsSourceSurface();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageLayer> BasicLayerManager::CreateImageLayer() {
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
RefPtr<ImageLayer> layer = new BasicImageLayer(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla::layers
|
|
@ -1,180 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdint.h> // for uint8_t, uint32_t
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "ImageContainer.h" // for PlanarYCbCrImage, etc
|
||||
#include "ImageTypes.h" // for ImageFormat, etc
|
||||
#include "cairo.h" // for cairo_user_data_key_t
|
||||
#include "gfxASurface.h" // for gfxASurface, etc
|
||||
#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete[], etc
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_ERROR, NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for Image::Release, etc
|
||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "YCbCrUtils.h" // for YCbCr conversions
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BasicPlanarYCbCrImage : public RecyclingPlanarYCbCrImage {
|
||||
public:
|
||||
BasicPlanarYCbCrImage(const gfx::IntSize& aScaleHint,
|
||||
gfxImageFormat aOffscreenFormat,
|
||||
BufferRecycleBin* aRecycleBin)
|
||||
: RecyclingPlanarYCbCrImage(aRecycleBin),
|
||||
mScaleHint(aScaleHint),
|
||||
mStride(0),
|
||||
mDelayedConversion(false) {
|
||||
SetOffscreenFormat(aOffscreenFormat);
|
||||
}
|
||||
|
||||
~BasicPlanarYCbCrImage() {
|
||||
if (mDecodedBuffer) {
|
||||
// Right now this only happens if the Image was never drawn, otherwise
|
||||
// this will have been tossed away at surface destruction.
|
||||
mRecycleBin->RecycleBuffer(std::move(mDecodedBuffer),
|
||||
mSize.height * mStride);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool CopyData(const Data& aData) override;
|
||||
virtual void SetDelayedConversion(bool aDelayed) override {
|
||||
mDelayedConversion = aDelayed;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
|
||||
virtual size_t SizeOfIncludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const override {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const override {
|
||||
size_t size = RecyclingPlanarYCbCrImage::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += aMallocSizeOf(mDecodedBuffer.get());
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<uint8_t[]> mDecodedBuffer;
|
||||
gfx::IntSize mScaleHint;
|
||||
int mStride;
|
||||
bool mDelayedConversion;
|
||||
};
|
||||
|
||||
class BasicImageFactory : public ImageFactory {
|
||||
public:
|
||||
BasicImageFactory() = default;
|
||||
|
||||
virtual RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage(
|
||||
const gfx::IntSize& aScaleHint, BufferRecycleBin* aRecycleBin) override {
|
||||
return new BasicPlanarYCbCrImage(
|
||||
aScaleHint, gfxPlatform::GetPlatform()->GetOffscreenFormat(),
|
||||
aRecycleBin);
|
||||
}
|
||||
};
|
||||
|
||||
bool BasicPlanarYCbCrImage::CopyData(const Data& aData) {
|
||||
RecyclingPlanarYCbCrImage::CopyData(aData);
|
||||
|
||||
if (mDelayedConversion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do some sanity checks to prevent integer overflow
|
||||
if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image source width or height");
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat format =
|
||||
gfx::ImageFormatToSurfaceFormat(GetOffscreenFormat());
|
||||
|
||||
gfx::IntSize size(mScaleHint);
|
||||
gfx::GetYCbCrToRGBDestFormatAndSize(aData, format, size);
|
||||
if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
size.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image dest width or height");
|
||||
return false;
|
||||
}
|
||||
|
||||
mStride = gfx::StrideForFormatAndWidth(format, size.width);
|
||||
mozilla::CheckedInt32 requiredBytes =
|
||||
mozilla::CheckedInt32(size.height) * mozilla::CheckedInt32(mStride);
|
||||
if (!requiredBytes.isValid()) {
|
||||
// invalid size
|
||||
return false;
|
||||
}
|
||||
mDecodedBuffer = AllocateBuffer(requiredBytes.value());
|
||||
if (!mDecodedBuffer) {
|
||||
// out of memory
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer.get(), mStride);
|
||||
SetOffscreenFormat(gfx::SurfaceFormatToImageFormat(format));
|
||||
mSize = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
BasicPlanarYCbCrImage::GetAsSourceSurface() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
|
||||
|
||||
if (mSourceSurface) {
|
||||
RefPtr<gfx::SourceSurface> surface(mSourceSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
if (!mDecodedBuffer) {
|
||||
return PlanarYCbCrImage::GetAsSourceSurface();
|
||||
}
|
||||
|
||||
gfxImageFormat format = GetOffscreenFormat();
|
||||
|
||||
RefPtr<gfx::SourceSurface> surface;
|
||||
{
|
||||
// Create a DrawTarget so that we can own the data inside mDecodeBuffer.
|
||||
// We create the target out of mDecodedBuffer, and get a snapshot from it.
|
||||
// The draw target is destroyed on scope exit and the surface owns the data.
|
||||
RefPtr<gfx::DrawTarget> drawTarget = gfxPlatform::CreateDrawTargetForData(
|
||||
mDecodedBuffer.get(), mSize, mStride,
|
||||
gfx::ImageFormatToSurfaceFormat(format));
|
||||
if (!drawTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface = drawTarget->Snapshot();
|
||||
}
|
||||
|
||||
mRecycleBin->RecycleBuffer(std::move(mDecodedBuffer), mSize.height * mStride);
|
||||
|
||||
mSourceSurface = surface;
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
ImageFactory* BasicLayerManager::GetImageFactory() {
|
||||
if (!mFactory) {
|
||||
mFactory = new BasicImageFactory();
|
||||
}
|
||||
|
||||
return mFactory.get();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,973 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include <stdlib.h> // for rand, RAND_MAX
|
||||
#include <sys/types.h> // for int32_t
|
||||
#include <stack> // for stack
|
||||
#include "BasicContainerLayer.h" // for BasicContainerLayer
|
||||
#include "BasicLayersImpl.h" // for ToData, BasicReadbackLayer, etc
|
||||
#include "ImageContainer.h" // for ImageFactory
|
||||
#include "Layers.h" // for Layer, ContainerLayer, etc
|
||||
#include "ReadbackLayer.h" // for ReadbackLayer
|
||||
#include "ReadbackProcessor.h" // for ReadbackProcessor
|
||||
#include "RenderTrace.h" // for RenderTraceLayers, etc
|
||||
#include "basic/BasicImplData.h" // for BasicImplData
|
||||
#include "basic/BasicLayers.h" // for BasicLayerManager, etc
|
||||
#include "gfxASurface.h" // for gfxASurface, etc
|
||||
#include "gfxContext.h" // for gfxContext, etc
|
||||
#include "gfxImageSurface.h" // for gfxImageSurface
|
||||
#include "gfxMatrix.h" // for gfxMatrix
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
|
||||
#include "gfxPoint.h" // for IntSize, gfxPoint
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "gfx2DGlue.h" // for thebes --> moz2d transition
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/ProfilerLabels.h"
|
||||
#include "mozilla/StaticPrefs_nglayout.h"
|
||||
#include "mozilla/WidgetUtils.h" // for ScreenRotation
|
||||
#include "mozilla/gfx/2D.h" // for DrawTarget
|
||||
#include "mozilla/gfx/BasePoint.h" // for BasePoint
|
||||
#include "mozilla/gfx/BaseRect.h" // for BaseRect
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/gfx/Rect.h" // for IntRect, Rect
|
||||
#include "mozilla/layers/BSPTree.h"
|
||||
#include "mozilla/layers/LayersTypes.h" // for BufferMode::BUFFER_NONE, etc
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_ASSERTION, etc
|
||||
#include "nsISupportsImpl.h" // for gfxContext::Release, etc
|
||||
#include "nsLayoutUtils.h" // for nsLayoutUtils
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "nsRegion.h" // for nsIntRegion, etc
|
||||
#include "nsTArray.h" // for AutoTArray
|
||||
#include "TreeTraversal.h" // for ForEachNode
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
/**
|
||||
* Clips to the smallest device-pixel-aligned rectangle containing aRect
|
||||
* in user space.
|
||||
* Returns true if the clip is "perfect", i.e. we actually clipped exactly to
|
||||
* aRect.
|
||||
*/
|
||||
static bool ClipToContain(gfxContext* aContext, const IntRect& aRect) {
|
||||
gfxRect userRect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
|
||||
gfxRect deviceRect = aContext->UserToDevice(userRect);
|
||||
deviceRect.RoundOut();
|
||||
|
||||
Matrix currentMatrix = aContext->CurrentMatrix();
|
||||
aContext->SetMatrix(Matrix());
|
||||
aContext->NewPath();
|
||||
aContext->Rectangle(deviceRect);
|
||||
aContext->Clip();
|
||||
aContext->SetMatrix(currentMatrix);
|
||||
|
||||
return aContext->DeviceToUser(deviceRect).IsEqualInterior(userRect);
|
||||
}
|
||||
|
||||
bool BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
|
||||
const nsIntRegion& aRegion,
|
||||
PushedGroup& aGroupResult) {
|
||||
aGroupResult.mVisibleRegion = aRegion;
|
||||
aGroupResult.mFinalTarget = aContext;
|
||||
aGroupResult.mOperator = GetEffectiveOperator(aLayer);
|
||||
aGroupResult.mOpacity = aLayer->GetEffectiveOpacity();
|
||||
|
||||
// If we need to call PushGroup, we should clip to the smallest possible
|
||||
// area first to minimize the size of the temporary surface.
|
||||
bool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
|
||||
|
||||
bool canPushGroup =
|
||||
aGroupResult.mOperator == CompositionOp::OP_OVER ||
|
||||
(aGroupResult.mOperator == CompositionOp::OP_SOURCE &&
|
||||
(aLayer->CanUseOpaqueSurface() ||
|
||||
aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA));
|
||||
|
||||
if (!canPushGroup) {
|
||||
aContext->Save();
|
||||
// Restore() is called in PopGroupForLayer
|
||||
// if group.mFinalTarget != group.mGroupTarget
|
||||
|
||||
gfxUtils::ClipToRegion(aGroupResult.mFinalTarget,
|
||||
aGroupResult.mVisibleRegion);
|
||||
|
||||
// PushGroup/PopGroup do not support non operator over.
|
||||
gfxRect rect = aContext->GetClipExtents(gfxContext::eDeviceSpace);
|
||||
rect.RoundOut();
|
||||
IntRect surfRect;
|
||||
ToRect(rect).ToIntRect(&surfRect);
|
||||
|
||||
if (!surfRect.IsEmpty()) {
|
||||
RefPtr<DrawTarget> dt;
|
||||
if (aContext->GetDrawTarget()->CanCreateSimilarDrawTarget(
|
||||
surfRect.Size(), SurfaceFormat::B8G8R8A8)) {
|
||||
dt = aContext->GetDrawTarget()->CreateSimilarDrawTarget(
|
||||
surfRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
}
|
||||
|
||||
RefPtr<gfxContext> ctx =
|
||||
gfxContext::CreateOrNull(dt, ToRect(rect).TopLeft());
|
||||
if (!ctx) {
|
||||
gfxCriticalNote
|
||||
<< "BasicLayerManager context problem in PushGroupForLayer "
|
||||
<< gfx::hexa(dt);
|
||||
aContext->Restore();
|
||||
return false;
|
||||
}
|
||||
ctx->SetMatrix(aContext->CurrentMatrix());
|
||||
|
||||
aGroupResult.mGroupOffset = surfRect.TopLeft();
|
||||
aGroupResult.mGroupTarget = ctx;
|
||||
|
||||
aGroupResult.mMaskSurface =
|
||||
GetMaskForLayer(aLayer, &aGroupResult.mMaskTransform);
|
||||
return true;
|
||||
}
|
||||
aContext->Restore();
|
||||
}
|
||||
|
||||
Matrix maskTransform;
|
||||
RefPtr<SourceSurface> maskSurf = GetMaskForLayer(aLayer, &maskTransform);
|
||||
|
||||
if (maskSurf) {
|
||||
// The returned transform will transform the mask to device space on the
|
||||
// destination. Since the User->Device space transform will be applied
|
||||
// to the mask by PopGroupAndBlend we need to adjust the transform to
|
||||
// transform the mask to user space.
|
||||
Matrix currentTransform = aGroupResult.mFinalTarget->CurrentMatrix();
|
||||
currentTransform.Invert();
|
||||
maskTransform = maskTransform * currentTransform;
|
||||
}
|
||||
|
||||
if (aLayer->CanUseOpaqueSurface() &&
|
||||
((didCompleteClip && aRegion.GetNumRects() == 1) ||
|
||||
!aContext->CurrentMatrix().HasNonIntegerTranslation())) {
|
||||
// If the layer is opaque in its visible region we can push a
|
||||
// gfxContentType::COLOR group. We need to make sure that only pixels inside
|
||||
// the layer's visible region are copied back to the destination. Remember
|
||||
// if we've already clipped precisely to the visible region.
|
||||
aGroupResult.mNeedsClipToVisibleRegion =
|
||||
!didCompleteClip || aRegion.GetNumRects() > 1;
|
||||
if (aGroupResult.mNeedsClipToVisibleRegion) {
|
||||
aGroupResult.mFinalTarget->Save();
|
||||
gfxUtils::ClipToRegion(aGroupResult.mFinalTarget,
|
||||
aGroupResult.mVisibleRegion);
|
||||
}
|
||||
|
||||
aContext->PushGroupForBlendBack(
|
||||
gfxContentType::COLOR, aGroupResult.mOpacity, maskSurf, maskTransform);
|
||||
} else {
|
||||
if (aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) {
|
||||
aContext->PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA,
|
||||
aGroupResult.mOpacity, maskSurf,
|
||||
maskTransform);
|
||||
} else {
|
||||
aContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA,
|
||||
aGroupResult.mOpacity, maskSurf,
|
||||
maskTransform);
|
||||
}
|
||||
}
|
||||
|
||||
aGroupResult.mGroupTarget = aGroupResult.mFinalTarget;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BasicLayerManager::PopGroupForLayer(PushedGroup& group) {
|
||||
if (group.mFinalTarget == group.mGroupTarget) {
|
||||
group.mFinalTarget->PopGroupAndBlend();
|
||||
if (group.mNeedsClipToVisibleRegion) {
|
||||
group.mFinalTarget->Restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DrawTarget* dt = group.mFinalTarget->GetDrawTarget();
|
||||
RefPtr<DrawTarget> sourceDT = group.mGroupTarget->GetDrawTarget();
|
||||
group.mGroupTarget = nullptr;
|
||||
|
||||
RefPtr<SourceSurface> src = sourceDT->Snapshot();
|
||||
|
||||
if (group.mMaskSurface) {
|
||||
Point finalOffset = group.mFinalTarget->GetDeviceOffset();
|
||||
dt->SetTransform(group.mMaskTransform * Matrix::Translation(-finalOffset));
|
||||
Matrix surfTransform = group.mMaskTransform;
|
||||
surfTransform.Invert();
|
||||
dt->MaskSurface(SurfacePattern(src, ExtendMode::CLAMP,
|
||||
surfTransform * Matrix::Translation(
|
||||
group.mGroupOffset.x,
|
||||
group.mGroupOffset.y)),
|
||||
group.mMaskSurface, Point(0, 0),
|
||||
DrawOptions(group.mOpacity, group.mOperator));
|
||||
} else {
|
||||
// For now this is required since our group offset is in device space of the
|
||||
// final target, context but that may still have its own device offset. Once
|
||||
// PushGroup/PopGroup logic is migrated to DrawTargets this can go as
|
||||
// gfxContext::GetDeviceOffset will essentially always become null.
|
||||
dt->SetTransform(
|
||||
Matrix::Translation(-group.mFinalTarget->GetDeviceOffset()));
|
||||
dt->DrawSurface(src,
|
||||
Rect(group.mGroupOffset.x, group.mGroupOffset.y,
|
||||
src->GetSize().width, src->GetSize().height),
|
||||
Rect(0, 0, src->GetSize().width, src->GetSize().height),
|
||||
DrawSurfaceOptions(SamplingFilter::POINT),
|
||||
DrawOptions(group.mOpacity, group.mOperator));
|
||||
}
|
||||
|
||||
if (group.mNeedsClipToVisibleRegion) {
|
||||
dt->PopClip();
|
||||
}
|
||||
|
||||
group.mFinalTarget->Restore();
|
||||
}
|
||||
|
||||
static IntRect ToInsideIntRect(const gfxRect& aRect) {
|
||||
return IntRect::RoundIn(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
|
||||
}
|
||||
|
||||
// A context helper for BasicLayerManager::PaintLayer() that holds all the
|
||||
// painting context together in a data structure so it can be easily passed
|
||||
// around. It also uses ensures that the Transform and Opaque rect are restored
|
||||
// to their former state on destruction.
|
||||
|
||||
class PaintLayerContext {
|
||||
public:
|
||||
PaintLayerContext(gfxContext* aTarget, Layer* aLayer,
|
||||
LayerManager::DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
: mTarget(aTarget),
|
||||
mTargetMatrixSR(aTarget),
|
||||
mLayer(aLayer),
|
||||
mCallback(aCallback),
|
||||
mCallbackData(aCallbackData),
|
||||
mPushedOpaqueRect(false) {}
|
||||
|
||||
~PaintLayerContext() {
|
||||
// Matrix is restored by mTargetMatrixSR
|
||||
if (mPushedOpaqueRect) {
|
||||
ClearOpaqueRect();
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the effective transform and returns true if it is a 2D
|
||||
// transform.
|
||||
bool Setup2DTransform() {
|
||||
// Will return an identity matrix for 3d transforms.
|
||||
return mLayer->GetEffectiveTransformForBuffer().CanDraw2D(&mTransform);
|
||||
}
|
||||
|
||||
// Applies the effective transform if it's 2D. If it's a 3D transform then
|
||||
// it applies an identity.
|
||||
void Apply2DTransform() { mTarget->SetMatrix(mTransform); }
|
||||
|
||||
// Set the opaque rect to match the bounds of the visible region.
|
||||
void AnnotateOpaqueRect() {
|
||||
const nsIntRegion visibleRegion =
|
||||
mLayer->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
const IntRect& bounds = visibleRegion.GetBounds();
|
||||
|
||||
DrawTarget* dt = mTarget->GetDrawTarget();
|
||||
const IntRect& targetOpaqueRect = dt->GetOpaqueRect();
|
||||
|
||||
// Try to annotate currentSurface with a region of pixels that have been
|
||||
// (or will be) painted opaque, if no such region is currently set.
|
||||
if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
|
||||
(mLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
|
||||
!mTransform.HasNonAxisAlignedTransform()) {
|
||||
gfx::Rect opaqueRect = dt->GetTransform().TransformBounds(
|
||||
gfx::Rect(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height()));
|
||||
opaqueRect.RoundIn();
|
||||
IntRect intOpaqueRect;
|
||||
if (opaqueRect.ToIntRect(&intOpaqueRect)) {
|
||||
mTarget->GetDrawTarget()->SetOpaqueRect(intOpaqueRect);
|
||||
mPushedOpaqueRect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the Opaque rect. Although this doesn't really restore it to it's
|
||||
// previous state it will happen on the exit path of the PaintLayer() so when
|
||||
// painting is complete the opaque rect qill be clear.
|
||||
void ClearOpaqueRect() { mTarget->GetDrawTarget()->SetOpaqueRect(IntRect()); }
|
||||
|
||||
gfxContext* mTarget;
|
||||
gfxContextMatrixAutoSaveRestore mTargetMatrixSR;
|
||||
Layer* mLayer;
|
||||
LayerManager::DrawPaintedLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
Matrix mTransform;
|
||||
bool mPushedOpaqueRect;
|
||||
};
|
||||
|
||||
BasicLayerManager::BasicLayerManager(nsIWidget* aWidget)
|
||||
: mPhase(PHASE_NONE),
|
||||
mWidget(aWidget),
|
||||
mDoubleBuffering(BufferMode::BUFFER_NONE),
|
||||
mType(BLM_WIDGET),
|
||||
mUsingDefaultTarget(false),
|
||||
mTransactionIncomplete(false),
|
||||
mCompositorMightResample(false) {
|
||||
MOZ_COUNT_CTOR(BasicLayerManager);
|
||||
NS_ASSERTION(aWidget, "Must provide a widget");
|
||||
}
|
||||
|
||||
BasicLayerManager::BasicLayerManager(BasicLayerManagerType aType)
|
||||
: mPhase(PHASE_NONE),
|
||||
mWidget(nullptr),
|
||||
mDoubleBuffering(BufferMode::BUFFER_NONE),
|
||||
mType(aType),
|
||||
mUsingDefaultTarget(false),
|
||||
mTransactionIncomplete(false),
|
||||
mCompositorMightResample(false) {
|
||||
MOZ_COUNT_CTOR(BasicLayerManager);
|
||||
MOZ_ASSERT(mType != BLM_WIDGET);
|
||||
}
|
||||
|
||||
BasicLayerManager::~BasicLayerManager() {
|
||||
NS_ASSERTION(!InTransaction(), "Died during transaction?");
|
||||
|
||||
ClearCachedResources();
|
||||
|
||||
mRoot = nullptr;
|
||||
|
||||
MOZ_COUNT_DTOR(BasicLayerManager);
|
||||
}
|
||||
|
||||
void BasicLayerManager::SetDefaultTarget(gfxContext* aContext) {
|
||||
NS_ASSERTION(!InTransaction(), "Must set default target outside transaction");
|
||||
mDefaultTarget = aContext;
|
||||
}
|
||||
|
||||
void BasicLayerManager::SetDefaultTargetConfiguration(
|
||||
BufferMode aDoubleBuffering, ScreenRotation aRotation) {
|
||||
mDoubleBuffering = aDoubleBuffering;
|
||||
}
|
||||
|
||||
bool BasicLayerManager::BeginTransaction(const nsCString& aURL) {
|
||||
mInTransaction = true;
|
||||
mUsingDefaultTarget = true;
|
||||
return BeginTransactionWithTarget(mDefaultTarget, aURL);
|
||||
}
|
||||
|
||||
bool BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget,
|
||||
const nsCString& aURL) {
|
||||
mInTransaction = true;
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
MOZ_LAYERS_LOG(("[----- BeginTransaction"));
|
||||
Log();
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
|
||||
mPhase = PHASE_CONSTRUCTION;
|
||||
mTarget = aTarget;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void TransformIntRect(IntRect& aRect, const Matrix& aMatrix,
|
||||
IntRect (*aRoundMethod)(const gfxRect&)) {
|
||||
Rect gr = Rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
|
||||
gr = aMatrix.TransformBounds(gr);
|
||||
aRect = (*aRoundMethod)(ThebesRect(gr));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function assumes that GetEffectiveTransform transforms
|
||||
* all layers to the same coordinate system (the "root coordinate system").
|
||||
* It can't be used as is by accelerated layers because of intermediate
|
||||
* surfaces. This must set the hidden flag to true or false on *all* layers in
|
||||
* the subtree. It also sets the operator for all layers to "OVER", and call
|
||||
* SetDrawAtomically(false).
|
||||
* It clears mClipToVisibleRegion on all layers.
|
||||
* @param aClipRect the cliprect, in the root coordinate system. We assume
|
||||
* that any layer drawing is clipped to this rect. It is therefore not
|
||||
* allowed to add to the opaque region outside that rect.
|
||||
* @param aDirtyRect the dirty rect that will be painted, in the root
|
||||
* coordinate system. Layers outside this rect should be hidden.
|
||||
* @param aOpaqueRegion the opaque region covering aLayer, in the
|
||||
* root coordinate system.
|
||||
*/
|
||||
enum {
|
||||
ALLOW_OPAQUE = 0x01,
|
||||
};
|
||||
static void MarkLayersHidden(Layer* aLayer, const IntRect& aClipRect,
|
||||
const IntRect& aDirtyRect,
|
||||
nsIntRegion& aOpaqueRegion, uint32_t aFlags) {
|
||||
IntRect newClipRect(aClipRect);
|
||||
uint32_t newFlags = aFlags;
|
||||
|
||||
// Allow aLayer or aLayer's descendants to cover underlying layers
|
||||
// only if it's opaque.
|
||||
if (aLayer->GetOpacity() != 1.0f) {
|
||||
newFlags &= ~ALLOW_OPAQUE;
|
||||
}
|
||||
|
||||
{
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
if (clipRect) {
|
||||
IntRect cr = clipRect->ToUnknownRect();
|
||||
// clipRect is in the container's coordinate system. Get it into the
|
||||
// global coordinate system.
|
||||
if (aLayer->GetParent()) {
|
||||
Matrix tr;
|
||||
if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
|
||||
// Clip rect is applied after aLayer's transform, i.e., in the
|
||||
// coordinate system of aLayer's parent.
|
||||
TransformIntRect(cr, tr, ToInsideIntRect);
|
||||
} else {
|
||||
cr.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
newClipRect.IntersectRect(newClipRect, cr);
|
||||
}
|
||||
}
|
||||
|
||||
BasicImplData* data = ToData(aLayer);
|
||||
data->SetOperator(CompositionOp::OP_OVER);
|
||||
data->SetClipToVisibleRegion(false);
|
||||
data->SetDrawAtomically(false);
|
||||
|
||||
if (!aLayer->AsContainerLayer()) {
|
||||
Matrix transform;
|
||||
if (!aLayer->GetEffectiveTransform().CanDraw2D(&transform)) {
|
||||
data->SetHidden(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRegion region = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
IntRect r = region.GetBounds();
|
||||
TransformIntRect(r, transform, ToOutsideIntRect);
|
||||
r.IntersectRect(r, aDirtyRect);
|
||||
data->SetHidden(aOpaqueRegion.Contains(r));
|
||||
|
||||
// Allow aLayer to cover underlying layers only if aLayer's
|
||||
// content is opaque
|
||||
if ((aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
|
||||
(newFlags & ALLOW_OPAQUE)) {
|
||||
for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
|
||||
r = iter.Get();
|
||||
TransformIntRect(r, transform, ToInsideIntRect);
|
||||
|
||||
r.IntersectRect(r, newClipRect);
|
||||
aOpaqueRegion.Or(aOpaqueRegion, r);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Layer* child = aLayer->GetLastChild();
|
||||
bool allHidden = true;
|
||||
for (; child; child = child->GetPrevSibling()) {
|
||||
MarkLayersHidden(child, newClipRect, aDirtyRect, aOpaqueRegion, newFlags);
|
||||
if (!ToData(child)->IsHidden()) {
|
||||
allHidden = false;
|
||||
}
|
||||
}
|
||||
data->SetHidden(allHidden);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function assumes that GetEffectiveTransform transforms
|
||||
* all layers to the same coordinate system (the "root coordinate system").
|
||||
* MarkLayersHidden must be called before calling this.
|
||||
* @param aVisibleRect the rectangle of aLayer that is visible (i.e. not
|
||||
* clipped and in the dirty rect), in the root coordinate system.
|
||||
*/
|
||||
static void ApplyDoubleBuffering(Layer* aLayer, const IntRect& aVisibleRect) {
|
||||
BasicImplData* data = ToData(aLayer);
|
||||
if (data->IsHidden()) return;
|
||||
|
||||
IntRect newVisibleRect(aVisibleRect);
|
||||
|
||||
{
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
if (clipRect) {
|
||||
IntRect cr = clipRect->ToUnknownRect();
|
||||
// clipRect is in the container's coordinate system. Get it into the
|
||||
// global coordinate system.
|
||||
if (aLayer->GetParent()) {
|
||||
Matrix tr;
|
||||
if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
|
||||
NS_ASSERTION(!ThebesMatrix(tr).HasNonIntegerTranslation(),
|
||||
"Parent can only have an integer translation");
|
||||
cr += nsIntPoint(int32_t(tr._31), int32_t(tr._32));
|
||||
} else {
|
||||
NS_ERROR("Parent can only have an integer translation");
|
||||
}
|
||||
}
|
||||
newVisibleRect.IntersectRect(newVisibleRect, cr);
|
||||
}
|
||||
}
|
||||
|
||||
BasicContainerLayer* container =
|
||||
static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
|
||||
// Layers that act as their own backbuffers should be drawn to the destination
|
||||
// using OP_SOURCE to ensure that alpha values in a transparent window are
|
||||
// cleared. This can also be faster than OP_OVER.
|
||||
if (!container) {
|
||||
data->SetOperator(CompositionOp::OP_SOURCE);
|
||||
data->SetDrawAtomically(true);
|
||||
} else {
|
||||
if (container->UseIntermediateSurface() ||
|
||||
!container->ChildrenPartitionVisibleRegion(newVisibleRect)) {
|
||||
// We need to double-buffer this container.
|
||||
data->SetOperator(CompositionOp::OP_SOURCE);
|
||||
container->ForceIntermediateSurface();
|
||||
} else {
|
||||
// Tell the children to clip to their visible regions so our assumption
|
||||
// that they don't paint outside their visible regions is valid!
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
ToData(child)->SetClipToVisibleRegion(true);
|
||||
ApplyDoubleBuffering(child, newVisibleRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags) {
|
||||
mInTransaction = false;
|
||||
|
||||
EndTransactionInternal(aCallback, aCallbackData, aFlags);
|
||||
}
|
||||
|
||||
void BasicLayerManager::AbortTransaction() {
|
||||
NS_ASSERTION(InConstruction(), "Should be in construction phase");
|
||||
mPhase = PHASE_NONE;
|
||||
mUsingDefaultTarget = false;
|
||||
mInTransaction = false;
|
||||
}
|
||||
|
||||
bool BasicLayerManager::EndTransactionInternal(
|
||||
DrawPaintedLayerCallback aCallback, void* aCallbackData,
|
||||
EndTransactionFlags aFlags) {
|
||||
AUTO_PROFILER_LABEL("BasicLayerManager::EndTransactionInternal", GRAPHICS);
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
MOZ_LAYERS_LOG((" ----- (beginning paint)"));
|
||||
Log();
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(InConstruction(), "Should be in construction phase");
|
||||
mPhase = PHASE_DRAWING;
|
||||
|
||||
SetCompositionTime(TimeStamp::Now());
|
||||
|
||||
RenderTraceLayers(mRoot, "FF00");
|
||||
|
||||
mTransactionIncomplete = false;
|
||||
|
||||
std::unordered_set<ScrollableLayerGuid::ViewID> scrollIdsUpdated;
|
||||
|
||||
if (mRoot) {
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
// Apply pending tree updates before recomputing effective
|
||||
// properties.
|
||||
scrollIdsUpdated = mRoot->ApplyPendingUpdatesToSubtree();
|
||||
}
|
||||
|
||||
// Need to do this before we call ApplyDoubleBuffering,
|
||||
// which depends on correct effective transforms
|
||||
if (mTarget) {
|
||||
mSnapEffectiveTransforms =
|
||||
!mTarget->GetDrawTarget()->GetUserData(&sDisablePixelSnapping);
|
||||
} else {
|
||||
mSnapEffectiveTransforms = true;
|
||||
}
|
||||
mRoot->ComputeEffectiveTransforms(
|
||||
mTarget ? Matrix4x4::From2D(mTarget->CurrentMatrix()) : Matrix4x4());
|
||||
|
||||
ToData(mRoot)->Validate(aCallback, aCallbackData, nullptr);
|
||||
if (mRoot->GetMaskLayer()) {
|
||||
ToData(mRoot->GetMaskLayer())
|
||||
->Validate(aCallback, aCallbackData, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW) &&
|
||||
!(aFlags & END_NO_COMPOSITE)) {
|
||||
IntRect clipRect =
|
||||
ToOutsideIntRect(mTarget->GetClipExtents(gfxContext::eDeviceSpace));
|
||||
|
||||
if (IsRetained()) {
|
||||
nsIntRegion region;
|
||||
MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
|
||||
if (mUsingDefaultTarget && mDoubleBuffering != BufferMode::BUFFER_NONE) {
|
||||
ApplyDoubleBuffering(mRoot, clipRect);
|
||||
}
|
||||
}
|
||||
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData);
|
||||
if (!mRegionToClear.IsEmpty()) {
|
||||
for (auto iter = mRegionToClear.RectIter(); !iter.Done(); iter.Next()) {
|
||||
const IntRect& r = iter.Get();
|
||||
mTarget->GetDrawTarget()->ClearRect(
|
||||
Rect(r.X(), r.Y(), r.Width(), r.Height()));
|
||||
}
|
||||
}
|
||||
if (mWidget) {
|
||||
FlashWidgetUpdateArea(mTarget);
|
||||
}
|
||||
RecordFrame();
|
||||
|
||||
if (!mTransactionIncomplete) {
|
||||
// Clear out target if we have a complete transaction.
|
||||
mTarget = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mRoot) {
|
||||
mAnimationReadyTime = TimeStamp::Now();
|
||||
mRoot->StartPendingAnimations(mAnimationReadyTime);
|
||||
|
||||
// Once we're sure we're not going to fall back to a full paint,
|
||||
// notify the scroll frames which had pending updates.
|
||||
if (!mTransactionIncomplete) {
|
||||
for (ScrollableLayerGuid::ViewID scrollId : scrollIdsUpdated) {
|
||||
nsLayoutUtils::NotifyPaintSkipTransaction(scrollId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
Log();
|
||||
MOZ_LAYERS_LOG(("]----- EndTransaction"));
|
||||
#endif
|
||||
|
||||
// Go back to the construction phase if the transaction isn't complete.
|
||||
// Layout will update the layer tree and call EndTransaction().
|
||||
mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
|
||||
|
||||
if (!mTransactionIncomplete) {
|
||||
// This is still valid if the transaction was incomplete.
|
||||
mUsingDefaultTarget = false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!aCallback || !mTransactionIncomplete,
|
||||
"If callback is not null, transaction must be complete");
|
||||
|
||||
// XXX - We should probably assert here that for an incomplete transaction
|
||||
// out target is the default target.
|
||||
|
||||
return !mTransactionIncomplete;
|
||||
}
|
||||
|
||||
void BasicLayerManager::FlashWidgetUpdateArea(gfxContext* aContext) {
|
||||
if (StaticPrefs::nglayout_debug_widget_update_flashing()) {
|
||||
float r = float(rand()) / float(RAND_MAX);
|
||||
float g = float(rand()) / float(RAND_MAX);
|
||||
float b = float(rand()) / float(RAND_MAX);
|
||||
aContext->SetDeviceColor(DeviceColor(r, g, b, 0.2f));
|
||||
aContext->Paint();
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
|
||||
mInTransaction = false;
|
||||
|
||||
if (!mRoot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return EndTransactionInternal(nullptr, nullptr, aFlags);
|
||||
}
|
||||
|
||||
void BasicLayerManager::SetRoot(Layer* aLayer) {
|
||||
NS_ASSERTION(aLayer, "Root can't be null");
|
||||
NS_ASSERTION(aLayer->Manager() == this, "Wrong manager");
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
mRoot = aLayer;
|
||||
}
|
||||
|
||||
void BasicLayerManager::PaintSelfOrChildren(PaintLayerContext& aPaintContext,
|
||||
gfxContext* aGroupTarget) {
|
||||
MOZ_ASSERT(aGroupTarget);
|
||||
BasicImplData* data = ToData(aPaintContext.mLayer);
|
||||
|
||||
/* Only paint ourself, or our children - This optimization relies on this! */
|
||||
Layer* child = aPaintContext.mLayer->GetFirstChild();
|
||||
if (!child) {
|
||||
if (aPaintContext.mLayer->AsPaintedLayer()) {
|
||||
data->PaintThebes(aGroupTarget, aPaintContext.mLayer->GetMaskLayer(),
|
||||
aPaintContext.mCallback, aPaintContext.mCallbackData);
|
||||
} else {
|
||||
data->Paint(aGroupTarget->GetDrawTarget(),
|
||||
aGroupTarget->GetDeviceOffset(),
|
||||
aPaintContext.mLayer->GetMaskLayer());
|
||||
}
|
||||
} else {
|
||||
ContainerLayer* container =
|
||||
static_cast<ContainerLayer*>(aPaintContext.mLayer);
|
||||
|
||||
nsTArray<LayerPolygon> children = container->SortChildrenBy3DZOrder(
|
||||
ContainerLayer::SortMode::WITHOUT_GEOMETRY);
|
||||
|
||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
||||
Layer* layer = children.ElementAt(i).data;
|
||||
if (layer->IsBackfaceHidden()) {
|
||||
continue;
|
||||
}
|
||||
if (!layer->AsContainerLayer() && !layer->IsVisible()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PaintLayer(aGroupTarget, layer, aPaintContext.mCallback,
|
||||
aPaintContext.mCallbackData);
|
||||
if (mTransactionIncomplete) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext,
|
||||
bool aNeedsClipToVisibleRegion) {
|
||||
// If we're doing our own double-buffering, we need to avoid drawing
|
||||
// the results of an incomplete transaction to the destination surface ---
|
||||
// that could cause flicker. Double-buffering is implemented using a
|
||||
// temporary surface for one or more container layers, so we need to stop
|
||||
// those temporary surfaces from being composited to aTarget.
|
||||
// ApplyDoubleBuffering guarantees that this container layer can't
|
||||
// intersect any other leaf layers, so if the transaction is not yet marked
|
||||
// incomplete, the contents of this container layer are the final contents
|
||||
// for the window.
|
||||
if (!mTransactionIncomplete) {
|
||||
if (aNeedsClipToVisibleRegion) {
|
||||
gfxUtils::ClipToRegion(
|
||||
aPaintContext.mTarget,
|
||||
aPaintContext.mLayer->GetLocalVisibleRegion().ToUnknownRegion());
|
||||
}
|
||||
|
||||
CompositionOp op = GetEffectiveOperator(aPaintContext.mLayer);
|
||||
AutoSetOperator setOperator(aPaintContext.mTarget, op);
|
||||
|
||||
PaintWithMask(aPaintContext.mTarget,
|
||||
aPaintContext.mLayer->GetEffectiveOpacity(),
|
||||
aPaintContext.mLayer->GetMaskLayer());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the clip applied to the layer on the given gfxContext. The
|
||||
* given gfxContext is the buffer that the layer will be painted to.
|
||||
*/
|
||||
static void InstallLayerClipPreserves3D(gfxContext* aTarget, Layer* aLayer) {
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
|
||||
if (!clipRect) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(
|
||||
!aLayer->Extend3DContext() || !aLayer->Combines3DTransformWithAncestors(),
|
||||
"Layers in a preserve 3D context have no clip"
|
||||
" except leaves and the estabisher!");
|
||||
|
||||
Layer* parent = aLayer->GetParent();
|
||||
Matrix4x4 transform3d = parent && parent->Extend3DContext()
|
||||
? parent->GetEffectiveTransform()
|
||||
: Matrix4x4();
|
||||
Matrix transform;
|
||||
if (!transform3d.CanDraw2D(&transform)) {
|
||||
gfxDevCrash(LogReason::CannotDraw3D)
|
||||
<< "GFX: We should not have a 3D transform that CanDraw2D() is false!";
|
||||
}
|
||||
Matrix oldTransform = aTarget->CurrentMatrix();
|
||||
transform *= oldTransform;
|
||||
aTarget->SetMatrix(transform);
|
||||
|
||||
aTarget->SnappedClip(gfxRect(clipRect->X(), clipRect->Y(), clipRect->Width(),
|
||||
clipRect->Height()));
|
||||
|
||||
aTarget->SetMatrix(oldTransform);
|
||||
}
|
||||
|
||||
void BasicLayerManager::PaintLayer(gfxContext* aTarget, Layer* aLayer,
|
||||
DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData) {
|
||||
MOZ_ASSERT(aTarget);
|
||||
|
||||
AUTO_PROFILER_LABEL("BasicLayerManager::PaintLayer", GRAPHICS);
|
||||
|
||||
PaintLayerContext paintLayerContext(aTarget, aLayer, aCallback,
|
||||
aCallbackData);
|
||||
|
||||
// Don't attempt to paint layers with a singular transform, cairo will
|
||||
// just throw an error.
|
||||
if (aLayer->GetEffectiveTransform().IsSingular()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderTraceScope trace("BasicLayerManager::PaintLayer", "707070");
|
||||
|
||||
const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
|
||||
BasicContainerLayer* container =
|
||||
static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
|
||||
bool needsGroup = container && container->UseIntermediateSurface();
|
||||
BasicImplData* data = ToData(aLayer);
|
||||
bool needsClipToVisibleRegion =
|
||||
data->GetClipToVisibleRegion() && !aLayer->AsPaintedLayer();
|
||||
NS_ASSERTION(needsGroup || !container ||
|
||||
container->GetOperator() == CompositionOp::OP_OVER,
|
||||
"non-OVER operator should have forced UseIntermediateSurface");
|
||||
NS_ASSERTION(
|
||||
!container || !aLayer->GetMaskLayer() ||
|
||||
container->UseIntermediateSurface(),
|
||||
"ContainerLayer with mask layer should force UseIntermediateSurface");
|
||||
|
||||
gfxContextAutoSaveRestore contextSR;
|
||||
gfxMatrix transform;
|
||||
// Will return an identity matrix for 3d transforms, and is handled separately
|
||||
// below.
|
||||
bool is2D = paintLayerContext.Setup2DTransform();
|
||||
MOZ_ASSERT(is2D || needsGroup || !container || container->Extend3DContext() ||
|
||||
container->Is3DContextLeaf(),
|
||||
"Must PushGroup for 3d transforms!");
|
||||
|
||||
Layer* parent = aLayer->GetParent();
|
||||
bool inPreserves3DChain = parent && parent->Extend3DContext();
|
||||
bool needsSaveRestore = needsGroup || clipRect || needsClipToVisibleRegion ||
|
||||
!is2D || inPreserves3DChain;
|
||||
if (needsSaveRestore) {
|
||||
contextSR.SetContext(aTarget);
|
||||
|
||||
// The clips on ancestors on the preserved3d chain should be
|
||||
// installed on the aTarget before painting the layer.
|
||||
InstallLayerClipPreserves3D(aTarget, aLayer);
|
||||
for (Layer* l = parent; l && l->Extend3DContext(); l = l->GetParent()) {
|
||||
InstallLayerClipPreserves3D(aTarget, l);
|
||||
}
|
||||
}
|
||||
|
||||
paintLayerContext.Apply2DTransform();
|
||||
|
||||
nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
// If needsGroup is true, we'll clip to the visible region after we've popped
|
||||
// the group
|
||||
if (needsClipToVisibleRegion && !needsGroup) {
|
||||
gfxUtils::ClipToRegion(aTarget, visibleRegion);
|
||||
// Don't need to clip to visible region again
|
||||
needsClipToVisibleRegion = false;
|
||||
}
|
||||
|
||||
if (is2D) {
|
||||
paintLayerContext.AnnotateOpaqueRect();
|
||||
}
|
||||
|
||||
bool clipIsEmpty = aTarget->GetClipExtents().IsEmpty();
|
||||
if (clipIsEmpty) {
|
||||
PaintSelfOrChildren(paintLayerContext, aTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is2D) {
|
||||
if (needsGroup) {
|
||||
PushedGroup pushedGroup;
|
||||
if (PushGroupForLayer(aTarget, aLayer,
|
||||
aLayer->GetLocalVisibleRegion().ToUnknownRegion(),
|
||||
pushedGroup)) {
|
||||
PaintSelfOrChildren(paintLayerContext, pushedGroup.mGroupTarget);
|
||||
PopGroupForLayer(pushedGroup);
|
||||
}
|
||||
} else {
|
||||
PaintSelfOrChildren(paintLayerContext, aTarget);
|
||||
}
|
||||
} else {
|
||||
if (!needsGroup && container) {
|
||||
PaintSelfOrChildren(paintLayerContext, aTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
IntRect bounds = visibleRegion.GetBounds();
|
||||
// DrawTarget without the 3D transform applied:
|
||||
RefPtr<DrawTarget> untransformedDT =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
|
||||
IntSize(bounds.Width(), bounds.Height()), SurfaceFormat::B8G8R8A8);
|
||||
if (!untransformedDT || !untransformedDT->IsValid()) {
|
||||
return;
|
||||
}
|
||||
untransformedDT->SetTransform(
|
||||
Matrix::Translation(-Point(bounds.X(), bounds.Y())));
|
||||
|
||||
RefPtr<gfxContext> groupTarget =
|
||||
gfxContext::CreatePreservingTransformOrNull(untransformedDT);
|
||||
MOZ_ASSERT(groupTarget); // already checked the target above
|
||||
|
||||
PaintSelfOrChildren(paintLayerContext, groupTarget);
|
||||
|
||||
// Temporary fast fix for bug 725886
|
||||
// Revert these changes when 725886 is ready
|
||||
#ifdef DEBUG
|
||||
if (aLayer->GetDebugColorIndex() != 0) {
|
||||
DeviceColor color((aLayer->GetDebugColorIndex() & 1) ? 1.f : 0.f,
|
||||
(aLayer->GetDebugColorIndex() & 2) ? 1.f : 0.f,
|
||||
(aLayer->GetDebugColorIndex() & 4) ? 1.f : 0.f);
|
||||
untransformedDT->FillRect(Rect(bounds), ColorPattern(color));
|
||||
}
|
||||
#endif
|
||||
Matrix4x4 effectiveTransform = aLayer->GetEffectiveTransform();
|
||||
Rect xformBounds = effectiveTransform.TransformAndClipBounds(
|
||||
Rect(bounds), ToRect(aTarget->GetClipExtents()));
|
||||
xformBounds.RoundOut();
|
||||
effectiveTransform.PostTranslate(-xformBounds.X(), -xformBounds.Y(), 0);
|
||||
effectiveTransform.PreTranslate(bounds.X(), bounds.Y(), 0);
|
||||
|
||||
RefPtr<SourceSurface> untransformedSurf = untransformedDT->Snapshot();
|
||||
RefPtr<DrawTarget> xformDT = untransformedDT->CreateSimilarDrawTarget(
|
||||
IntSize::Truncate(xformBounds.Width(), xformBounds.Height()),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
RefPtr<SourceSurface> xformSurf;
|
||||
if (xformDT && untransformedSurf &&
|
||||
xformDT->Draw3DTransformedSurface(untransformedSurf,
|
||||
effectiveTransform)) {
|
||||
xformSurf = xformDT->Snapshot();
|
||||
}
|
||||
|
||||
if (xformSurf) {
|
||||
aTarget->SetPattern(new gfxPattern(
|
||||
xformSurf, Matrix::Translation(xformBounds.TopLeft())));
|
||||
|
||||
// Azure doesn't support EXTEND_NONE, so to avoid extending the edges
|
||||
// of the source surface out to the current clip region, clip to
|
||||
// the rectangle of the result surface now.
|
||||
aTarget->SnappedClip(ThebesRect(xformBounds));
|
||||
FlushGroup(paintLayerContext, needsClipToVisibleRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BasicLayerManager::ClearCachedResources(Layer* aSubtree) {
|
||||
MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
|
||||
if (aSubtree) {
|
||||
ClearLayer(aSubtree);
|
||||
} else if (mRoot) {
|
||||
ClearLayer(mRoot);
|
||||
}
|
||||
}
|
||||
void BasicLayerManager::ClearLayer(Layer* aLayer) {
|
||||
ToData(aLayer)->ClearCachedResources();
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
ClearLayer(child);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ReadbackLayer> BasicLayerManager::CreateReadbackLayer() {
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
RefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,243 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_BASICLAYERS_H
|
||||
#define GFX_BASICLAYERS_H
|
||||
|
||||
#include <stdint.h> // for INT32_MAX, int32_t
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxContext.h" // for gfxContext
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/WidgetUtils.h" // for ScreenRotation
|
||||
#include "mozilla/layers/LayerManager.h" // for LayerManager::DrawPaintedLayerCallback, LayerManager::END_DEFAULT, LayerManager::EndTra...
|
||||
#include "mozilla/layers/LayersTypes.h" // for BufferMode, LayersBackend, etc
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "nscore.h" // for nsAString, etc
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CanvasLayer;
|
||||
class ColorLayer;
|
||||
class ContainerLayer;
|
||||
class ImageFactory;
|
||||
class ImageLayer;
|
||||
class Layer;
|
||||
class PaintLayerContext;
|
||||
class PaintedLayer;
|
||||
class ReadbackLayer;
|
||||
|
||||
/**
|
||||
* This is a cairo/Thebes-only, main-thread-only implementation of layers.
|
||||
*
|
||||
* In each transaction, the client sets up the layer tree and then during
|
||||
* the drawing phase, each PaintedLayer is painted directly into the target
|
||||
* context (with appropriate clipping and Push/PopGroups performed
|
||||
* between layers).
|
||||
*/
|
||||
class BasicLayerManager final : public LayerManager {
|
||||
public:
|
||||
enum BasicLayerManagerType { BLM_WIDGET, BLM_OFFSCREEN, BLM_INACTIVE };
|
||||
/**
|
||||
* Construct a BasicLayerManager which will have no default
|
||||
* target context. SetDefaultTarget or BeginTransactionWithTarget
|
||||
* must be called for any rendering to happen. PaintedLayers will not
|
||||
* be retained.
|
||||
*/
|
||||
explicit BasicLayerManager(BasicLayerManagerType aType);
|
||||
/**
|
||||
* Construct a BasicLayerManager which will have no default
|
||||
* target context. SetDefaultTarget or BeginTransactionWithTarget
|
||||
* must be called for any rendering to happen. PaintedLayers will be
|
||||
* retained; that is, we will try to retain the visible contents of
|
||||
* PaintedLayers as cairo surfaces. We create PaintedLayer buffers by
|
||||
* creating similar surfaces to the default target context, or to
|
||||
* aWidget's GetThebesSurface if there is no default target context, or
|
||||
* to the passed-in context if there is no widget and no default
|
||||
* target context.
|
||||
*
|
||||
* This does not keep a strong reference to the widget, so the caller
|
||||
* must ensure that the widget outlives the layer manager or call
|
||||
* ClearWidget before the widget dies.
|
||||
*/
|
||||
explicit BasicLayerManager(nsIWidget* aWidget);
|
||||
|
||||
protected:
|
||||
virtual ~BasicLayerManager();
|
||||
|
||||
public:
|
||||
BasicLayerManager* AsBasicLayerManager() override { return this; }
|
||||
|
||||
/**
|
||||
* Set the default target context that will be used when BeginTransaction
|
||||
* is called. This can only be called outside a transaction.
|
||||
*
|
||||
* aDoubleBuffering can request double-buffering for drawing to the
|
||||
* default target. When BUFFERED, the layer manager avoids blitting
|
||||
* temporary results to aContext and then overpainting them with final
|
||||
* results, by using a temporary buffer when necessary. In BUFFERED
|
||||
* mode we always completely overwrite the contents of aContext's
|
||||
* destination surface (within the clip region) using OP_SOURCE.
|
||||
*/
|
||||
void SetDefaultTarget(gfxContext* aContext);
|
||||
virtual void SetDefaultTargetConfiguration(BufferMode aDoubleBuffering,
|
||||
ScreenRotation aRotation);
|
||||
gfxContext* GetDefaultTarget() { return mDefaultTarget; }
|
||||
|
||||
nsIWidget* GetRetainerWidget() { return mWidget; }
|
||||
void ClearRetainerWidget() { mWidget = nullptr; }
|
||||
|
||||
virtual bool IsWidgetLayerManager() override { return mWidget != nullptr; }
|
||||
virtual bool IsInactiveLayerManager() override {
|
||||
return mType == BLM_INACTIVE;
|
||||
}
|
||||
|
||||
virtual bool BeginTransaction(const nsCString& aURL = nsCString()) override;
|
||||
virtual bool BeginTransactionWithTarget(
|
||||
gfxContext* aTarget, const nsCString& aURL = nsCString()) override;
|
||||
virtual bool EndEmptyTransaction(
|
||||
EndTransactionFlags aFlags = END_DEFAULT) override;
|
||||
virtual void EndTransaction(
|
||||
DrawPaintedLayerCallback aCallback, void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT) override;
|
||||
void AbortTransaction();
|
||||
|
||||
virtual void SetRoot(Layer* aLayer) override;
|
||||
|
||||
virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() override;
|
||||
virtual already_AddRefed<ContainerLayer> CreateContainerLayer() override;
|
||||
virtual already_AddRefed<ImageLayer> CreateImageLayer() override;
|
||||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override;
|
||||
virtual already_AddRefed<ColorLayer> CreateColorLayer() override;
|
||||
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() override;
|
||||
virtual ImageFactory* GetImageFactory();
|
||||
|
||||
virtual LayersBackend GetBackendType() override {
|
||||
return LayersBackend::LAYERS_BASIC;
|
||||
}
|
||||
virtual void GetBackendName(nsAString& name) override {
|
||||
name.AssignLiteral("Basic");
|
||||
}
|
||||
|
||||
bool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }
|
||||
#ifdef DEBUG
|
||||
bool InDrawing() { return mPhase == PHASE_DRAWING; }
|
||||
bool InForward() { return mPhase == PHASE_FORWARD; }
|
||||
#endif
|
||||
bool InTransaction() { return mPhase != PHASE_NONE; }
|
||||
|
||||
gfxContext* GetTarget() { return mTarget; }
|
||||
void SetTarget(gfxContext* aTarget) {
|
||||
mUsingDefaultTarget = false;
|
||||
mTarget = aTarget;
|
||||
}
|
||||
bool IsRetained() { return mWidget != nullptr; }
|
||||
|
||||
virtual const char* Name() const override { return "Basic"; }
|
||||
|
||||
// Clear the cached contents of this layer tree.
|
||||
virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
|
||||
|
||||
void SetTransactionIncomplete() { mTransactionIncomplete = true; }
|
||||
bool IsTransactionIncomplete() { return mTransactionIncomplete; }
|
||||
|
||||
struct PushedGroup {
|
||||
PushedGroup()
|
||||
: mFinalTarget(nullptr),
|
||||
mNeedsClipToVisibleRegion(false),
|
||||
mOperator(gfx::CompositionOp::OP_COUNT),
|
||||
mOpacity(0.0f) {}
|
||||
gfxContext* mFinalTarget;
|
||||
RefPtr<gfxContext> mGroupTarget;
|
||||
nsIntRegion mVisibleRegion;
|
||||
bool mNeedsClipToVisibleRegion;
|
||||
gfx::IntPoint mGroupOffset;
|
||||
gfx::CompositionOp mOperator;
|
||||
gfx::Float mOpacity;
|
||||
RefPtr<gfx::SourceSurface> mMaskSurface;
|
||||
gfx::Matrix mMaskTransform;
|
||||
};
|
||||
|
||||
// Construct a PushedGroup for a specific layer.
|
||||
// Return false if it has some errors in PushGroupForLayer(). Then, the
|
||||
// "aGroupResult" is unavailable for future using.
|
||||
bool PushGroupForLayer(gfxContext* aContext, Layer* aLayerContext,
|
||||
const nsIntRegion& aRegion, PushedGroup& aGroupResult);
|
||||
|
||||
void PopGroupForLayer(PushedGroup& aGroup);
|
||||
|
||||
virtual bool IsCompositingCheap() override { return false; }
|
||||
virtual int32_t GetMaxTextureSize() const override { return INT32_MAX; }
|
||||
bool CompositorMightResample() { return mCompositorMightResample; }
|
||||
|
||||
TimeStamp GetCompositionTime() const { return mCompositionTime; }
|
||||
|
||||
protected:
|
||||
enum TransactionPhase {
|
||||
PHASE_NONE,
|
||||
PHASE_CONSTRUCTION,
|
||||
PHASE_DRAWING,
|
||||
PHASE_FORWARD
|
||||
};
|
||||
TransactionPhase mPhase;
|
||||
|
||||
// This is the main body of the PaintLayer routine which will if it has
|
||||
// children, recurse into PaintLayer() otherwise it will paint using the
|
||||
// underlying Paint() method of the Layer. It will not do both.
|
||||
void PaintSelfOrChildren(PaintLayerContext& aPaintContext,
|
||||
gfxContext* aGroupTarget);
|
||||
|
||||
// Paint the group onto the underlying target. This is used by PaintLayer to
|
||||
// flush the group to the underlying target.
|
||||
void FlushGroup(PaintLayerContext& aPaintContext,
|
||||
bool aNeedsClipToVisibleRegion);
|
||||
|
||||
// Paints aLayer to mTarget.
|
||||
void PaintLayer(gfxContext* aTarget, Layer* aLayer,
|
||||
DrawPaintedLayerCallback aCallback, void* aCallbackData);
|
||||
|
||||
// Clear the contents of a layer
|
||||
void ClearLayer(Layer* aLayer);
|
||||
|
||||
bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT);
|
||||
|
||||
void FlashWidgetUpdateArea(gfxContext* aContext);
|
||||
|
||||
void SetCompositionTime(TimeStamp aTimeStamp) {
|
||||
mCompositionTime = aTimeStamp;
|
||||
}
|
||||
|
||||
// Widget whose surface should be used as the basis for PaintedLayer
|
||||
// buffers.
|
||||
nsIWidget* mWidget;
|
||||
// The default context for BeginTransaction.
|
||||
RefPtr<gfxContext> mDefaultTarget;
|
||||
// The context to draw into.
|
||||
RefPtr<gfxContext> mTarget;
|
||||
// Image factory we use.
|
||||
RefPtr<ImageFactory> mFactory;
|
||||
|
||||
BufferMode mDoubleBuffering;
|
||||
BasicLayerManagerType mType;
|
||||
bool mUsingDefaultTarget;
|
||||
bool mTransactionIncomplete;
|
||||
bool mCompositorMightResample;
|
||||
|
||||
TimeStamp mCompositionTime;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_BASICLAYERS_H */
|
|
@ -8,7 +8,6 @@
|
|||
#define GFX_BASICLAYERSIMPL_H
|
||||
|
||||
#include "BasicImplData.h" // for BasicImplData
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "ReadbackLayer.h" // for ReadbackLayer
|
||||
#include "gfxContext.h" // for gfxContext, etc
|
||||
#include "mozilla/Attributes.h" // for MOZ_STACK_CLASS
|
||||
|
@ -47,29 +46,6 @@ class AutoSetOperator {
|
|||
RefPtr<gfxContext> mContext;
|
||||
};
|
||||
|
||||
class BasicReadbackLayer : public ReadbackLayer, public BasicImplData {
|
||||
public:
|
||||
explicit BasicReadbackLayer(BasicLayerManager* aLayerManager)
|
||||
: ReadbackLayer(aLayerManager, static_cast<BasicImplData*>(this)) {
|
||||
MOZ_COUNT_CTOR(BasicReadbackLayer);
|
||||
}
|
||||
|
||||
protected:
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(BasicReadbackLayer)
|
||||
|
||||
public:
|
||||
void SetVisibleRegion(const LayerIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
ReadbackLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager() {
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Extract a mask surface for a mask layer
|
||||
* Returns true and through outparams a surface for the mask layer if
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BasicPaintedLayer.h"
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include "ReadbackLayer.h" // for ReadbackLayer, ReadbackSink
|
||||
#include "ReadbackProcessor.h" // for ReadbackProcessor::Update, etc
|
||||
#include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc
|
||||
#include "BasicLayersImpl.h" // for AutoMaskData, etc
|
||||
#include "gfxContext.h" // for gfxContext, etc
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "mozilla/gfx/2D.h" // for DrawTarget
|
||||
#include "mozilla/gfx/BaseRect.h" // for BaseRect
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix
|
||||
#include "mozilla/gfx/Rect.h" // for Rect, IntRect
|
||||
#include "mozilla/gfx/Types.h" // for Float, etc
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/ProfilerLabels.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsISupportsImpl.h" // for gfxContext::Release, etc
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl
|
||||
#include "AutoMaskData.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
static nsIntRegion IntersectWithClip(const nsIntRegion& aRegion,
|
||||
gfxContext* aContext) {
|
||||
gfxRect clip = aContext->GetClipExtents();
|
||||
nsIntRegion result;
|
||||
result.And(aRegion, IntRect::RoundOut(clip.X(), clip.Y(), clip.Width(),
|
||||
clip.Height()));
|
||||
return result;
|
||||
}
|
||||
|
||||
void BasicPaintedLayer::PaintThebes(
|
||||
gfxContext* aContext, Layer* aMaskLayer,
|
||||
LayerManager::DrawPaintedLayerCallback aCallback, void* aCallbackData) {
|
||||
AUTO_PROFILER_LABEL("BasicPaintedLayer::PaintThebes", GRAPHICS);
|
||||
|
||||
NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase");
|
||||
|
||||
float opacity = GetEffectiveOpacity();
|
||||
CompositionOp effectiveOperator = GetEffectiveOperator(this);
|
||||
|
||||
if (!BasicManager()->IsRetained()) {
|
||||
ClearValidRegion();
|
||||
mContentClient->Clear();
|
||||
|
||||
nsIntRegion toDraw =
|
||||
IntersectWithClip(GetLocalVisibleRegion().ToUnknownRegion(), aContext);
|
||||
|
||||
RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
|
||||
|
||||
if (!toDraw.IsEmpty() && !IsHidden()) {
|
||||
if (!aCallback) {
|
||||
BasicManager()->SetTransactionIncomplete();
|
||||
return;
|
||||
}
|
||||
|
||||
aContext->Save();
|
||||
|
||||
bool needsGroup = opacity != 1.0 ||
|
||||
effectiveOperator != CompositionOp::OP_OVER ||
|
||||
aMaskLayer;
|
||||
RefPtr<gfxContext> context = nullptr;
|
||||
BasicLayerManager::PushedGroup group;
|
||||
bool availableGroup = false;
|
||||
|
||||
if (needsGroup) {
|
||||
availableGroup =
|
||||
BasicManager()->PushGroupForLayer(aContext, this, toDraw, group);
|
||||
if (availableGroup) {
|
||||
context = group.mGroupTarget;
|
||||
}
|
||||
} else {
|
||||
context = aContext;
|
||||
}
|
||||
if (context) {
|
||||
DrawTarget* target = context->GetDrawTarget();
|
||||
bool oldAA = target->GetPermitSubpixelAA();
|
||||
SetAntialiasingFlags(this, target);
|
||||
aCallback(this, context, toDraw, toDraw, DrawRegionClip::NONE,
|
||||
nsIntRegion(), aCallbackData);
|
||||
target->SetPermitSubpixelAA(oldAA);
|
||||
}
|
||||
if (needsGroup && availableGroup) {
|
||||
BasicManager()->PopGroupForLayer(group);
|
||||
}
|
||||
|
||||
aContext->Restore();
|
||||
}
|
||||
|
||||
RenderTraceInvalidateEnd(this, "FFFF00");
|
||||
return;
|
||||
}
|
||||
|
||||
if (BasicManager()->IsTransactionIncomplete()) return;
|
||||
|
||||
gfxRect clipExtents;
|
||||
clipExtents = aContext->GetClipExtents();
|
||||
|
||||
// Pull out the mask surface and transform here, because the mask
|
||||
// is internal to basic layers
|
||||
AutoMoz2DMaskData mask;
|
||||
SourceSurface* maskSurface = nullptr;
|
||||
Matrix maskTransform;
|
||||
if (GetMaskData(aMaskLayer, aContext->GetDeviceOffset(), &mask)) {
|
||||
maskSurface = mask.GetSurface();
|
||||
maskTransform = mask.GetTransform();
|
||||
}
|
||||
|
||||
if (!IsHidden() && !clipExtents.IsEmpty()) {
|
||||
mContentClient->DrawTo(this, aContext->GetDrawTarget(), opacity,
|
||||
effectiveOperator, maskSurface, &maskTransform);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicPaintedLayer::Validate(
|
||||
LayerManager::DrawPaintedLayerCallback aCallback, void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) {
|
||||
if (!mContentClient) {
|
||||
// This client will have a null Forwarder, which means it will not have
|
||||
// a ContentHost on the other side.
|
||||
mContentClient = new ContentClientBasic(mBackend);
|
||||
}
|
||||
|
||||
if (!BasicManager()->IsRetained()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetPaintedLayerUpdates(this, &readbackUpdates);
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
if (BasicManager()->CompositorMightResample()) {
|
||||
flags |= ContentClient::PAINT_WILL_RESAMPLE;
|
||||
}
|
||||
if (!(flags & ContentClient::PAINT_WILL_RESAMPLE)) {
|
||||
if (MayResample()) {
|
||||
flags |= ContentClient::PAINT_WILL_RESAMPLE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (mDrawAtomically) {
|
||||
flags |= ContentClient::PAINT_NO_ROTATION;
|
||||
}
|
||||
PaintState state = mContentClient->BeginPaint(this, flags);
|
||||
SubtractFromValidRegion(state.mRegionToInvalidate);
|
||||
|
||||
DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state);
|
||||
if (target && target->IsValid()) {
|
||||
// The area that became invalid and is visible needs to be repainted
|
||||
// (this could be the whole visible area if our buffer switched
|
||||
// from RGB to RGBA, because we might need to repaint with
|
||||
// subpixel AA)
|
||||
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
|
||||
GetLocalVisibleRegion().ToUnknownRegion());
|
||||
SetAntialiasingFlags(this, target);
|
||||
|
||||
RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
|
||||
|
||||
RefPtr<gfxContext> ctx =
|
||||
gfxContext::CreatePreservingTransformOrNull(target);
|
||||
MOZ_ASSERT(ctx); // already checked the target above
|
||||
|
||||
PaintBuffer(ctx, state.mRegionToDraw, state.mRegionToDraw,
|
||||
state.mRegionToInvalidate, state.mClip, aCallback,
|
||||
aCallbackData);
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this,
|
||||
("Layer::Mutated(%p) PaintThebes", this));
|
||||
Mutated();
|
||||
ctx = nullptr;
|
||||
mContentClient->ReturnDrawTarget(target);
|
||||
target = nullptr;
|
||||
|
||||
RenderTraceInvalidateEnd(this, "FFFF00");
|
||||
} else {
|
||||
if (target) {
|
||||
mContentClient->ReturnDrawTarget(target);
|
||||
target = nullptr;
|
||||
}
|
||||
|
||||
// It's possible that state.mRegionToInvalidate is nonempty here,
|
||||
// if we are shrinking the valid region to nothing. So use mRegionToDraw
|
||||
// instead.
|
||||
NS_WARNING_ASSERTION(
|
||||
state.mRegionToDraw.IsEmpty(),
|
||||
"No context when we have something to draw, resource exhaustion?");
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
|
||||
ReadbackProcessor::Update& update = readbackUpdates[i];
|
||||
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
|
||||
RefPtr<DrawTarget> dt = update.mLayer->GetSink()->BeginUpdate(
|
||||
update.mUpdateRect + offset, update.mSequenceCounter);
|
||||
if (dt) {
|
||||
NS_ASSERTION(GetEffectiveOpacity() == 1.0,
|
||||
"Should only read back opaque layers");
|
||||
NS_ASSERTION(!GetMaskLayer(),
|
||||
"Should only read back layers without masks");
|
||||
dt->SetTransform(dt->GetTransform().PreTranslate(offset.x, offset.y));
|
||||
mContentClient->DrawTo(this, dt, 1.0, CompositionOp::OP_OVER, nullptr,
|
||||
nullptr);
|
||||
update.mLayer->GetSink()->EndUpdate(update.mUpdateRect + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<PaintedLayer> BasicLayerManager::CreatePaintedLayer() {
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
|
||||
BackendType backend = gfxPlatform::GetPlatform()->GetDefaultContentBackend();
|
||||
|
||||
if (mDefaultTarget) {
|
||||
backend = mDefaultTarget->GetDrawTarget()->GetBackendType();
|
||||
} else if (mType == BLM_WIDGET) {
|
||||
backend = gfxPlatform::GetPlatform()->GetContentBackendFor(
|
||||
LayersBackend::LAYERS_BASIC);
|
||||
}
|
||||
|
||||
RefPtr<PaintedLayer> layer = new BasicPaintedLayer(this, backend);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,121 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_BASICPAINTEDLAYER_H
|
||||
#define GFX_BASICPAINTEDLAYER_H
|
||||
|
||||
#include "Layers.h" // for PaintedLayer, LayerManager, etc
|
||||
#include "RotatedBuffer.h" // for RotatedBuffer, etc
|
||||
#include "BasicImplData.h" // for BasicImplData
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "gfxPoint.h" // for gfxPoint
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/gfx/BasePoint.h" // for BasePoint
|
||||
#include "mozilla/layers/ContentClient.h" // for ContentClientBasic
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
class gfxContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ReadbackProcessor;
|
||||
|
||||
class BasicPaintedLayer : public PaintedLayer, public BasicImplData {
|
||||
public:
|
||||
typedef ContentClient::PaintState PaintState;
|
||||
typedef ContentClient::ContentType ContentType;
|
||||
|
||||
BasicPaintedLayer(BasicLayerManager* aLayerManager, gfx::BackendType aBackend)
|
||||
: PaintedLayer(aLayerManager, static_cast<BasicImplData*>(this)),
|
||||
mContentClient(nullptr),
|
||||
mBackend(aBackend) {
|
||||
MOZ_COUNT_CTOR(BasicPaintedLayer);
|
||||
}
|
||||
|
||||
protected:
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(BasicPaintedLayer)
|
||||
|
||||
public:
|
||||
void SetVisibleRegion(const LayerIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
PaintedLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
void InvalidateRegion(const nsIntRegion& aRegion) override {
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
mInvalidRegion.Add(aRegion);
|
||||
UpdateValidRegionAfterInvalidRegionChanged();
|
||||
}
|
||||
|
||||
void PaintThebes(gfxContext* aContext, Layer* aMaskLayer,
|
||||
LayerManager::DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData) override;
|
||||
|
||||
void Validate(LayerManager::DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData, ReadbackProcessor* aReadback) override;
|
||||
|
||||
void ClearCachedResources() override {
|
||||
if (mContentClient) {
|
||||
mContentClient->Clear();
|
||||
}
|
||||
ClearValidRegion();
|
||||
}
|
||||
|
||||
void ComputeEffectiveTransforms(
|
||||
const gfx::Matrix4x4& aTransformToSurface) override {
|
||||
if (!BasicManager()->IsRetained()) {
|
||||
// Don't do any snapping of our transform, since we're just going to
|
||||
// draw straight through without intermediate buffers.
|
||||
mEffectiveTransform = GetLocalTransform() * aTransformToSurface;
|
||||
if (gfxPoint(0, 0) != mResidualTranslation) {
|
||||
mResidualTranslation = gfxPoint(0, 0);
|
||||
ClearValidRegion();
|
||||
}
|
||||
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
|
||||
return;
|
||||
}
|
||||
PaintedLayer::ComputeEffectiveTransforms(aTransformToSurface);
|
||||
}
|
||||
|
||||
BasicLayerManager* BasicManager() {
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void PaintBuffer(gfxContext* aContext,
|
||||
const nsIntRegion& aRegionToDraw,
|
||||
const nsIntRegion& aExtendedRegionToDraw,
|
||||
const nsIntRegion& aRegionToInvalidate,
|
||||
DrawRegionClip aClip,
|
||||
LayerManager::DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData) {
|
||||
if (!aCallback) {
|
||||
BasicManager()->SetTransactionIncomplete();
|
||||
return;
|
||||
}
|
||||
aCallback(this, aContext, aExtendedRegionToDraw, aExtendedRegionToDraw,
|
||||
aClip, aRegionToInvalidate, aCallbackData);
|
||||
// Everything that's visible has been validated. Do this instead of just
|
||||
// OR-ing with aRegionToDraw, since that can lead to a very complex region
|
||||
// here (OR doesn't automatically simplify to the simplest possible
|
||||
// representation of a region.)
|
||||
nsIntRegion tmp;
|
||||
tmp.Or(mVisibleRegion.ToUnknownRegion(), aExtendedRegionToDraw);
|
||||
AddToValidRegion(tmp);
|
||||
}
|
||||
|
||||
RefPtr<ContentClientBasic> mContentClient;
|
||||
gfx::BackendType mBackend;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/layers/ContentClient.h"
|
||||
#include "BasicLayers.h" // for BasicLayerManager
|
||||
#include "gfxContext.h" // for gfxContext, etc
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxEnv.h" // for gfxEnv
|
||||
|
@ -447,59 +446,6 @@ void ContentClient::PrintInfo(std::stringstream& aStream, const char* aPrefix) {
|
|||
aStream << nsPrintfCString("ContentClient (0x%p)", this).get();
|
||||
}
|
||||
|
||||
// We pass a null pointer for the ContentClient Forwarder argument, which means
|
||||
// this client will not have a ContentHost on the other side.
|
||||
ContentClientBasic::ContentClientBasic(gfx::BackendType aBackend)
|
||||
: ContentClient(nullptr, ContainsVisibleBounds), mBackend(aBackend) {}
|
||||
|
||||
void ContentClientBasic::DrawTo(PaintedLayer* aLayer, gfx::DrawTarget* aTarget,
|
||||
float aOpacity, gfx::CompositionOp aOp,
|
||||
gfx::SourceSurface* aMask,
|
||||
const gfx::Matrix* aMaskTransform) {
|
||||
if (!mBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
mBuffer->DrawTo(aLayer, aTarget, aOpacity, aOp, aMask, aMaskTransform);
|
||||
}
|
||||
|
||||
RefPtr<RotatedBuffer> ContentClientBasic::CreateBuffer(gfxContentType aType,
|
||||
const IntRect& aRect,
|
||||
uint32_t aFlags) {
|
||||
MOZ_ASSERT(!(aFlags & BUFFER_COMPONENT_ALPHA));
|
||||
if (aFlags & BUFFER_COMPONENT_ALPHA) {
|
||||
gfxDevCrash(LogReason::AlphaWithBasicClient)
|
||||
<< "Asking basic content client for component alpha";
|
||||
}
|
||||
|
||||
IntSize size(aRect.Width(), aRect.Height());
|
||||
RefPtr<gfx::DrawTarget> drawTarget;
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (mBackend == BackendType::CAIRO &&
|
||||
(aType == gfxContentType::COLOR ||
|
||||
aType == gfxContentType::COLOR_ALPHA)) {
|
||||
RefPtr<gfxASurface> surf = new gfxWindowsSurface(
|
||||
size, aType == gfxContentType::COLOR ? gfxImageFormat::X8R8G8B8_UINT32
|
||||
: gfxImageFormat::A8R8G8B8_UINT32);
|
||||
drawTarget = gfxPlatform::CreateDrawTargetForSurface(surf, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!drawTarget) {
|
||||
drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForBackend(
|
||||
mBackend, size,
|
||||
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aType));
|
||||
}
|
||||
|
||||
if (!drawTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new DrawTargetRotatedBuffer(drawTarget, nullptr, aRect,
|
||||
IntPoint(0, 0));
|
||||
}
|
||||
|
||||
class RemoteBufferReadbackProcessor : public TextureReadbackSink {
|
||||
public:
|
||||
RemoteBufferReadbackProcessor(
|
||||
|
|
|
@ -210,28 +210,6 @@ class ContentClient : public CompositableClient {
|
|||
BufferSizePolicy mBufferSizePolicy;
|
||||
};
|
||||
|
||||
// Thin wrapper around DrawTargetRotatedBuffer, for on-mtc
|
||||
class ContentClientBasic final : public ContentClient {
|
||||
public:
|
||||
explicit ContentClientBasic(gfx::BackendType aBackend);
|
||||
|
||||
void DrawTo(PaintedLayer* aLayer, gfx::DrawTarget* aTarget, float aOpacity,
|
||||
gfx::CompositionOp aOp, gfx::SourceSurface* aMask,
|
||||
const gfx::Matrix* aMaskTransform);
|
||||
|
||||
TextureInfo GetTextureInfo() const override {
|
||||
MOZ_CRASH("GFX: Should not be called on non-remote ContentClient");
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType,
|
||||
const gfx::IntRect& aRect,
|
||||
uint32_t aFlags) override;
|
||||
|
||||
private:
|
||||
gfx::BackendType mBackend;
|
||||
};
|
||||
|
||||
/**
|
||||
* A ContentClient backed by a RemoteRotatedBuffer.
|
||||
*
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include <stddef.h> // for size_t
|
||||
#include "base/task.h" // for NewRunnableMethod, etc
|
||||
#include <stddef.h> // for size_t
|
||||
#include "base/task.h" // for NewRunnableMethod, etc
|
||||
#include "mozilla/StaticPrefs_layers.h"
|
||||
#include "mozilla/layers/CompositorManagerChild.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
|
|
|
@ -11,11 +11,6 @@ with Files("apz/**"):
|
|||
BUG_COMPONENT = ("Core", "Panning and Zooming")
|
||||
|
||||
EXPORTS += [
|
||||
"basic/BasicCanvasLayer.h",
|
||||
"basic/BasicImplData.h",
|
||||
"basic/BasicLayers.h",
|
||||
"basic/BasicLayersImpl.h",
|
||||
"basic/BasicPaintedLayer.h",
|
||||
"composite/CompositableHost.h",
|
||||
"composite/ImageHost.h",
|
||||
"CompositorTypes.h",
|
||||
|
@ -386,13 +381,7 @@ UNIFIED_SOURCES += [
|
|||
"apz/util/TouchCounter.cpp",
|
||||
"AxisPhysicsModel.cpp",
|
||||
"AxisPhysicsMSDModel.cpp",
|
||||
"basic/BasicCanvasLayer.cpp",
|
||||
"basic/BasicColorLayer.cpp",
|
||||
"basic/BasicContainerLayer.cpp",
|
||||
"basic/BasicImages.cpp",
|
||||
"basic/BasicLayerManager.cpp",
|
||||
"basic/BasicLayersImpl.cpp",
|
||||
"basic/BasicPaintedLayer.cpp",
|
||||
"basic/TextureHostBasic.cpp",
|
||||
"BSPTree.cpp",
|
||||
"BufferTexture.cpp",
|
||||
|
@ -523,7 +512,6 @@ UNIFIED_SOURCES += [
|
|||
|
||||
SOURCES += [
|
||||
"basic/BasicCompositor.cpp",
|
||||
"basic/BasicImageLayer.cpp",
|
||||
"client/TextureClient.cpp",
|
||||
"ImageContainer.cpp",
|
||||
"PersistentBufferProvider.cpp",
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "WebRenderCommandBuilder.h"
|
||||
|
||||
#include "BasicLayers.h"
|
||||
#include "Layers.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "WebRenderLayerManager.h"
|
||||
|
||||
#include "BasicLayers.h"
|
||||
#include "Layers.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
#include "WebRenderUserData.h"
|
||||
|
||||
#include "BasicLayers.h"
|
||||
#include "mozilla/layers/AnimationHelper.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/ImageClient.h"
|
||||
#include "mozilla/layers/LayerManager.h"
|
||||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||
#include "mozilla/layers/RenderRootStateManager.h"
|
||||
#include "mozilla/layers/WebRenderMessages.h"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "BasicLayers.h"
|
||||
#include "WindowRenderer.h"
|
||||
#include "Common.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "ImageFactory.h"
|
||||
|
@ -52,12 +52,11 @@ TEST_F(ImageContainers, RasterImageContainer) {
|
|||
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
|
||||
tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
|
||||
|
||||
RefPtr<layers::LayerManager> layerManager =
|
||||
new layers::BasicLayerManager(layers::BasicLayerManager::BLM_OFFSCREEN);
|
||||
RefPtr<WindowRenderer> renderer = new FallbackRenderer;
|
||||
|
||||
// Get at native size.
|
||||
RefPtr<layers::ImageContainer> nativeContainer =
|
||||
image->GetImageContainer(layerManager, imgIContainer::FLAG_SYNC_DECODE);
|
||||
image->GetImageContainer(renderer, imgIContainer::FLAG_SYNC_DECODE);
|
||||
ASSERT_TRUE(nativeContainer != nullptr);
|
||||
IntSize containerSize = nativeContainer->GetCurrentSize();
|
||||
EXPECT_EQ(testCase.mSize.width, containerSize.width);
|
||||
|
@ -69,7 +68,7 @@ TEST_F(ImageContainers, RasterImageContainer) {
|
|||
requestedSize.Scale(2, 2);
|
||||
RefPtr<layers::ImageContainer> upscaleContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
layerManager, requestedSize, Nothing(), Nothing(),
|
||||
renderer, requestedSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE |
|
||||
imgIContainer::FLAG_HIGH_QUALITY_SCALING,
|
||||
getter_AddRefs(upscaleContainer));
|
||||
|
@ -85,7 +84,7 @@ TEST_F(ImageContainers, RasterImageContainer) {
|
|||
requestedSize.height /= 2;
|
||||
RefPtr<layers::ImageContainer> downscaleContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
layerManager, requestedSize, Nothing(), Nothing(),
|
||||
renderer, requestedSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE |
|
||||
imgIContainer::FLAG_HIGH_QUALITY_SCALING,
|
||||
getter_AddRefs(downscaleContainer));
|
||||
|
@ -98,7 +97,7 @@ TEST_F(ImageContainers, RasterImageContainer) {
|
|||
// Get at native size again. Should give same container.
|
||||
RefPtr<layers::ImageContainer> againContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
layerManager, testCase.mSize, Nothing(), Nothing(),
|
||||
renderer, testCase.mSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE, getter_AddRefs(againContainer));
|
||||
EXPECT_EQ(drawResult, ImgDrawResult::SUCCESS);
|
||||
ASSERT_EQ(nativeContainer.get(), againContainer.get());
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||
#include "mozilla/layers/WebRenderCanvasRenderer.h"
|
||||
#include "mozilla/layers/RenderRootStateManager.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "mozilla/webgpu/CanvasContext.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
#include "Layers.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "mozilla/layers/WebRenderUserData.h"
|
||||
#include "mozilla/layers/WebRenderScrollData.h"
|
||||
#include "mozilla/layers/RenderRootStateManager.h"
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "mozilla/dom/HTMLVideoElement.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/layers/RenderRootStateManager.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsPresContext.h"
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/dom/Animation.h" // for Animation
|
||||
#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, ScrollableLayerGuid::ViewID
|
||||
#include "nsRefPtrHashtable.h" // for nsRefPtrHashtable
|
||||
#include "mozilla/ScrollPositionUpdate.h" // for ScrollPositionUpdate
|
||||
#include "nsRefPtrHashtable.h" // for nsRefPtrHashtable
|
||||
#include "gfxContext.h"
|
||||
|
||||
class gfxContext;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class LayerManager;
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsImageFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "gfxContext.h"
|
||||
#include "SVGPaintServerFrame.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/CSSClipPathInstance.h"
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "mozilla/TextEventDispatcher.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "PuppetWidget.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIWidgetListener.h"
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "ErrorList.h"
|
||||
#include "HeadlessCompositorWidget.h"
|
||||
#include "Layers.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "BasicEvents.h"
|
||||
#include "MouseEvents.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "BasicLayers.h"
|
||||
#include "GLConsts.h"
|
||||
#include "InputData.h"
|
||||
#include "LiveResizeListener.h"
|
||||
|
@ -433,13 +432,6 @@ void nsBaseWidget::FreeLocalesChangedObserver() {
|
|||
nsBaseWidget::~nsBaseWidget() {
|
||||
IMEStateManager::WidgetDestroyed(this);
|
||||
|
||||
if (mWindowRenderer && mWindowRenderer->AsLayerManager()) {
|
||||
if (BasicLayerManager* mgr =
|
||||
mWindowRenderer->AsLayerManager()->AsBasicLayerManager()) {
|
||||
mgr->ClearRetainerWidget();
|
||||
}
|
||||
}
|
||||
|
||||
FreeLocalesChangedObserver();
|
||||
FreeShutdownObserver();
|
||||
RevokeTransactionIdAllocator();
|
||||
|
@ -885,28 +877,10 @@ nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
|
|||
if (renderer->AsFallback()) {
|
||||
mRenderer = renderer->AsFallback();
|
||||
mRenderer->SetTarget(aTarget, aDoubleBuffering);
|
||||
return;
|
||||
}
|
||||
LayerManager* lm = renderer ? renderer->AsLayerManager() : nullptr;
|
||||
NS_ASSERTION(
|
||||
!lm || lm->GetBackendType() == LayersBackend::LAYERS_BASIC,
|
||||
"AutoLayerManagerSetup instantiated for non-basic layer backend!");
|
||||
if (lm) {
|
||||
mLayerManager = lm->AsBasicLayerManager();
|
||||
if (mLayerManager) {
|
||||
mLayerManager->SetDefaultTarget(aTarget);
|
||||
mLayerManager->SetDefaultTargetConfiguration(aDoubleBuffering,
|
||||
ROTATION_0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup() {
|
||||
if (mLayerManager) {
|
||||
mLayerManager->SetDefaultTarget(nullptr);
|
||||
mLayerManager->SetDefaultTargetConfiguration(
|
||||
mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0);
|
||||
}
|
||||
if (mRenderer) {
|
||||
mRenderer->SetTarget(nullptr, mozilla::layers::BufferMode::BUFFER_NONE);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ class SourceSurface;
|
|||
} // namespace gfx
|
||||
|
||||
namespace layers {
|
||||
class BasicLayerManager;
|
||||
class CompositorBridgeChild;
|
||||
class CompositorBridgeParent;
|
||||
class IAPZCTreeManager;
|
||||
|
@ -143,7 +142,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
|||
typedef base::Thread Thread;
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||
typedef mozilla::layers::BasicLayerManager BasicLayerManager;
|
||||
typedef mozilla::layers::BufferMode BufferMode;
|
||||
typedef mozilla::layers::CompositorBridgeChild CompositorBridgeChild;
|
||||
typedef mozilla::layers::CompositorBridgeParent CompositorBridgeParent;
|
||||
|
@ -404,7 +402,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
|
|||
|
||||
private:
|
||||
nsBaseWidget* mWidget;
|
||||
RefPtr<BasicLayerManager> mLayerManager;
|
||||
mozilla::FallbackRenderer* mRenderer = nullptr;
|
||||
};
|
||||
friend class AutoLayerManagerSetup;
|
||||
|
|
Загрузка…
Ссылка в новой задаче