Bug 867474 - Split BasicShadowableLayerManager into a separate ClientLayerManager. r=nrc

--HG--
rename : gfx/layers/basic/BasicCanvasLayer.cpp => gfx/layers/CopyableCanvasLayer.cpp
rename : gfx/layers/basic/BasicCanvasLayer.h => gfx/layers/CopyableCanvasLayer.h
rename : gfx/layers/basic/BasicCanvasLayer.cpp => gfx/layers/client/ClientCanvasLayer.cpp
rename : gfx/layers/basic/BasicCanvasLayer.h => gfx/layers/client/ClientCanvasLayer.h
rename : gfx/layers/basic/BasicColorLayer.cpp => gfx/layers/client/ClientColorLayer.cpp
rename : gfx/layers/basic/BasicContainerLayer.cpp => gfx/layers/client/ClientContainerLayer.cpp
rename : gfx/layers/basic/BasicContainerLayer.h => gfx/layers/client/ClientContainerLayer.h
rename : gfx/layers/basic/BasicImageLayer.cpp => gfx/layers/client/ClientImageLayer.cpp
rename : gfx/layers/basic/BasicLayerManager.cpp => gfx/layers/client/ClientLayerManager.cpp
rename : gfx/layers/basic/BasicLayers.h => gfx/layers/client/ClientLayerManager.h
rename : gfx/layers/basic/BasicThebesLayer.cpp => gfx/layers/client/ClientThebesLayer.cpp
rename : gfx/layers/basic/BasicThebesLayer.h => gfx/layers/client/ClientThebesLayer.h
rename : gfx/layers/basic/BasicTiledThebesLayer.cpp => gfx/layers/client/ClientTiledThebesLayer.cpp
rename : gfx/layers/basic/BasicTiledThebesLayer.h => gfx/layers/client/ClientTiledThebesLayer.h
This commit is contained in:
Matt Woodrow 2013-05-01 17:03:25 +12:00
parent 7fb5e2a39b
commit c727739057
40 changed files with 2097 additions and 1576 deletions

View File

@ -0,0 +1,220 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "mozilla/layers/PLayerTransactionParent.h"
#include "CopyableCanvasLayer.h"
#include "BasicLayersImpl.h"
#include "gfxImageSurface.h"
#include "GLContext.h"
#include "gfxUtils.h"
#include "gfxPlatform.h"
#include "mozilla/Preferences.h"
#include "SurfaceStream.h"
#include "SharedSurfaceGL.h"
#include "SharedSurfaceEGL.h"
#include "GeckoProfiler.h"
#include "nsXULAppAPI.h"
using namespace mozilla::gfx;
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
void
CopyableCanvasLayer::Initialize(const Data& aData)
{
NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
if (aData.mSurface) {
mSurface = aData.mSurface;
NS_ASSERTION(!aData.mGLContext, "CanvasLayer can't have both surface and GLContext");
mNeedsYFlip = false;
} else if (aData.mGLContext) {
mGLContext = aData.mGLContext;
mIsGLAlphaPremult = aData.mIsGLAlphaPremult;
mNeedsYFlip = true;
MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
// [Basic Layers, non-OMTC] WebGL layer init.
// `GLScreenBuffer::Morph`ing is only needed in BasicShadowableCanvasLayer.
} else if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
mNeedsYFlip = false;
} else {
NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
}
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
}
void
CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
{
if (!IsDirty())
return;
Painted();
if (mDrawTarget) {
mDrawTarget->Flush();
if (mDrawTarget->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) {
// We have an accelerated CG context which has changed, unlike a bitmap surface
// where we can alias the bits on initializing the mDrawTarget, we need to readback
// and copy the accelerated surface each frame. We want to support this for quick
// thumbnail but if we're going to be doing this every frame it likely is better
// to use a non accelerated (bitmap) canvas.
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
}
}
if (!mGLContext && aDestSurface) {
nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
return;
}
if (mGLContext) {
if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) {
MOZ_ASSERT(false, "Destination surface must be ImageSurface type.");
return;
}
nsRefPtr<gfxImageSurface> readSurf;
nsRefPtr<gfxImageSurface> resultSurf;
SharedSurface* sharedSurf = mGLContext->RequestFrame();
if (!sharedSurf) {
NS_WARNING("Null frame received.");
return;
}
gfxIntSize readSize(sharedSurf->Size());
gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE)
? gfxASurface::ImageFormatRGB24
: gfxASurface::ImageFormatARGB32;
if (aDestSurface) {
resultSurf = static_cast<gfxImageSurface*>(aDestSurface);
} else {
resultSurf = GetTempSurface(readSize, format);
}
MOZ_ASSERT(resultSurf);
if (resultSurf->CairoStatus() != 0) {
MOZ_ASSERT(false, "Bad resultSurf->CairoStatus().");
return;
}
MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL);
SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf);
if (surfGL->Type() == SharedSurfaceType::Basic) {
SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL);
readSurf = sharedSurf_Basic->GetData();
} else {
if (resultSurf->Format() == format &&
resultSurf->GetSize() == readSize)
{
readSurf = resultSurf;
} else {
readSurf = GetTempSurface(readSize, format);
}
// Readback handles Flush/MarkDirty.
mGLContext->Screen()->Readback(surfGL, readSurf);
}
MOZ_ASSERT(readSurf);
bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
if (needsPremult) {
gfxImageSurface* sizedReadSurf = nullptr;
if (readSurf->Format() == resultSurf->Format() &&
readSurf->GetSize() == resultSurf->GetSize())
{
sizedReadSurf = readSurf;
} else {
readSurf->Flush();
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(readSurf);
ctx->Paint();
sizedReadSurf = resultSurf;
}
MOZ_ASSERT(sizedReadSurf);
readSurf->Flush();
resultSurf->Flush();
gfxUtils::PremultiplyImageSurface(readSurf, resultSurf);
resultSurf->MarkDirty();
} else if (resultSurf != readSurf) {
// Didn't need premult, but we do need to blit to resultSurf
readSurf->Flush();
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(readSurf);
ctx->Paint();
}
// stick our surface into mSurface, so that the Paint() path is the same
if (!aDestSurface) {
mSurface = resultSurf;
}
}
}
void
CopyableCanvasLayer::PaintWithOpacity(gfxContext* aContext,
float aOpacity,
Layer* aMaskLayer,
gfxContext::GraphicsOperator aOperator)
{
if (!mSurface) {
NS_WARNING("No valid surface to draw!");
return;
}
nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
pat->SetFilter(mFilter);
pat->SetExtend(gfxPattern::EXTEND_PAD);
gfxMatrix m;
if (mNeedsYFlip) {
m = aContext->CurrentMatrix();
aContext->Translate(gfxPoint(0.0, mBounds.height));
aContext->Scale(1.0, -1.0);
}
// If content opaque, then save off current operator and set to source.
// This ensures that alpha is not applied even if the source surface
// has an alpha channel
gfxContext::GraphicsOperator savedOp;
if (GetContentFlags() & CONTENT_OPAQUE) {
savedOp = aContext->CurrentOperator();
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
}
AutoSetOperator setOperator(aContext, aOperator);
aContext->NewPath();
// No need to snap here; our transform is already set up to snap our rect
aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
aContext->SetPattern(pat);
FillWithMask(aContext, aOpacity, aMaskLayer);
// Restore surface operator
if (GetContentFlags() & CONTENT_OPAQUE) {
aContext->SetOperator(savedOp);
}
if (mNeedsYFlip) {
aContext->SetMatrix(m);
}
}
}
}

View File

@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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_COPYABLECANVASLAYER_H
#define GFX_COPYABLECANVASLAYER_H
#include "Layers.h"
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/Preferences.h"
#include "gfxPlatform.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
class CanvasClient2D;
class CanvasClientWebGL;
/**
* A shared CanvasLayer implementation that supports copying
* its contents into a gfxASurface using UpdateSurface.
*/
class CopyableCanvasLayer : public CanvasLayer
{
public:
CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
CanvasLayer(aLayerManager, aImplData)
{
MOZ_COUNT_CTOR(CopyableCanvasLayer);
mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false);
}
virtual ~CopyableCanvasLayer()
{
MOZ_COUNT_DTOR(CopyableCanvasLayer);
}
virtual void Initialize(const Data& aData);
protected:
void PaintWithOpacity(gfxContext* aContext,
float aOpacity,
Layer* aMaskLayer,
gfxContext::GraphicsOperator aOperator = gfxContext::OPERATOR_OVER);
void UpdateSurface(gfxASurface* aDestSurface = nullptr, Layer* aMaskLayer = nullptr);
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<mozilla::gl::GLContext> mGLContext;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
uint32_t mCanvasFramebuffer;
bool mIsGLAlphaPremult;
bool mNeedsYFlip;
bool mForceReadback;
nsRefPtr<gfxImageSurface> mCachedTempSurface;
gfxIntSize mCachedSize;
gfxImageFormat mCachedFormat;
gfxImageSurface* GetTempSurface(const gfxIntSize& aSize, const gfxImageFormat aFormat)
{
if (!mCachedTempSurface ||
aSize.width != mCachedSize.width ||
aSize.height != mCachedSize.height ||
aFormat != mCachedFormat)
{
mCachedTempSurface = new gfxImageSurface(aSize, aFormat);
mCachedSize = aSize;
mCachedFormat = aFormat;
}
MOZ_ASSERT(mCachedTempSurface->Stride() == mCachedTempSurface->Width() * 4);
return mCachedTempSurface;
}
void DiscardTempSurface()
{
mCachedTempSurface = nullptr;
}
};
}
}
#endif

View File

@ -37,6 +37,7 @@ enum LayersBackend {
LAYERS_OPENGL,
LAYERS_D3D9,
LAYERS_D3D10,
LAYERS_CLIENT,
LAYERS_LAST
};

View File

@ -38,9 +38,16 @@ CPPSRCS = \
BasicImageLayer.cpp \
BasicLayersImpl.cpp \
BasicThebesLayer.cpp \
BasicTiledThebesLayer.cpp \
ClientCanvasLayer.cpp \
ClientColorLayer.cpp \
ClientContainerLayer.cpp \
ClientImageLayer.cpp \
ClientLayerManager.cpp \
ClientThebesLayer.cpp \
ClientTiledThebesLayer.cpp \
CompositableHost.cpp \
CompositableTransactionParent.cpp \
CopyableCanvasLayer.cpp \
ImageContainer.cpp \
Layers.cpp \
LayersLogging.cpp \

View File

@ -24,149 +24,6 @@ using namespace mozilla::gl;
namespace mozilla {
namespace layers {
void
BasicCanvasLayer::Initialize(const Data& aData)
{
NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
if (aData.mSurface) {
mSurface = aData.mSurface;
NS_ASSERTION(!aData.mGLContext, "CanvasLayer can't have both surface and GLContext");
mNeedsYFlip = false;
} else if (aData.mGLContext) {
mGLContext = aData.mGLContext;
mIsGLAlphaPremult = aData.mIsGLAlphaPremult;
mNeedsYFlip = true;
MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
// [Basic Layers, non-OMTC] WebGL layer init.
// `GLScreenBuffer::Morph`ing is only needed in BasicShadowableCanvasLayer.
} else if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
mNeedsYFlip = false;
} else {
NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
}
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
}
void
BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
{
if (!IsDirty())
return;
Painted();
if (mDrawTarget) {
mDrawTarget->Flush();
if (mDrawTarget->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) {
// We have an accelerated CG context which has changed, unlike a bitmap surface
// where we can alias the bits on initializing the mDrawTarget, we need to readback
// and copy the accelerated surface each frame. We want to support this for quick
// thumbnail but if we're going to be doing this every frame it likely is better
// to use a non accelerated (bitmap) canvas.
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
}
}
if (!mGLContext && aDestSurface) {
nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
BasicCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
return;
}
if (mGLContext) {
if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) {
MOZ_ASSERT(false, "Destination surface must be ImageSurface type.");
return;
}
nsRefPtr<gfxImageSurface> readSurf;
nsRefPtr<gfxImageSurface> resultSurf;
SharedSurface* sharedSurf = mGLContext->RequestFrame();
if (!sharedSurf) {
NS_WARNING("Null frame received.");
return;
}
gfxIntSize readSize(sharedSurf->Size());
gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE)
? gfxASurface::ImageFormatRGB24
: gfxASurface::ImageFormatARGB32;
if (aDestSurface) {
resultSurf = static_cast<gfxImageSurface*>(aDestSurface);
} else {
resultSurf = GetTempSurface(readSize, format);
}
MOZ_ASSERT(resultSurf);
if (resultSurf->CairoStatus() != 0) {
MOZ_ASSERT(false, "Bad resultSurf->CairoStatus().");
return;
}
MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL);
SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf);
if (surfGL->Type() == SharedSurfaceType::Basic) {
SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL);
readSurf = sharedSurf_Basic->GetData();
} else {
if (resultSurf->Format() == format &&
resultSurf->GetSize() == readSize)
{
readSurf = resultSurf;
} else {
readSurf = GetTempSurface(readSize, format);
}
// Readback handles Flush/MarkDirty.
mGLContext->Screen()->Readback(surfGL, readSurf);
}
MOZ_ASSERT(readSurf);
bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult;
if (needsPremult) {
gfxImageSurface* sizedReadSurf = nullptr;
if (readSurf->Format() == resultSurf->Format() &&
readSurf->GetSize() == resultSurf->GetSize())
{
sizedReadSurf = readSurf;
} else {
readSurf->Flush();
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(readSurf);
ctx->Paint();
sizedReadSurf = resultSurf;
}
MOZ_ASSERT(sizedReadSurf);
readSurf->Flush();
resultSurf->Flush();
gfxUtils::PremultiplyImageSurface(readSurf, resultSurf);
resultSurf->MarkDirty();
} else if (resultSurf != readSurf) {
// Didn't need premult, but we do need to blit to resultSurf
readSurf->Flush();
nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(readSurf);
ctx->Paint();
}
// stick our surface into mSurface, so that the Paint() path is the same
if (!aDestSurface) {
mSurface = resultSurf;
}
}
}
void
BasicCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
@ -177,145 +34,9 @@ BasicCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
UpdateSurface();
FireDidTransactionCallback();
PaintWithOpacity(aContext, GetEffectiveOpacity(), aMaskLayer);
PaintWithOpacity(aContext, GetEffectiveOpacity(), aMaskLayer, GetOperator());
}
void
BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
float aOpacity,
Layer* aMaskLayer)
{
NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase");
if (!mSurface) {
NS_WARNING("No valid surface to draw!");
return;
}
nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
pat->SetFilter(mFilter);
pat->SetExtend(gfxPattern::EXTEND_PAD);
gfxMatrix m;
if (mNeedsYFlip) {
m = aContext->CurrentMatrix();
aContext->Translate(gfxPoint(0.0, mBounds.height));
aContext->Scale(1.0, -1.0);
}
// If content opaque, then save off current operator and set to source.
// This ensures that alpha is not applied even if the source surface
// has an alpha channel
gfxContext::GraphicsOperator savedOp;
if (GetContentFlags() & CONTENT_OPAQUE) {
savedOp = aContext->CurrentOperator();
aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
}
AutoSetOperator setOperator(aContext, GetOperator());
aContext->NewPath();
// No need to snap here; our transform is already set up to snap our rect
aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
aContext->SetPattern(pat);
FillWithMask(aContext, aOpacity, aMaskLayer);
// Restore surface operator
if (GetContentFlags() & CONTENT_OPAQUE) {
aContext->SetOperator(savedOp);
}
if (mNeedsYFlip) {
aContext->SetMatrix(m);
}
}
void
BasicShadowableCanvasLayer::Initialize(const Data& aData)
{
BasicCanvasLayer::Initialize(aData);
if (!HasShadow())
return;
mCanvasClient = nullptr;
if (mGLContext) {
GLScreenBuffer* screen = mGLContext->Screen();
SurfaceStreamType streamType =
SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
screen->PreserveBuffer());
SurfaceFactory_GL* factory = nullptr;
if (!mForceReadback) {
if (BasicManager()->GetCompositorBackendType() == mozilla::layers::LAYERS_OPENGL) {
if (mGLContext->GetEGLContext()) {
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
if (!isCrossProcess) {
// [Basic/OGL Layers, OMTC] WebGL layer init.
factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
} else {
// [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
// Fall back to readback.
}
} else {
// [Basic Layers, OMTC] WebGL layer init.
// Well, this *should* work...
factory = new SurfaceFactory_GLTexture(mGLContext, mGLContext, screen->Caps());
}
}
}
if (factory) {
screen->Morph(factory, streamType);
}
}
}
void
BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
PROFILER_LABEL("BasicShadowableCanvasLayer", "Paint");
if (!HasShadow()) {
BasicCanvasLayer::Paint(aContext, aMaskLayer);
return;
}
if (!IsDirty()) {
return;
}
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
if (!mCanvasClient) {
TextureFlags flags = 0;
if (mNeedsYFlip) {
flags |= NeedsYFlip;
}
mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
BasicManager(), flags);
if (!mCanvasClient) {
return;
}
if (HasShadow()) {
mCanvasClient->Connect();
BasicManager()->Attach(mCanvasClient, this);
}
}
FirePreTransactionCallback();
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
FireDidTransactionCallback();
BasicManager()->Hold(this);
mCanvasClient->Updated();
}
already_AddRefed<CanvasLayer>
BasicLayerManager::CreateCanvasLayer()
{
@ -324,16 +45,5 @@ BasicLayerManager::CreateCanvasLayer()
return layer.forget();
}
already_AddRefed<CanvasLayer>
BasicShadowLayerManager::CreateCanvasLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<BasicShadowableCanvasLayer> layer =
new BasicShadowableCanvasLayer(this);
MAYBE_CREATE_SHADOW(Canvas);
return layer.forget();
}
}
}

View File

@ -12,6 +12,7 @@
#include "BasicImplData.h"
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/Preferences.h"
#include "CopyableCanvasLayer.h"
#include "gfxPlatform.h"
@ -23,137 +24,28 @@ namespace layers {
class CanvasClient2D;
class CanvasClientWebGL;
class BasicCanvasLayer : public CanvasLayer,
class BasicCanvasLayer : public CopyableCanvasLayer,
public BasicImplData
{
public:
BasicCanvasLayer(BasicLayerManager* aLayerManager) :
CanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
{
MOZ_COUNT_CTOR(BasicCanvasLayer);
mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false);
}
virtual ~BasicCanvasLayer()
{
MOZ_COUNT_DTOR(BasicCanvasLayer);
}
CopyableCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
{ }
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(BasicManager()->InConstruction(),
"Can only set properties in construction phase");
CanvasLayer::SetVisibleRegion(aRegion);
}
virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void PaintWithOpacity(gfxContext* aContext,
float aOpacity,
Layer* aMaskLayer);
protected:
BasicLayerManager* BasicManager()
{
return static_cast<BasicLayerManager*>(mManager);
}
void UpdateSurface(gfxASurface* aDestSurface = nullptr, Layer* aMaskLayer = nullptr);
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<mozilla::gl::GLContext> mGLContext;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
uint32_t mCanvasFramebuffer;
bool mIsGLAlphaPremult;
bool mNeedsYFlip;
bool mForceReadback;
nsRefPtr<gfxImageSurface> mCachedTempSurface;
gfxIntSize mCachedSize;
gfxImageFormat mCachedFormat;
gfxImageSurface* GetTempSurface(const gfxIntSize& aSize, const gfxImageFormat aFormat)
{
if (!mCachedTempSurface ||
aSize.width != mCachedSize.width ||
aSize.height != mCachedSize.height ||
aFormat != mCachedFormat)
{
mCachedTempSurface = new gfxImageSurface(aSize, aFormat);
mCachedSize = aSize;
mCachedFormat = aFormat;
}
MOZ_ASSERT(mCachedTempSurface->Stride() == mCachedTempSurface->Width() * 4);
return mCachedTempSurface;
}
void DiscardTempSurface()
{
mCachedTempSurface = nullptr;
}
friend class CanvasClient2D;
friend class CanvasClientWebGL;
};
class BasicShadowableCanvasLayer : public BasicCanvasLayer,
public BasicShadowableLayer
{
public:
BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
BasicCanvasLayer(aManager),
mCanvasClient(nullptr)
{
MOZ_COUNT_CTOR(BasicShadowableCanvasLayer);
}
virtual ~BasicShadowableCanvasLayer()
{
MOZ_COUNT_DTOR(BasicShadowableCanvasLayer);
}
virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = CanvasLayerAttributes(mFilter, mBounds);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
/*virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
{
NS_ERROR("Should not be called.");
}*/
virtual void Disconnect()
{
mCanvasClient = nullptr;
BasicShadowableLayer::Disconnect();
}
virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
{
return mCanvasClient;
}
private:
BasicShadowLayerManager* BasicManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
}
CompositableType GetCompositableClientType()
{
if (mGLContext && XRE_GetProcessType() == GeckoProcessType_Default) {
return BUFFER_IMAGE_BUFFERED;
}
return BUFFER_IMAGE_SINGLE;
}
RefPtr<CanvasClient> mCanvasClient;
};
}

View File

@ -58,52 +58,6 @@ BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity,
PaintWithMask(aContext, aOpacity, aMaskLayer);
}
class BasicShadowableColorLayer : public BasicColorLayer,
public BasicShadowableLayer
{
public:
BasicShadowableColorLayer(BasicShadowLayerManager* aManager) :
BasicColorLayer(aManager)
{
MOZ_COUNT_CTOR(BasicShadowableColorLayer);
}
virtual ~BasicShadowableColorLayer()
{
MOZ_COUNT_DTOR(BasicShadowableColorLayer);
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ColorLayerAttributes(GetColor());
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
BasicShadowableLayer::Disconnect();
}
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
};
void
BasicShadowableColorLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
BasicColorLayer::Paint(aContext, aMaskLayer);
if (!HasShadow()) {
return;
}
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
}
already_AddRefed<ColorLayer>
BasicLayerManager::CreateColorLayer()
{
@ -111,15 +65,6 @@ BasicLayerManager::CreateColorLayer()
nsRefPtr<ColorLayer> layer = new BasicColorLayer(this);
return layer.forget();
}
already_AddRefed<ColorLayer>
BasicShadowLayerManager::CreateColorLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<BasicShadowableColorLayer> layer =
new BasicShadowableColorLayer(this);
MAYBE_CREATE_SHADOW(Color);
return layer.forget();
}
}
}

View File

@ -59,124 +59,6 @@ BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
return covered.Contains(rect);
}
class BasicShadowableContainerLayer : public BasicContainerLayer,
public BasicShadowableLayer {
public:
BasicShadowableContainerLayer(BasicShadowLayerManager* aManager) :
BasicContainerLayer(aManager)
{
MOZ_COUNT_CTOR(BasicShadowableContainerLayer);
}
virtual ~BasicShadowableContainerLayer()
{
MOZ_COUNT_DTOR(BasicShadowableContainerLayer);
}
virtual void InsertAfter(Layer* aChild, Layer* aAfter);
virtual void RemoveChild(Layer* aChild);
virtual void RepositionChild(Layer* aChild, Layer* aAfter);
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
BasicShadowableLayer::Disconnect();
}
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) MOZ_OVERRIDE
{
if (HasShadow()) {
DefaultComputeEffectiveTransforms(aTransformToSurface);
} else {
BasicContainerLayer::ComputeEffectiveTransforms(aTransformToSurface);
}
}
private:
BasicShadowLayerManager* ShadowManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
}
};
void
BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
{
if (HasShadow() && ShouldShadow(aChild)) {
while (aAfter && !ShouldShadow(aAfter)) {
aAfter = aAfter->GetPrevSibling();
}
ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
ShadowManager()->Hold(aChild),
aAfter ? ShadowManager()->Hold(aAfter) : nullptr);
}
BasicContainerLayer::InsertAfter(aChild, aAfter);
}
void
BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
{
if (HasShadow() && ShouldShadow(aChild)) {
ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
ShadowManager()->Hold(aChild));
}
BasicContainerLayer::RemoveChild(aChild);
}
void
BasicShadowableContainerLayer::RepositionChild(Layer* aChild, Layer* aAfter)
{
if (HasShadow() && ShouldShadow(aChild)) {
while (aAfter && !ShouldShadow(aAfter)) {
aAfter = aAfter->GetPrevSibling();
}
ShadowManager()->RepositionChild(ShadowManager()->Hold(this),
ShadowManager()->Hold(aChild),
aAfter ? ShadowManager()->Hold(aAfter) : nullptr);
}
BasicContainerLayer::RepositionChild(aChild, aAfter);
}
class BasicShadowableRefLayer : public RefLayer, public BasicImplData,
public BasicShadowableLayer {
template<class Container>
friend void ContainerComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface,
Container* aContainer);
public:
BasicShadowableRefLayer(BasicShadowLayerManager* aManager) :
RefLayer(aManager, static_cast<BasicImplData*>(this))
{
MOZ_COUNT_CTOR(BasicShadowableRefLayer);
}
virtual ~BasicShadowableRefLayer()
{
MOZ_COUNT_DTOR(BasicShadowableRefLayer);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
BasicShadowableLayer::Disconnect();
}
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
ContainerComputeEffectiveTransforms(aTransformToSurface, this);
}
private:
BasicShadowLayerManager* ShadowManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
}
};
already_AddRefed<ContainerLayer>
BasicLayerManager::CreateContainerLayer()
{
@ -185,26 +67,5 @@ BasicLayerManager::CreateContainerLayer()
return layer.forget();
}
already_AddRefed<ContainerLayer>
BasicShadowLayerManager::CreateContainerLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<BasicShadowableContainerLayer> layer =
new BasicShadowableContainerLayer(this);
MAYBE_CREATE_SHADOW(Container);
return layer.forget();
}
already_AddRefed<RefLayer>
BasicShadowLayerManager::CreateRefLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<BasicShadowableRefLayer> layer =
new BasicShadowableRefLayer(this);
MAYBE_CREATE_SHADOW(Ref);
return layer.forget();
}
}
}

View File

@ -157,130 +157,6 @@ BasicImageLayer::GetAsSurface(gfxASurface** aSurface,
return true;
}
class BasicShadowableImageLayer : public BasicImageLayer,
public BasicShadowableLayer
{
public:
BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
BasicImageLayer(aManager),
mImageClient(nullptr),
mImageClientTypeContainer(BUFFER_UNKNOWN)
{
MOZ_COUNT_CTOR(BasicShadowableImageLayer);
}
virtual ~BasicShadowableImageLayer()
{
DestroyBackBuffer();
MOZ_COUNT_DTOR(BasicShadowableImageLayer);
}
virtual void SetContainer(ImageContainer* aContainer) MOZ_OVERRIDE
{
ImageLayer::SetContainer(aContainer);
mImageClientTypeContainer = BUFFER_UNKNOWN;
}
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void ClearCachedResources() MOZ_OVERRIDE
{
DestroyBackBuffer();
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ImageLayerAttributes(mFilter);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
DestroyBackBuffer();
BasicShadowableLayer::Disconnect();
}
void DestroyBackBuffer()
{
mImageClient = nullptr;
}
virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
{
return mImageClient;
}
private:
BasicShadowLayerManager* BasicManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
}
CompositableType GetImageClientType()
{
if (mImageClientTypeContainer != BUFFER_UNKNOWN) {
return mImageClientTypeContainer;
}
if (mContainer->IsAsync()) {
mImageClientTypeContainer = BUFFER_BRIDGE;
return mImageClientTypeContainer;
}
nsRefPtr<gfxASurface> surface;
AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
mImageClientTypeContainer = autoLock.GetImage() ?
BUFFER_IMAGE_SINGLE : BUFFER_UNKNOWN;
return mImageClientTypeContainer;
}
RefPtr<ImageClient> mImageClient;
CompositableType mImageClientTypeContainer;
};
void
BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (!HasShadow()) {
BasicImageLayer::Paint(aContext, aMaskLayer);
return;
}
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
if (!mContainer) {
return;
}
if (!mImageClient ||
!mImageClient->UpdateImage(mContainer, GetContentFlags())) {
mImageClient = ImageClient::CreateImageClient(GetImageClientType(),
BasicManager(),
mForceSingleTile
? ForceSingleTile
: 0);
if (GetImageClientType() == BUFFER_BRIDGE) {
static_cast<ImageClientBridge*>(mImageClient.get())->SetLayer(this);
}
if (!mImageClient) {
return;
}
if (HasShadow() && !mContainer->IsAsync()) {
mImageClient->Connect();
BasicManager()->Attach(mImageClient, this);
}
if (!mImageClient->UpdateImage(mContainer, GetContentFlags())) {
return;
}
}
BasicManager()->Hold(this);
}
already_AddRefed<ImageLayer>
BasicLayerManager::CreateImageLayer()
{
@ -288,15 +164,6 @@ BasicLayerManager::CreateImageLayer()
nsRefPtr<ImageLayer> layer = new BasicImageLayer(this);
return layer.forget();
}
already_AddRefed<ImageLayer>
BasicShadowLayerManager::CreateImageLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<BasicShadowableImageLayer> layer =
new BasicShadowableImageLayer(this);
MAYBE_CREATE_SHADOW(Image);
return layer.forget();
}
}
}

View File

@ -20,7 +20,6 @@
#define PIXMAN_DONT_DEFINE_STDINT
#include "pixman.h"
#include "BasicTiledThebesLayer.h"
#include "BasicLayersImpl.h"
#include "BasicThebesLayer.h"
#include "BasicContainerLayer.h"
@ -873,16 +872,6 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT
}
}
static bool
HasOpaqueAncestorLayer(Layer* aLayer)
{
for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
return true;
}
return false;
}
void
BasicLayerManager::PaintLayer(gfxContext* aTarget,
Layer* aLayer,
@ -917,28 +906,6 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
container->UseIntermediateSurface(),
"ContainerLayer with mask layer should force UseIntermediateSurface");
// If we're a shadowable ContainerLayer, then setup mSupportsComponentAlphaChildren
// in the same way that ContainerLayerComposite will do. Otherwise leave it set to
// true.
ShadowableLayer* shadow = aLayer->AsShadowableLayer();
if (aLayer->GetFirstChild() && shadow && shadow->HasShadow()) {
if (needsGroup) {
if (container->GetEffectiveVisibleRegion().GetNumRects() != 1 ||
!(container->GetContentFlags() & Layer::CONTENT_OPAQUE))
{
const gfx3DMatrix& transform3D = container->GetEffectiveTransform();
gfxMatrix transform;
if (HasOpaqueAncestorLayer(container) &&
transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
container->SetSupportsComponentAlphaChildren(gfxPlatform::GetPlatform()->UsesSubpixelAATextRendering());
}
}
} else {
container->SetSupportsComponentAlphaChildren((container->GetContentFlags() & Layer::CONTENT_OPAQUE) ||
(container->GetParent() && container->GetParent()->SupportsComponentAlphaChildren()));
}
}
gfxContextAutoSaveRestore contextSR;
gfxMatrix transform;
// Will return an identity matrix for 3d transforms, and is handled separately below.
@ -1066,330 +1033,5 @@ BasicLayerManager::CreateReadbackLayer()
return layer.forget();
}
BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
BasicLayerManager(aWidget), mTargetRotation(ROTATION_0),
mRepeatTransaction(false), mIsRepeatTransaction(false)
{
MOZ_COUNT_CTOR(BasicShadowLayerManager);
}
BasicShadowLayerManager::~BasicShadowLayerManager()
{
MOZ_COUNT_DTOR(BasicShadowLayerManager);
}
int32_t
BasicShadowLayerManager::GetMaxTextureSize() const
{
if (HasShadowManager()) {
return ShadowLayerForwarder::GetMaxTextureSize();
}
return INT32_MAX;
}
void
BasicShadowLayerManager::SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, ScreenRotation aRotation)
{
BasicLayerManager::SetDefaultTargetConfiguration(aDoubleBuffering, aRotation);
mTargetRotation = aRotation;
if (mWidget) {
mTargetBounds = mWidget->GetNaturalBounds();
}
}
void
BasicShadowLayerManager::SetRoot(Layer* aLayer)
{
if (mRoot != aLayer) {
if (HasShadowManager()) {
// Have to hold the old root and its children in order to
// maintain the same view of the layer tree in this process as
// the parent sees. Otherwise layers can be destroyed
// mid-transaction and bad things can happen (v. bug 612573)
if (mRoot) {
Hold(mRoot);
}
ShadowLayerForwarder::SetRoot(Hold(aLayer));
}
BasicLayerManager::SetRoot(aLayer);
}
}
void
BasicShadowLayerManager::Mutated(Layer* aLayer)
{
BasicLayerManager::Mutated(aLayer);
NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
if (HasShadowManager() && ShouldShadow(aLayer)) {
ShadowLayerForwarder::Mutated(Hold(aLayer));
}
}
void
BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
nsRefPtr<gfxContext> targetContext = aTarget;
// If the last transaction was incomplete (a failed DoEmptyTransaction),
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
if (HasShadowManager()) {
ScreenOrientation orientation;
nsIntRect clientBounds;
if (TabChild* window = mWidget->GetOwningTabChild()) {
orientation = window->GetOrientation();
} else {
hal::ScreenConfiguration currentConfig;
hal::GetCurrentScreenConfiguration(&currentConfig);
orientation = currentConfig.orientation();
}
mWidget->GetClientBounds(clientBounds);
ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation, clientBounds, orientation);
// If we're drawing on behalf of a context with async pan/zoom
// enabled, then the entire buffer of thebes layers might be
// composited (including resampling) asynchronously before we get
// a chance to repaint, so we have to ensure that it's all valid
// and not rotated.
if (mWidget) {
if (TabChild* window = mWidget->GetOwningTabChild()) {
mCompositorMightResample = window->IsAsyncPanZoomEnabled();
}
}
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.
if (aTarget && ((aTarget != mDefaultTarget) || Compositor::GetBackend() == LAYERS_BASIC) &&
XRE_GetProcessType() == GeckoProcessType_Default) {
mShadowTarget = aTarget;
gfxASurface::gfxContentType contentType;
if (aTarget->IsCairo()) {
contentType = aTarget->OriginalSurface()->GetContentType();
} else {
contentType = aTarget->GetDrawTarget()->GetFormat() == FORMAT_B8G8R8X8 ?
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
}
// Create a temporary target for ourselves, so that
// mShadowTarget is only drawn to for the window snapshot.
nsRefPtr<gfxASurface> dummy =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(
gfxIntSize(1, 1),
contentType);
mDummyTarget = new gfxContext(dummy);
aTarget = mDummyTarget;
}
}
BasicLayerManager::BeginTransactionWithTarget(aTarget);
}
void
BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
if (mWidget) {
mWidget->PrepareWindowEffects();
}
BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
ForwardTransaction();
if (mRepeatTransaction) {
mRepeatTransaction = false;
mIsRepeatTransaction = true;
BasicLayerManager::BeginTransaction();
BasicShadowLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
mIsRepeatTransaction = false;
} else {
MakeSnapshotIfRequired();
}
}
bool
BasicShadowLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
{
if (!BasicLayerManager::EndEmptyTransaction(aFlags)) {
// Return without calling ForwardTransaction. This leaves the
// ShadowLayerForwarder transaction open; the following
// EndTransaction will complete it.
return false;
}
ForwardTransaction();
MakeSnapshotIfRequired();
return true;
}
void
BasicShadowLayerManager::MakeSnapshotIfRequired()
{
if (!mShadowTarget) {
return;
}
if (mWidget) {
if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
nsIntRect bounds;
mWidget->GetBounds(bounds);
SurfaceDescriptor inSnapshot, snapshot;
if (AllocSurfaceDescriptor(bounds.Size(),
gfxASurface::CONTENT_COLOR_ALPHA,
&inSnapshot) &&
// The compositor will usually reuse |snapshot| and return
// it through |outSnapshot|, but if it doesn't, it's
// responsible for freeing |snapshot|.
remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
AutoOpenSurface opener(OPEN_READ_ONLY, snapshot);
gfxASurface* source = opener.Get();
mShadowTarget->DrawSurface(source, source->GetSize());
}
if (IsSurfaceDescriptorValid(snapshot)) {
ShadowLayerForwarder::DestroySharedSurface(&snapshot);
}
}
}
mShadowTarget = nullptr;
mDummyTarget = nullptr;
}
void
BasicShadowLayerManager::ForwardTransaction()
{
RenderTraceScope rendertrace("Foward Transaction", "000090");
mPhase = PHASE_FORWARD;
// forward this transaction's changeset to our LayerManagerComposite
AutoInfallibleTArray<EditReply, 10> replies;
if (HasShadowManager() && ShadowLayerForwarder::EndTransaction(&replies)) {
for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
const EditReply& reply = replies[i];
switch (reply.type()) {
case EditReply::TOpContentBufferSwap: {
MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap"));
const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap();
CompositableChild* compositableChild =
static_cast<CompositableChild*>(obs.compositableChild());
ContentClientRemote* contentClient =
static_cast<ContentClientRemote*>(compositableChild->GetCompositableClient());
MOZ_ASSERT(contentClient);
contentClient->SwapBuffers(obs.frontUpdatedRegion());
break;
}
case EditReply::TOpTextureSwap: {
MOZ_LAYERS_LOG(("[LayersForwarder] TextureSwap"));
const OpTextureSwap& ots = reply.get_OpTextureSwap();
CompositableChild* compositableChild =
static_cast<CompositableChild*>(ots.compositableChild());
MOZ_ASSERT(compositableChild);
compositableChild->GetCompositableClient()
->SetDescriptorFromReply(ots.textureId(), ots.image());
break;
}
default:
NS_RUNTIMEABORT("not reached");
}
}
} else if (HasShadowManager()) {
NS_WARNING("failed to forward Layers transaction");
}
mPhase = PHASE_NONE;
// this may result in Layers being deleted, which results in
// PLayer::Send__delete__() and DeallocShmem()
mKeepAlive.Clear();
}
ShadowableLayer*
BasicShadowLayerManager::Hold(Layer* aLayer)
{
NS_ABORT_IF_FALSE(HasShadowManager(),
"top-level tree, no shadow tree to remote to");
ShadowableLayer* shadowable = ToShadowable(aLayer);
NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
mKeepAlive.AppendElement(aLayer);
return shadowable;
}
bool
BasicShadowLayerManager::IsCompositingCheap()
{
// Whether compositing is cheap depends on the parent backend.
return mShadowManager &&
LayerManager::IsCompositingCheap(GetCompositorBackendType());
}
void
BasicShadowLayerManager::SetIsFirstPaint()
{
ShadowLayerForwarder::SetIsFirstPaint();
}
void
BasicShadowLayerManager::ClearCachedResources(Layer* aSubtree)
{
MOZ_ASSERT(!HasShadowManager() || !aSubtree);
if (PLayerTransactionChild* manager = GetShadowManager()) {
manager->SendClearCachedResources();
}
BasicLayerManager::ClearCachedResources(aSubtree);
}
bool
BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY,
bool aDrawingCritical)
{
#ifdef MOZ_WIDGET_ANDROID
Layer* primaryScrollable = GetPrimaryScrollableLayer();
if (primaryScrollable) {
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
// This is derived from the code in
// gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
float devPixelRatioX = 1 / rootTransform.GetXScale();
float devPixelRatioY = 1 / rootTransform.GetYScale();
const gfx::Rect& metricsDisplayPort =
(aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
metrics.mCriticalDisplayPort : metrics.mDisplayPort;
gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
(metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
metricsDisplayPort.width * devPixelRatioX,
metricsDisplayPort.height * devPixelRatioY);
return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
aViewport, aScaleX, aScaleY);
}
#endif
return false;
}
BasicShadowableLayer::~BasicShadowableLayer()
{
if (HasShadow()) {
PLayerChild::Send__delete__(GetShadow());
}
MOZ_COUNT_DTOR(BasicShadowableLayer);
}
}
}

View File

@ -204,134 +204,6 @@ protected:
bool mCompositorMightResample;
};
class BasicShadowLayerManager : public BasicLayerManager,
public ShadowLayerForwarder
{
typedef nsTArray<nsRefPtr<Layer> > LayerRefArray;
public:
BasicShadowLayerManager(nsIWidget* aWidget);
virtual ~BasicShadowLayerManager();
virtual ShadowLayerForwarder* AsShadowForwarder()
{
return this;
}
virtual int32_t GetMaxTextureSize() const;
virtual void SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, ScreenRotation aRotation) MOZ_OVERRIDE;
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT);
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags = END_DEFAULT);
virtual void SetRoot(Layer* aLayer);
virtual void Mutated(Layer* aLayer);
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<RefLayer> CreateRefLayer();
ShadowableLayer* Hold(Layer* aLayer);
bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); }
virtual bool IsCompositingCheap();
virtual bool HasShadowManagerInternal() const { return HasShadowManager(); }
virtual void SetIsFirstPaint() MOZ_OVERRIDE;
// Drop cached resources and ask our shadow manager to do the same,
// if we have one.
virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
void SetRepeatTransaction() { mRepeatTransaction = true; }
bool GetRepeatTransaction() { return mRepeatTransaction; }
bool IsRepeatTransaction() { return mIsRepeatTransaction; }
/**
* Called for each iteration of a progressive tile update. Fills
* aViewport, aScaleX and aScaleY with the current scale and viewport
* being used to composite the layers in this manager, to determine what area
* intersects with the target render rectangle. aDrawingCritical will be
* true if the current drawing operation is using the critical displayport.
* Returns true if the update should continue, or false if it should be
* cancelled.
* This is only called if gfxPlatform::UseProgressiveTilePainting() returns
* true.
*/
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY,
bool aDrawingCritical);
private:
/**
* Forward transaction results to the parent context.
*/
void ForwardTransaction();
/**
* Take a snapshot of the parent context, and copy
* it into mShadowTarget.
*/
void MakeSnapshotIfRequired();
// The bounds of |mTarget| in device pixels.
nsIntRect mTargetBounds;
LayerRefArray mKeepAlive;
// Sometimes we draw to targets that don't natively support
// landscape/portrait orientation. When we need to implement that
// ourselves, |mTargetRotation| describes the induced transform we
// need to apply when compositing content to our target.
ScreenRotation mTargetRotation;
// Used to repeat the transaction right away (to avoid rebuilding
// a display list) to support progressive drawing.
bool mRepeatTransaction;
bool mIsRepeatTransaction;
};
class BasicShadowableThebesLayer;
class BasicShadowableLayer : public ShadowableLayer
{
public:
BasicShadowableLayer()
{
MOZ_COUNT_CTOR(BasicShadowableLayer);
}
~BasicShadowableLayer();
void SetShadow(PLayerChild* aShadow)
{
NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
mShadow = aShadow;
}
virtual void Disconnect()
{
// This is an "emergency Disconnect()", called when the compositing
// process has died. |mShadow| and our Shmem buffers are
// automatically managed by IPDL, so we don't need to explicitly
// free them here (it's hard to get that right on emergency
// shutdown anyway).
mShadow = nullptr;
}
virtual BasicShadowableThebesLayer* AsThebes() { return nullptr; }
};
void
PaintContext(gfxPattern* aPattern,
const nsIntRegion& aVisible,

View File

@ -129,47 +129,6 @@ FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer);
BasicImplData*
ToData(Layer* aLayer);
ShadowableLayer*
ToShadowable(Layer* aLayer);
// Some layers, like ReadbackLayers, can't be shadowed and shadowing
// them doesn't make sense anyway
bool
ShouldShadow(Layer* aLayer);
template<class OpT> BasicShadowableLayer*
GetBasicShadowable(const OpT& op)
{
return static_cast<BasicShadowableLayer*>(
static_cast<const ShadowLayerChild*>(op.textureChild()->Manager())->layer());
}
// Create a shadow layer (PLayerChild) for aLayer, if we're forwarding
// our layer tree to a parent process. Record the new layer creation
// in the current open transaction as a side effect.
template<typename CreatedMethod> void
MaybeCreateShadowFor(BasicShadowableLayer* aLayer,
BasicShadowLayerManager* aMgr,
CreatedMethod aMethod)
{
if (!aMgr->HasShadowManager()) {
return;
}
PLayerChild* shadow = aMgr->ConstructShadowFor(aLayer);
// XXX error handling
NS_ABORT_IF_FALSE(shadow, "failed to create shadow");
aLayer->SetShadow(shadow);
(aMgr->*aMethod)(aLayer);
aMgr->Hold(aLayer->AsLayer());
}
#define MAYBE_CREATE_SHADOW(_type) \
MaybeCreateShadowFor(layer, this, \
&ShadowLayerForwarder::Created ## _type ## Layer)
}
}

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BasicThebesLayer.h"
#include "BasicTiledThebesLayer.h"
#include "gfxUtils.h"
#include "nsIWidget.h"
#include "RenderTrace.h"
@ -74,9 +73,6 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
if (!mContentClient) {
MOZ_ASSERT(!AsShadowableLayer() ||
!static_cast<BasicShadowableThebesLayer*>(AsShadowableLayer())->HasShadow(),
"OMTC layers must have a content client by now");
// we pass a null pointer for the Forwarder argument, which means
// this will not have a ContentHost on the other side.
mContentClient = new ContentClientBasic(nullptr, BasicManager());
@ -231,129 +227,6 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
}
}
BasicShadowableThebesLayer::~BasicShadowableThebesLayer()
{
MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
}
void
BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback)
{
if (!HasShadow()) {
BasicThebesLayer::PaintThebes(aContext, aMaskLayer, aCallback, aCallbackData, aReadback);
return;
}
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
if (!mContentClient) {
mContentClient = ContentClient::CreateContentClient(BasicManager());
if (!mContentClient) {
return;
}
mContentClient->Connect();
BasicManager()->Attach(mContentClient, this);
MOZ_ASSERT(mContentClient->GetForwarder());
}
mContentClient->BeginPaint();
BasicThebesLayer::PaintThebes(aContext, nullptr, aCallback, aCallbackData, aReadback);
mContentClient->EndPaint();
}
void
BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData)
{
ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
MOZ_ASSERT(contentClientRemote->GetIPDLActor() || !HasShadow());
// NB: this just throws away the entire valid region if there are
// too many rects.
mValidRegion.SimplifyInward(8);
Base::PaintBuffer(aContext,
aRegionToDraw, aExtendedRegionToDraw, aRegionToInvalidate,
aDidSelfCopy,
aCallback, aCallbackData);
if (!HasShadow() || BasicManager()->IsTransactionIncomplete()) {
return;
}
// Hold(this) ensures this layer is kept alive through the current transaction
// The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer,
// DestroyThebesBuffer), so deleting this Hold for whatever reason will break things.
BasicManager()->Hold(this);
contentClientRemote->Updated(aRegionToDraw,
mVisibleRegion,
aDidSelfCopy);
}
void
BasicShadowableThebesLayer::Disconnect()
{
mContentClient = nullptr;
BasicShadowableLayer::Disconnect();
}
class ShadowThebesLayerBuffer : public ThebesLayerBuffer
{
typedef ThebesLayerBuffer Base;
public:
ShadowThebesLayerBuffer()
: Base(ContainsVisibleBounds)
{
MOZ_COUNT_CTOR(ShadowThebesLayerBuffer);
}
~ShadowThebesLayerBuffer()
{
MOZ_COUNT_DTOR(ShadowThebesLayerBuffer);
}
/**
* Swap in the old "virtual buffer" (see above) attributes in aNew*
* and return the old ones in aOld*.
*
* Swap() must only be called when the buffer is in its "unmapped"
* state, that is the underlying gfxASurface is not available. It
* is expected that the owner of this buffer holds an unmapped
* SurfaceDescriptor as the backing storage for this buffer. That's
* why no gfxASurface or SurfaceDescriptor parameters appear here.
*/
void Swap(const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
nsIntRect* aOldRect, nsIntPoint* aOldRotation)
{
*aOldRect = BufferRect();
*aOldRotation = BufferRotation();
nsRefPtr<gfxASurface> oldBuffer;
oldBuffer = SetBuffer(nullptr, aNewRect, aNewRotation);
MOZ_ASSERT(!oldBuffer);
}
protected:
virtual already_AddRefed<gfxASurface>
CreateBuffer(ContentType, const nsIntRect&, uint32_t, gfxASurface**)
{
NS_RUNTIMEABORT("ThebesLayerComposite can't paint content");
return nullptr;
}
};
already_AddRefed<ThebesLayer>
BasicLayerManager::CreateThebesLayer()
{
@ -362,29 +235,5 @@ BasicLayerManager::CreateThebesLayer()
return layer.forget();
}
already_AddRefed<ThebesLayer>
BasicShadowLayerManager::CreateThebesLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
#ifdef FORCE_BASICTILEDTHEBESLAYER
if (HasShadowManager() && GetCompositorBackendType() == LAYERS_OPENGL) {
// BasicTiledThebesLayer doesn't support main
// thread compositing so only return this layer
// type if we have a shadow manager.
nsRefPtr<BasicTiledThebesLayer> layer =
new BasicTiledThebesLayer(this);
MAYBE_CREATE_SHADOW(Thebes);
return layer.forget();
} else
#endif
{
nsRefPtr<BasicShadowableThebesLayer> layer =
new BasicShadowableThebesLayer(this);
MAYBE_CREATE_SHADOW(Thebes);
return layer.forget();
}
}
}
}

View File

@ -107,71 +107,6 @@ protected:
RefPtr<ContentClient> mContentClient;
};
class BasicShadowableThebesLayer : public BasicThebesLayer,
public BasicShadowableLayer
{
typedef BasicThebesLayer Base;
public:
BasicShadowableThebesLayer(BasicShadowLayerManager* aManager)
: BasicThebesLayer(aManager)
{
MOZ_COUNT_CTOR(BasicShadowableThebesLayer);
}
virtual ~BasicShadowableThebesLayer();
virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback);
virtual void ClearCachedResources() MOZ_OVERRIDE
{
BasicThebesLayer::ClearCachedResources();
DestroyBackBuffer();
// Don't try to read back from this, it soon may be invalid.
// mROFrontBuffer = null_t();
// mFrontAndBackBufferDiffer = false;
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ThebesLayerAttributes(GetValidRegion());
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
{
return mContentClient;
}
virtual void Disconnect();
virtual BasicShadowableThebesLayer* AsThebes() { return this; }
private:
BasicShadowLayerManager* BasicManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
}
virtual void
PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) MOZ_OVERRIDE;
void DestroyBackBuffer()
{
mContentClient = nullptr;
}
};
}
}

View File

@ -5,7 +5,7 @@
#include "mozilla/layers/CanvasClient.h"
#include "mozilla/layers/TextureClient.h"
#include "BasicCanvasLayer.h"
#include "ClientCanvasLayer.h"
#include "mozilla/layers/ShadowLayers.h"
#include "SharedTextureImage.h"
#include "nsXULAppAPI.h"
@ -49,7 +49,7 @@ CanvasClient2D::CanvasClient2D(CompositableForwarder* aFwd,
}
void
CanvasClient2D::Update(gfx::IntSize aSize, BasicCanvasLayer* aLayer)
CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
if (!mTextureClient) {
mTextureClient = CreateTextureClient(TEXTURE_SHMEM);
@ -63,7 +63,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, BasicCanvasLayer* aLayer)
mTextureClient->EnsureAllocated(aSize, contentType);
gfxASurface* surface = mTextureClient->LockSurface();
static_cast<BasicCanvasLayer*>(aLayer)->UpdateSurface(surface, nullptr);
aLayer->UpdateSurface(surface);
mTextureClient->Unlock();
}
@ -75,7 +75,7 @@ CanvasClientWebGL::CanvasClientWebGL(CompositableForwarder* aFwd,
}
void
CanvasClientWebGL::Update(gfx::IntSize aSize, BasicCanvasLayer* aLayer)
CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
if (!mTextureClient) {
mTextureClient = CreateTextureClient(TEXTURE_STREAM_GL);

View File

@ -13,7 +13,7 @@ namespace mozilla {
namespace layers {
class BasicCanvasLayer;
class ClientCanvasLayer;
/**
* Compositable client for 2d and webgl canvas.
@ -38,7 +38,7 @@ public:
virtual ~CanvasClient() {}
virtual void Update(gfx::IntSize aSize, BasicCanvasLayer* aLayer) = 0;
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) = 0;
virtual void Updated();
@ -64,7 +64,7 @@ public:
return mTextureInfo;
}
virtual void Update(gfx::IntSize aSize, BasicCanvasLayer* aLayer);
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
};
// Used for GL canvases where we don't need to do any readback, i.e., with a
@ -80,7 +80,7 @@ public:
return mTextureInfo;
}
virtual void Update(gfx::IntSize aSize, BasicCanvasLayer* aLayer);
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer);
};
}

View File

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "ClientCanvasLayer.h"
#include "gfxPlatform.h"
#include "SurfaceStream.h"
#include "SharedSurfaceGL.h"
#include "SharedSurfaceEGL.h"
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
void
ClientCanvasLayer::Initialize(const Data& aData)
{
CopyableCanvasLayer::Initialize(aData);
mCanvasClient = nullptr;
if (mGLContext) {
GLScreenBuffer* screen = mGLContext->Screen();
SurfaceStreamType streamType =
SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
screen->PreserveBuffer());
SurfaceFactory_GL* factory = nullptr;
if (!mForceReadback) {
if (ClientManager()->GetCompositorBackendType() == mozilla::layers::LAYERS_OPENGL) {
if (mGLContext->GetEGLContext()) {
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
if (!isCrossProcess) {
// [Basic/OGL Layers, OMTC] WebGL layer init.
factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
} else {
// [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
// Fall back to readback.
}
} else {
// [Basic Layers, OMTC] WebGL layer init.
// Well, this *should* work...
factory = new SurfaceFactory_GLTexture(mGLContext, mGLContext, screen->Caps());
}
}
}
if (factory) {
screen->Morph(factory, streamType);
}
}
}
void
ClientCanvasLayer::RenderLayer()
{
PROFILER_LABEL("ClientCanvasLayer", "Paint");
if (!IsDirty()) {
return;
}
if (GetMaskLayer()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
}
if (!mCanvasClient) {
TextureFlags flags = 0;
if (mNeedsYFlip) {
flags |= NeedsYFlip;
}
mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
ClientManager(), flags);
if (!mCanvasClient) {
return;
}
if (HasShadow()) {
mCanvasClient->Connect();
ClientManager()->Attach(mCanvasClient, this);
}
}
FirePreTransactionCallback();
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
FireDidTransactionCallback();
ClientManager()->Hold(this);
mCanvasClient->Updated();
}
already_AddRefed<CanvasLayer>
ClientLayerManager::CreateCanvasLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ClientCanvasLayer> layer =
new ClientCanvasLayer(this);
CREATE_SHADOW(Canvas);
return layer.forget();
}
}
}

View File

@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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_CLIENTCANVASLAYER_H
#define GFX_CLIENTCANVASLAYER_H
#include "ClientLayerManager.h"
#include "nsXULAppAPI.h"
#include "gfxASurface.h"
#include "mozilla/Preferences.h"
#include "mozilla/layers/LayerTransaction.h"
#include "mozilla/layers/CanvasClient.h"
#include "CopyableCanvasLayer.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
class CanvasClient2D;
class CanvasClientWebGL;
class ClientCanvasLayer : public CopyableCanvasLayer,
public ClientLayer
{
public:
ClientCanvasLayer(ClientLayerManager* aLayerManager) :
CopyableCanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
{
MOZ_COUNT_CTOR(ClientCanvasLayer);
}
virtual ~ClientCanvasLayer()
{
MOZ_COUNT_DTOR(ClientCanvasLayer);
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
CanvasLayer::SetVisibleRegion(aRegion);
}
virtual void Initialize(const Data& aData);
virtual void RenderLayer();
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = CanvasLayerAttributes(mFilter, mBounds);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
mCanvasClient = nullptr;
ClientLayer::Disconnect();
}
virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
{
return mCanvasClient;
}
protected:
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
CompositableType GetCompositableClientType()
{
if (mGLContext && XRE_GetProcessType() == GeckoProcessType_Default) {
return BUFFER_IMAGE_BUFFERED;
}
return BUFFER_IMAGE_SINGLE;
}
RefPtr<CanvasClient> mCanvasClient;
friend class CanvasClient2D;
friend class CanvasClientWebGL;
};
}
}
#endif

View File

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "ClientLayerManager.h"
#include "mozilla/layers/LayerTransaction.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
class ClientColorLayer : public ColorLayer,
public ClientLayer {
public:
ClientColorLayer(ClientLayerManager* aLayerManager) :
ColorLayer(aLayerManager, static_cast<ClientLayer*>(this))
{
MOZ_COUNT_CTOR(ClientColorLayer);
}
virtual ~ClientColorLayer()
{
MOZ_COUNT_DTOR(ClientColorLayer);
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ColorLayer::SetVisibleRegion(aRegion);
}
virtual void RenderLayer()
{
if (GetMaskLayer()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
}
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ColorLayerAttributes(GetColor());
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
ClientLayer::Disconnect();
}
protected:
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
};
already_AddRefed<ColorLayer>
ClientLayerManager::CreateColorLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ClientColorLayer> layer =
new ClientColorLayer(this);
CREATE_SHADOW(Color);
return layer.forget();
}
}
}

View File

@ -0,0 +1,22 @@
#include "ClientContainerLayer.h"
#include "BasicLayersImpl.h"
already_AddRefed<ContainerLayer>
ClientLayerManager::CreateContainerLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ClientContainerLayer> layer =
new ClientContainerLayer(this);
CREATE_SHADOW(Container);
return layer.forget();
}
already_AddRefed<RefLayer>
ClientLayerManager::CreateRefLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ClientRefLayer> layer =
new ClientRefLayer(this);
CREATE_SHADOW(Ref);
return layer.forget();
}

View File

@ -0,0 +1,278 @@
#include "ClientLayerManager.h"
#include "gfxPlatform.h"
using namespace mozilla::layers;
template<class Container> void
ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
{
NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
"Child has wrong manager");
NS_ASSERTION(!aChild->GetParent(),
"aChild already in the tree");
NS_ASSERTION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
"aChild already has siblings?");
NS_ASSERTION(!aAfter ||
(aAfter->Manager() == aContainer->Manager() &&
aAfter->GetParent() == aContainer),
"aAfter is not our child");
aChild->SetParent(aContainer);
if (aAfter == aContainer->mLastChild) {
aContainer->mLastChild = aChild;
}
if (!aAfter) {
aChild->SetNextSibling(aContainer->mFirstChild);
if (aContainer->mFirstChild) {
aContainer->mFirstChild->SetPrevSibling(aChild);
}
aContainer->mFirstChild = aChild;
NS_ADDREF(aChild);
aContainer->DidInsertChild(aChild);
return;
}
Layer* next = aAfter->GetNextSibling();
aChild->SetNextSibling(next);
aChild->SetPrevSibling(aAfter);
if (next) {
next->SetPrevSibling(aChild);
}
aAfter->SetNextSibling(aChild);
NS_ADDREF(aChild);
aContainer->DidInsertChild(aChild);
}
template<class Container> void
ContainerRemoveChild(Layer* aChild, Container* aContainer)
{
NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
"Child has wrong manager");
NS_ASSERTION(aChild->GetParent() == aContainer,
"aChild not our child");
Layer* prev = aChild->GetPrevSibling();
Layer* next = aChild->GetNextSibling();
if (prev) {
prev->SetNextSibling(next);
} else {
aContainer->mFirstChild = next;
}
if (next) {
next->SetPrevSibling(prev);
} else {
aContainer->mLastChild = prev;
}
aChild->SetNextSibling(nullptr);
aChild->SetPrevSibling(nullptr);
aChild->SetParent(nullptr);
aContainer->DidRemoveChild(aChild);
NS_RELEASE(aChild);
}
template<class Container> void
ContainerRepositionChild(Layer* aChild, Layer* aAfter, Container* aContainer)
{
NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
"Child has wrong manager");
NS_ASSERTION(aChild->GetParent() == aContainer,
"aChild not our child");
NS_ASSERTION(!aAfter ||
(aAfter->Manager() == aContainer->Manager() &&
aAfter->GetParent() == aContainer),
"aAfter is not our child");
Layer* prev = aChild->GetPrevSibling();
Layer* next = aChild->GetNextSibling();
if (prev == aAfter) {
// aChild is already in the correct position, nothing to do.
return;
}
if (prev) {
prev->SetNextSibling(next);
}
if (next) {
next->SetPrevSibling(prev);
}
if (!aAfter) {
aChild->SetPrevSibling(nullptr);
aChild->SetNextSibling(aContainer->mFirstChild);
if (aContainer->mFirstChild) {
aContainer->mFirstChild->SetPrevSibling(aChild);
}
aContainer->mFirstChild = aChild;
return;
}
Layer* afterNext = aAfter->GetNextSibling();
if (afterNext) {
afterNext->SetPrevSibling(aChild);
} else {
aContainer->mLastChild = aChild;
}
aAfter->SetNextSibling(aChild);
aChild->SetPrevSibling(aAfter);
aChild->SetNextSibling(afterNext);
}
static bool
HasOpaqueAncestorLayer(Layer* aLayer)
{
for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
return true;
}
return false;
}
class ClientContainerLayer : public ContainerLayer,
public ClientLayer
{
template<class Container>
friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
template<class Container>
friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
template<class Container>
friend void ContainerRepositionChild(Layer* aChild, Layer* aAfter, Container* aContainer);
public:
ClientContainerLayer(ClientLayerManager* aManager) :
ContainerLayer(aManager, static_cast<ClientLayer*>(this))
{
MOZ_COUNT_CTOR(ClientContainerLayer);
mSupportsComponentAlphaChildren = true;
}
virtual ~ClientContainerLayer()
{
while (mFirstChild) {
ContainerRemoveChild(mFirstChild, this);
}
MOZ_COUNT_DTOR(ClientContainerLayer);
}
virtual void RenderLayer()
{
// Setup mSupportsComponentAlphaChildren in the same way
// that ContainerLayerComposite will do.
if (UseIntermediateSurface()) {
if (GetEffectiveVisibleRegion().GetNumRects() != 1 ||
!(GetContentFlags() & Layer::CONTENT_OPAQUE))
{
const gfx3DMatrix& transform3D = GetEffectiveTransform();
gfxMatrix transform;
if (HasOpaqueAncestorLayer(this) &&
transform3D.Is2D(&transform) &&
!transform.HasNonIntegerTranslation()) {
SetSupportsComponentAlphaChildren(
gfxPlatform::GetPlatform()->UsesSubpixelAATextRendering());
}
}
} else {
SetSupportsComponentAlphaChildren(
(GetContentFlags() & Layer::CONTENT_OPAQUE) ||
(GetParent() && GetParent()->SupportsComponentAlphaChildren()));
}
nsAutoTArray<Layer*, 12> children;
SortChildrenBy3DZOrder(children);
for (uint32_t i = 0; i < children.Length(); i++) {
if (children.ElementAt(i)->GetEffectiveVisibleRegion().IsEmpty()) {
continue;
}
ToClientLayer(children.ElementAt(i))->RenderLayer();
}
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ContainerLayer::SetVisibleRegion(aRegion);
}
virtual void InsertAfter(Layer* aChild, Layer* aAfter)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ClientManager()->InsertAfter(ClientManager()->Hold(this),
ClientManager()->Hold(aChild),
aAfter ? ClientManager()->Hold(aAfter) : nullptr);
ContainerInsertAfter(aChild, aAfter, this);
}
virtual void RemoveChild(Layer* aChild)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ClientManager()->RemoveChild(ClientManager()->Hold(this),
ClientManager()->Hold(aChild));
ContainerRemoveChild(aChild, this);
}
virtual void RepositionChild(Layer* aChild, Layer* aAfter)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ClientManager()->RepositionChild(ClientManager()->Hold(this),
ClientManager()->Hold(aChild),
aAfter ? ClientManager()->Hold(aAfter) : nullptr);
ContainerRepositionChild(aChild, aAfter, this);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
void ForceIntermediateSurface() { mUseIntermediateSurface = true; }
void SetSupportsComponentAlphaChildren(bool aSupports) { mSupportsComponentAlphaChildren = aSupports; }
protected:
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
};
class ClientRefLayer : public RefLayer,
public ClientLayer {
public:
ClientRefLayer(ClientLayerManager* aManager) :
RefLayer(aManager, static_cast<ClientLayer*>(this))
{
MOZ_COUNT_CTOR(ClientRefLayer);
}
virtual ~ClientRefLayer()
{
MOZ_COUNT_DTOR(ClientRefLayer);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
ClientLayer::Disconnect();
}
virtual void RenderLayer() { }
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
private:
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
};

View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "ClientLayerManager.h"
#include "mozilla/layers/LayerTransaction.h"
#include "mozilla/layers/ImageClient.h"
#include "ImageContainer.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
class ClientImageLayer : public ImageLayer,
public ClientLayer {
public:
ClientImageLayer(ClientLayerManager* aLayerManager)
: ImageLayer(aLayerManager, static_cast<ClientLayer*>(this))
, mImageClientTypeContainer(BUFFER_UNKNOWN)
{
MOZ_COUNT_CTOR(ClientImageLayer);
}
virtual ~ClientImageLayer()
{
DestroyBackBuffer();
MOZ_COUNT_DTOR(ClientImageLayer);
}
virtual void SetContainer(ImageContainer* aContainer) MOZ_OVERRIDE
{
ImageLayer::SetContainer(aContainer);
mImageClientTypeContainer = BUFFER_UNKNOWN;
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ImageLayer::SetVisibleRegion(aRegion);
}
virtual void RenderLayer();
virtual void ClearCachedResources() MOZ_OVERRIDE
{
DestroyBackBuffer();
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ImageLayerAttributes(mFilter);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual void Disconnect()
{
DestroyBackBuffer();
ClientLayer::Disconnect();
}
void DestroyBackBuffer()
{
mImageClient = nullptr;
}
virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
{
return mImageClient;
}
protected:
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
CompositableType GetImageClientType()
{
if (mImageClientTypeContainer != BUFFER_UNKNOWN) {
return mImageClientTypeContainer;
}
if (mContainer->IsAsync()) {
mImageClientTypeContainer = BUFFER_BRIDGE;
return mImageClientTypeContainer;
}
nsRefPtr<gfxASurface> surface;
AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
mImageClientTypeContainer = autoLock.GetImage() ?
BUFFER_IMAGE_SINGLE : BUFFER_UNKNOWN;
return mImageClientTypeContainer;
}
RefPtr<ImageClient> mImageClient;
CompositableType mImageClientTypeContainer;
};
void
ClientImageLayer::RenderLayer()
{
if (GetMaskLayer()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
}
if (!mContainer) {
return;
}
if (!mImageClient ||
!mImageClient->UpdateImage(mContainer, GetContentFlags())) {
mImageClient = ImageClient::CreateImageClient(GetImageClientType(),
ClientManager(),
mForceSingleTile
? ForceSingleTile
: 0);
if (GetImageClientType() == BUFFER_BRIDGE) {
static_cast<ImageClientBridge*>(mImageClient.get())->SetLayer(this);
}
if (!mImageClient) {
return;
}
if (HasShadow() && !mContainer->IsAsync()) {
mImageClient->Connect();
ClientManager()->Attach(mImageClient, this);
}
if (!mImageClient->UpdateImage(mContainer, GetContentFlags())) {
return;
}
}
ClientManager()->Hold(this);
}
already_AddRefed<ImageLayer>
ClientLayerManager::CreateImageLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ClientImageLayer> layer =
new ClientImageLayer(this);
CREATE_SHADOW(Image);
return layer.forget();
}
}
}

View File

@ -0,0 +1,424 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "ClientLayerManager.h"
#include "nsIWidget.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/Hal.h"
#include "mozilla/layers/PLayerChild.h"
#include "mozilla/layers/PLayerTransactionChild.h"
#include "mozilla/layers/PLayerTransactionParent.h"
#include "CompositorChild.h"
#include "ipc/AutoOpenSurface.h"
#include "ipc/ShadowLayerChild.h"
#include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/ContentClient.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
using namespace mozilla::dom;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
: mPhase(PHASE_NONE)
, mWidget(aWidget)
, mTargetRotation(ROTATION_0)
, mRepeatTransaction(false)
, mIsRepeatTransaction(false)
, mTransactionIncomplete(false)
, mCompositorMightResample(false)
{
MOZ_COUNT_CTOR(ClientLayerManager);
}
ClientLayerManager::~ClientLayerManager()
{
mRoot = nullptr;
MOZ_COUNT_DTOR(ClientLayerManager);
}
int32_t
ClientLayerManager::GetMaxTextureSize() const
{
return ShadowLayerForwarder::GetMaxTextureSize();
}
void
ClientLayerManager::SetDefaultTargetConfiguration(BufferMode aDoubleBuffering,
ScreenRotation aRotation)
{
mTargetRotation = aRotation;
if (mWidget) {
mTargetBounds = mWidget->GetNaturalBounds();
}
}
void
ClientLayerManager::SetRoot(Layer* aLayer)
{
if (mRoot != aLayer) {
// Have to hold the old root and its children in order to
// maintain the same view of the layer tree in this process as
// the parent sees. Otherwise layers can be destroyed
// mid-transaction and bad things can happen (v. bug 612573)
if (mRoot) {
Hold(mRoot);
}
ShadowLayerForwarder::SetRoot(Hold(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
ClientLayerManager::Mutated(Layer* aLayer)
{
LayerManager::Mutated(aLayer);
NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
ShadowLayerForwarder::Mutated(Hold(aLayer));
}
void
ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
mInTransaction = true;
#ifdef MOZ_LAYERS_HAVE_LOG
MOZ_LAYERS_LOG(("[----- BeginTransaction"));
Log();
#endif
NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
mPhase = PHASE_CONSTRUCTION;
NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
nsRefPtr<gfxContext> targetContext = aTarget;
// If the last transaction was incomplete (a failed DoEmptyTransaction),
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
ScreenOrientation orientation;
nsIntRect clientBounds;
if (TabChild* window = mWidget->GetOwningTabChild()) {
orientation = window->GetOrientation();
} else {
hal::ScreenConfiguration currentConfig;
hal::GetCurrentScreenConfiguration(&currentConfig);
orientation = currentConfig.orientation();
}
mWidget->GetClientBounds(clientBounds);
ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation, clientBounds, orientation);
// If we're drawing on behalf of a context with async pan/zoom
// enabled, then the entire buffer of thebes layers might be
// composited (including resampling) asynchronously before we get
// a chance to repaint, so we have to ensure that it's all valid
// and not rotated.
if (mWidget) {
if (TabChild* window = mWidget->GetOwningTabChild()) {
mCompositorMightResample = window->IsAsyncPanZoomEnabled();
}
}
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.
if (aTarget && XRE_GetProcessType() == GeckoProcessType_Default) {
mShadowTarget = aTarget;
}
}
void
ClientLayerManager::BeginTransaction()
{
mInTransaction = true;
BeginTransactionWithTarget(nullptr);
}
bool
ClientLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags)
{
PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal");
#ifdef MOZ_LAYERS_HAVE_LOG
MOZ_LAYERS_LOG((" ----- (beginning paint)"));
Log();
#endif
NS_ASSERTION(InConstruction(), "Should be in construction phase");
mPhase = PHASE_DRAWING;
ClientLayer* root = ClientLayer::ToClientLayer(GetRoot());
mTransactionIncomplete = false;
// Apply pending tree updates before recomputing effective
// properties.
GetRoot()->ApplyPendingUpdatesToSubtree();
mThebesLayerCallback = aCallback;
mThebesLayerCallbackData = aCallbackData;
GetRoot()->ComputeEffectiveTransforms(gfx3DMatrix());
root->RenderLayer();
mThebesLayerCallback = nullptr;
mThebesLayerCallbackData = nullptr;
// 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;
NS_ASSERTION(!aCallback || !mTransactionIncomplete,
"If callback is not null, transaction must be complete");
return !mTransactionIncomplete;
}
void
ClientLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
if (mWidget) {
mWidget->PrepareWindowEffects();
}
EndTransactionInternal(aCallback, aCallbackData, aFlags);
ForwardTransaction();
if (mRepeatTransaction) {
mRepeatTransaction = false;
mIsRepeatTransaction = true;
BeginTransaction();
ClientLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
mIsRepeatTransaction = false;
} else {
MakeSnapshotIfRequired();
}
}
bool
ClientLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
{
mInTransaction = false;
if (!mRoot) {
return false;
}
if (!EndTransactionInternal(nullptr, nullptr, aFlags)) {
// Return without calling ForwardTransaction. This leaves the
// ShadowLayerForwarder transaction open; the following
// EndTransaction will complete it.
return false;
}
ForwardTransaction();
MakeSnapshotIfRequired();
return true;
}
void
ClientLayerManager::MakeSnapshotIfRequired()
{
if (!mShadowTarget) {
return;
}
if (mWidget) {
if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
nsIntRect bounds;
mWidget->GetBounds(bounds);
SurfaceDescriptor inSnapshot, snapshot;
if (AllocSurfaceDescriptor(bounds.Size(),
gfxASurface::CONTENT_COLOR_ALPHA,
&inSnapshot) &&
// The compositor will usually reuse |snapshot| and return
// it through |outSnapshot|, but if it doesn't, it's
// responsible for freeing |snapshot|.
remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
AutoOpenSurface opener(OPEN_READ_ONLY, snapshot);
gfxASurface* source = opener.Get();
mShadowTarget->DrawSurface(source, source->GetSize());
}
if (IsSurfaceDescriptorValid(snapshot)) {
ShadowLayerForwarder::DestroySharedSurface(&snapshot);
}
}
}
mShadowTarget = nullptr;
}
void
ClientLayerManager::ForwardTransaction()
{
mPhase = PHASE_FORWARD;
// forward this transaction's changeset to our LayerManagerComposite
AutoInfallibleTArray<EditReply, 10> replies;
if (HasShadowManager() && ShadowLayerForwarder::EndTransaction(&replies)) {
for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
const EditReply& reply = replies[i];
switch (reply.type()) {
case EditReply::TOpContentBufferSwap: {
MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap"));
const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap();
CompositableChild* compositableChild =
static_cast<CompositableChild*>(obs.compositableChild());
ContentClientRemote* contentClient =
static_cast<ContentClientRemote*>(compositableChild->GetCompositableClient());
MOZ_ASSERT(contentClient);
contentClient->SwapBuffers(obs.frontUpdatedRegion());
break;
}
case EditReply::TOpTextureSwap: {
MOZ_LAYERS_LOG(("[LayersForwarder] TextureSwap"));
const OpTextureSwap& ots = reply.get_OpTextureSwap();
CompositableChild* compositableChild =
static_cast<CompositableChild*>(ots.compositableChild());
MOZ_ASSERT(compositableChild);
compositableChild->GetCompositableClient()
->SetDescriptorFromReply(ots.textureId(), ots.image());
break;
}
default:
NS_RUNTIMEABORT("not reached");
}
}
} else if (HasShadowManager()) {
NS_WARNING("failed to forward Layers transaction");
}
mPhase = PHASE_NONE;
// this may result in Layers being deleted, which results in
// PLayer::Send__delete__() and DeallocShmem()
mKeepAlive.Clear();
}
ShadowableLayer*
ClientLayerManager::Hold(Layer* aLayer)
{
NS_ABORT_IF_FALSE(HasShadowManager(),
"top-level tree, no shadow tree to remote to");
ShadowableLayer* shadowable = ClientLayer::ToClientLayer(aLayer);
NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
mKeepAlive.AppendElement(aLayer);
return shadowable;
}
bool
ClientLayerManager::IsCompositingCheap()
{
// Whether compositing is cheap depends on the parent backend.
return mShadowManager &&
LayerManager::IsCompositingCheap(GetCompositorBackendType());
}
void
ClientLayerManager::SetIsFirstPaint()
{
ShadowLayerForwarder::SetIsFirstPaint();
}
void
ClientLayerManager::ClearCachedResources(Layer* aSubtree)
{
MOZ_ASSERT(!HasShadowManager() || !aSubtree);
if (PLayerTransactionChild* manager = GetShadowManager()) {
manager->SendClearCachedResources();
}
if (aSubtree) {
ClearLayer(aSubtree);
} else if (mRoot) {
ClearLayer(mRoot);
}
}
void
ClientLayerManager::ClearLayer(Layer* aLayer)
{
ClientLayer::ToClientLayer(aLayer)->ClearCachedResources();
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
ClearLayer(child);
}
}
void
ClientLayerManager::GetBackendName(nsAString& aName)
{
switch (Compositor::GetBackend()) {
case LAYERS_BASIC: aName.AssignLiteral("Basic"); return;
case LAYERS_OPENGL: aName.AssignLiteral("OpenGL"); return;
case LAYERS_D3D9: aName.AssignLiteral("Direct3D 9"); return;
case LAYERS_D3D10: aName.AssignLiteral("Direct3D 10"); return;
default: NS_RUNTIMEABORT("Invalid backend");
}
}
bool
ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY,
bool aDrawingCritical)
{
#ifdef MOZ_WIDGET_ANDROID
Layer* primaryScrollable = GetPrimaryScrollableLayer();
if (primaryScrollable) {
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
// This is derived from the code in
// gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
float devPixelRatioX = 1 / rootTransform.GetXScale();
float devPixelRatioY = 1 / rootTransform.GetYScale();
const gfx::Rect& metricsDisplayPort =
(aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
metrics.mCriticalDisplayPort : metrics.mDisplayPort;
gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
(metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
metricsDisplayPort.width * devPixelRatioX,
metricsDisplayPort.height * devPixelRatioY);
return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
aViewport, aScaleX, aScaleY);
}
#endif
return false;
}
ClientLayer::~ClientLayer()
{
if (HasShadow()) {
PLayerChild::Send__delete__(GetShadow());
}
MOZ_COUNT_DTOR(ClientLayer);
}
}
}

View File

@ -0,0 +1,232 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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_CLIENTLAYERMANAGER_H
#define GFX_CLIENTLAYERMANAGER_H
#include "Layers.h"
#include "mozilla/layers/ShadowLayers.h"
namespace mozilla {
namespace layers {
class ClientLayerManager : public LayerManager,
public ShadowLayerForwarder
{
typedef nsTArray<nsRefPtr<Layer> > LayerRefArray;
public:
ClientLayerManager(nsIWidget* aWidget);
virtual ~ClientLayerManager();
virtual ShadowLayerForwarder* AsShadowForwarder()
{
return this;
}
virtual int32_t GetMaxTextureSize() const;
virtual void SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, ScreenRotation aRotation);
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
virtual void BeginTransaction();
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT);
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags = END_DEFAULT);
virtual LayersBackend GetBackendType() { return LAYERS_CLIENT; }
virtual void GetBackendName(nsAString& name);
virtual void SetRoot(Layer* aLayer);
virtual void Mutated(Layer* aLayer);
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<RefLayer> CreateRefLayer();
ShadowableLayer* Hold(Layer* aLayer);
bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); }
virtual bool IsCompositingCheap();
virtual bool HasShadowManagerInternal() const { return HasShadowManager(); }
virtual void SetIsFirstPaint() MOZ_OVERRIDE;
// Drop cached resources and ask our shadow manager to do the same,
// if we have one.
virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
void SetRepeatTransaction() { mRepeatTransaction = true; }
bool GetRepeatTransaction() { return mRepeatTransaction; }
bool IsRepeatTransaction() { return mIsRepeatTransaction; }
void SetTransactionIncomplete() { mTransactionIncomplete = true; }
bool HasShadowTarget() { return !!mShadowTarget; }
bool CompositorMightResample() { return mCompositorMightResample; }
DrawThebesLayerCallback GetThebesLayerCallback() const
{ return mThebesLayerCallback; }
void* GetThebesLayerCallbackData() const
{ return mThebesLayerCallbackData; }
/**
* Called for each iteration of a progressive tile update. Fills
* aViewport, aScaleX and aScaleY with the current scale and viewport
* being used to composite the layers in this manager, to determine what area
* intersects with the target render rectangle. aDrawingCritical will be
* true if the current drawing operation is using the critical displayport.
* Returns true if the update should continue, or false if it should be
* cancelled.
* This is only called if gfxPlatform::UseProgressiveTilePainting() returns
* true.
*/
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
gfx::Rect& aViewport,
float& aScaleX,
float& aScaleY,
bool aDrawingCritical);
#ifdef DEBUG
bool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }
bool InDrawing() { return mPhase == PHASE_DRAWING; }
bool InForward() { return mPhase == PHASE_FORWARD; }
#endif
bool InTransaction() { return mPhase != PHASE_NONE; }
protected:
enum TransactionPhase {
PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
};
TransactionPhase mPhase;
private:
/**
* Forward transaction results to the parent context.
*/
void ForwardTransaction();
/**
* Take a snapshot of the parent context, and copy
* it into mShadowTarget.
*/
void MakeSnapshotIfRequired();
void ClearLayer(Layer* aLayer);
bool EndTransactionInternal(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags);
// The bounds of |mTarget| in device pixels.
nsIntRect mTargetBounds;
LayerRefArray mKeepAlive;
nsIWidget* mWidget;
/* Thebes layer callbacks; valid at the end of a transaciton,
* while rendering */
DrawThebesLayerCallback mThebesLayerCallback;
void *mThebesLayerCallbackData;
// When we're doing a transaction in order to draw to a non-default
// target, the layers transaction is only performed in order to send
// a PLayers:Update. We save the original non-default target to
// mShadowTarget, and then perform the transaction using
// mDummyTarget as the render target. After the transaction ends,
// we send a message to our remote side to capture the actual pixels
// being drawn to the default target, and then copy those pixels
// back to mShadowTarget.
nsRefPtr<gfxContext> mShadowTarget;
// Sometimes we draw to targets that don't natively support
// landscape/portrait orientation. When we need to implement that
// ourselves, |mTargetRotation| describes the induced transform we
// need to apply when compositing content to our target.
ScreenRotation mTargetRotation;
// Used to repeat the transaction right away (to avoid rebuilding
// a display list) to support progressive drawing.
bool mRepeatTransaction;
bool mIsRepeatTransaction;
bool mTransactionIncomplete;
bool mCompositorMightResample;
};
class ClientThebesLayer;
class ClientLayer : public ShadowableLayer
{
public:
ClientLayer()
{
MOZ_COUNT_CTOR(ClientLayer);
}
~ClientLayer();
void SetShadow(PLayerChild* aShadow)
{
NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
mShadow = aShadow;
}
virtual void Disconnect()
{
// This is an "emergency Disconnect()", called when the compositing
// process has died. |mShadow| and our Shmem buffers are
// automatically managed by IPDL, so we don't need to explicitly
// free them here (it's hard to get that right on emergency
// shutdown anyway).
mShadow = nullptr;
}
virtual void ClearCachedResources() { }
virtual void RenderLayer() = 0;
virtual ClientThebesLayer* AsThebes() { return nullptr; }
static inline ClientLayer *
ToClientLayer(Layer* aLayer)
{
return static_cast<ClientLayer*>(aLayer->ImplData());
}
};
// Create a shadow layer (PLayerChild) for aLayer, if we're forwarding
// our layer tree to a parent process. Record the new layer creation
// in the current open transaction as a side effect.
template<typename CreatedMethod> void
CreateShadowFor(ClientLayer* aLayer,
ClientLayerManager* aMgr,
CreatedMethod aMethod)
{
PLayerChild* shadow = aMgr->ConstructShadowFor(aLayer);
// XXX error handling
NS_ABORT_IF_FALSE(shadow, "failed to create shadow");
aLayer->SetShadow(shadow);
(aMgr->*aMethod)(aLayer);
aMgr->Hold(aLayer->AsLayer());
}
#define CREATE_SHADOW(_type) \
CreateShadowFor(layer, this, \
&ShadowLayerForwarder::Created ## _type ## Layer)
}
}
#endif /* GFX_CLIENTLAYERMANAGER_H */

View File

@ -0,0 +1,190 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "ClientThebesLayer.h"
#include "ClientTiledThebesLayer.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
static void
SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
{
if (!aTarget->IsCairo()) {
RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();
if (dt->GetFormat() != FORMAT_B8G8R8A8) {
return;
}
const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
gfx::Rect transformedBounds = dt->GetTransform().TransformBounds(gfx::Rect(Float(bounds.x), Float(bounds.y),
Float(bounds.width), Float(bounds.height)));
transformedBounds.RoundOut();
IntRect intTransformedBounds;
transformedBounds.ToIntRect(&intTransformedBounds);
dt->SetPermitSubpixelAA(!(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
dt->GetOpaqueRect().Contains(intTransformedBounds));
} else {
nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
// Destination doesn't have alpha channel; no need to set any special flags
return;
}
const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
surface->SetSubpixelAntialiasingEnabled(
!(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
surface->GetOpaqueRect().Contains(
aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))));
}
}
void
ClientThebesLayer::PaintThebes()
{
PROFILER_LABEL("ClientThebesLayer", "PaintThebes");
NS_ASSERTION(ClientManager()->InDrawing(),
"Can only draw in drawing phase");
//TODO: This is going to copy back pixels that we might end up
// drawing over anyway. It would be nice if we could avoid
// this duplication.
mContentClient->SyncFrontBufferToBackBuffer();
bool canUseOpaqueSurface = CanUseOpaqueSurface();
ContentType contentType =
canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
gfxASurface::CONTENT_COLOR_ALPHA;
{
uint32_t flags = 0;
#ifndef MOZ_WIDGET_ANDROID
if (ClientManager()->CompositorMightResample()) {
flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
}
if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) {
if (MayResample()) {
flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
}
}
#endif
PaintState state =
mContentClient->BeginPaintBuffer(this, contentType, flags);
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
if (state.mContext) {
// 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,
GetEffectiveVisibleRegion());
nsIntRegion extendedDrawRegion = state.mRegionToDraw;
SetAntialiasingFlags(this, state.mContext);
PaintBuffer(state.mContext,
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
state.mDidSelfCopy);
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
Mutated();
} else {
// It's possible that state.mRegionToInvalidate is nonempty here,
// if we are shrinking the valid region to nothing. So use mRegionToDraw
// instead.
NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
"No context when we have something to draw, resource exhaustion?");
}
}
}
void
ClientThebesLayer::RenderLayer()
{
if (GetMaskLayer()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
}
if (!mContentClient) {
mContentClient = ContentClient::CreateContentClient(ClientManager());
if (!mContentClient) {
return;
}
mContentClient->Connect();
ClientManager()->Attach(mContentClient, this);
MOZ_ASSERT(mContentClient->GetForwarder());
}
mContentClient->BeginPaint();
PaintThebes();
mContentClient->EndPaint();
}
void
ClientThebesLayer::PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy)
{
ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
MOZ_ASSERT(contentClientRemote->GetIPDLActor());
// NB: this just throws away the entire valid region if there are
// too many rects.
mValidRegion.SimplifyInward(8);
if (!ClientManager()->GetThebesLayerCallback()) {
ClientManager()->SetTransactionIncomplete();
return;
}
ClientManager()->GetThebesLayerCallback()(this,
aContext,
aExtendedRegionToDraw,
aRegionToInvalidate,
ClientManager()->GetThebesLayerCallbackData());
// 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, aExtendedRegionToDraw);
mValidRegion.Or(mValidRegion, tmp);
// Hold(this) ensures this layer is kept alive through the current transaction
// The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer,
// DestroyThebesBuffer), so deleting this Hold for whatever reason will break things.
ClientManager()->Hold(this);
contentClientRemote->Updated(aRegionToDraw,
mVisibleRegion,
aDidSelfCopy);
}
already_AddRefed<ThebesLayer>
ClientLayerManager::CreateThebesLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
#ifdef FORCE_BASICTILEDTHEBESLAYER
if (GetCompositorBackendType() == LAYERS_OPENGL) {
nsRefPtr<ClientTiledThebesLayer> layer =
new ClientTiledThebesLayer(this);
CREATE_SHADOW(Thebes);
return layer.forget();
} else
#endif
{
nsRefPtr<ClientThebesLayer> layer =
new ClientThebesLayer(this);
CREATE_SHADOW(Thebes);
return layer.forget();
}
}
}
}

View File

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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_CLIENTTHEBESLAYER_H
#define GFX_CLIENTTHEBESLAYER_H
#include "ClientLayerManager.h"
#include "ThebesLayerBuffer.h"
#include "mozilla/layers/ContentClient.h"
namespace mozilla {
namespace layers {
class ClientThebesLayer : public ThebesLayer,
public ClientLayer {
public:
typedef ThebesLayerBuffer::PaintState PaintState;
typedef ThebesLayerBuffer::ContentType ContentType;
ClientThebesLayer(ClientLayerManager* aLayerManager) :
ThebesLayer(aLayerManager, static_cast<ClientLayer*>(this)),
mContentClient(nullptr)
{
MOZ_COUNT_CTOR(ClientThebesLayer);
}
virtual ~ClientThebesLayer()
{
MOZ_COUNT_DTOR(ClientThebesLayer);
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
ThebesLayer::SetVisibleRegion(aRegion);
}
virtual void InvalidateRegion(const nsIntRegion& aRegion)
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(10);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
}
virtual void RenderLayer();
virtual void ClearCachedResources()
{
if (mContentClient) {
mContentClient->Clear();
}
mValidRegion.SetEmpty();
DestroyBackBuffer();
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ThebesLayerAttributes(GetValidRegion());
}
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
virtual Layer* AsLayer() { return this; }
virtual ShadowableLayer* AsShadowableLayer() { return this; }
virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
{
return mContentClient;
}
virtual void Disconnect()
{
mContentClient = nullptr;
ClientLayer::Disconnect();
}
protected:
void
PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy);
void PaintThebes();
void DestroyBackBuffer()
{
mContentClient = nullptr;
}
RefPtr<ContentClient> mContentClient;
};
}
}
#endif

View File

@ -3,7 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/PLayerTransactionChild.h"
#include "BasicTiledThebesLayer.h"
#include "ClientTiledThebesLayer.h"
#include "gfxImageSurface.h"
#include "GeckoProfiler.h"
#include "gfxPlatform.h"
@ -13,30 +13,30 @@ namespace mozilla {
namespace layers {
BasicTiledThebesLayer::BasicTiledThebesLayer(BasicShadowLayerManager* const aManager)
: ThebesLayer(aManager, static_cast<BasicImplData*>(this))
ClientTiledThebesLayer::ClientTiledThebesLayer(ClientLayerManager* const aManager)
: ThebesLayer(aManager, static_cast<ClientLayer*>(this))
, mContentClient()
{
MOZ_COUNT_CTOR(BasicTiledThebesLayer);
MOZ_COUNT_CTOR(ClientTiledThebesLayer);
mPaintData.mLastScrollOffset = gfx::Point(0, 0);
mPaintData.mFirstPaint = true;
}
BasicTiledThebesLayer::~BasicTiledThebesLayer()
ClientTiledThebesLayer::~ClientTiledThebesLayer()
{
MOZ_COUNT_DTOR(BasicTiledThebesLayer);
MOZ_COUNT_DTOR(ClientTiledThebesLayer);
}
void
BasicTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
aAttrs = ThebesLayerAttributes(GetValidRegion());
}
void
BasicTiledThebesLayer::BeginPaint()
ClientTiledThebesLayer::BeginPaint()
{
if (BasicManager()->IsRepeatTransaction()) {
if (ClientManager()->IsRepeatTransaction()) {
return;
}
@ -82,7 +82,7 @@ BasicTiledThebesLayer::BeginPaint()
// composition bounds.
mPaintData.mCompositionBounds.SetEmpty();
mPaintData.mScrollOffset.MoveTo(0, 0);
Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
if (primaryScrollable) {
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
mPaintData.mScrollOffset = metrics.mScrollOffset;
@ -97,7 +97,7 @@ BasicTiledThebesLayer::BeginPaint()
}
void
BasicTiledThebesLayer::EndPaint(bool aFinish)
ClientTiledThebesLayer::EndPaint(bool aFinish)
{
if (!aFinish && !mPaintData.mPaintFinished) {
return;
@ -108,27 +108,21 @@ BasicTiledThebesLayer::EndPaint(bool aFinish)
}
void
BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback)
ClientTiledThebesLayer::RenderLayer()
{
if (!HasShadow()) {
NS_ASSERTION(false, "Shadow requested for painting\n");
return;
}
if (!aCallback) {
BasicManager()->SetTransactionIncomplete();
LayerManager::DrawThebesLayerCallback callback =
ClientManager()->GetThebesLayerCallback();
void *data = ClientManager()->GetThebesLayerCallbackData();
if (!callback) {
ClientManager()->SetTransactionIncomplete();
return;
}
if (!mContentClient) {
mContentClient = new TiledContentClient(this, BasicManager());
mContentClient = new TiledContentClient(this, ClientManager());
mContentClient->Connect();
BasicManager()->Attach(mContentClient, this);
ClientManager()->Attach(mContentClient, this);
MOZ_ASSERT(mContentClient->GetForwarder());
}
@ -144,8 +138,8 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
}
// Only paint the mask layer on the first transaction.
if (aMaskLayer && !BasicManager()->IsRepeatTransaction()) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())->Paint(aContext, nullptr);
if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
ToClientLayer(GetMaskLayer())->RenderLayer();
}
// Fast path for no progressive updates, no low-precision updates and no
@ -155,12 +149,12 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
GetParent()->GetFrameMetrics().mCriticalDisplayPort.IsEmpty()) {
mValidRegion = mVisibleRegion;
NS_ASSERTION(!BasicManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
aCallback, aCallbackData);
callback, data);
BasicManager()->Hold(this);
ClientManager()->Hold(this);
mContentClient->LockCopyAndWrite(TiledContentClient::TILED_BUFFER);
return;
@ -174,7 +168,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
// Make sure that tiles that fall outside of the visible region are
// discarded on the first update.
if (!BasicManager()->IsRepeatTransaction()) {
if (!ClientManager()->IsRepeatTransaction()) {
mValidRegion.And(mValidRegion, mVisibleRegion);
if (!mPaintData.mLayerCriticalDisplayPort.IsEmpty()) {
// Make sure that tiles that fall outside of the critical displayport are
@ -206,7 +200,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
bool updatedBuffer = false;
// Only draw progressively when the resolution is unchanged.
if (gfxPlatform::UseProgressiveTilePainting() &&
!BasicManager()->HasShadowTarget() &&
!ClientManager()->HasShadowTarget() &&
mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
@ -220,7 +214,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
updatedBuffer =
mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, invalidRegion,
oldValidRegion, &mPaintData,
aCallback, aCallbackData);
callback, data);
} else {
updatedBuffer = true;
mValidRegion = mVisibleRegion;
@ -229,18 +223,18 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
}
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
aCallback, aCallbackData);
callback, data);
}
if (updatedBuffer) {
mPaintData.mFirstPaint = false;
BasicManager()->Hold(this);
ClientManager()->Hold(this);
mContentClient->LockCopyAndWrite(TiledContentClient::TILED_BUFFER);
// If there are low precision updates, mark the paint as unfinished and
// request a repeat transaction.
if (!lowPrecisionInvalidRegion.IsEmpty() && mPaintData.mPaintFinished) {
BasicManager()->SetRepeatTransaction();
ClientManager()->SetRepeatTransaction();
mPaintData.mLowPrecisionPaintCount = 1;
mPaintData.mPaintFinished = false;
}
@ -288,7 +282,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
.ProgressiveUpdate(mLowPrecisionValidRegion,
lowPrecisionInvalidRegion,
oldValidRegion, &mPaintData,
aCallback, aCallbackData);
callback, data);
}
} else if (!mLowPrecisionValidRegion.IsEmpty()) {
// Clear the low precision tiled buffer
@ -296,14 +290,14 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
mLowPrecisionValidRegion.SetEmpty();
mContentClient->mLowPrecisionTiledBuffer.PaintThebes(mLowPrecisionValidRegion,
mLowPrecisionValidRegion,
aCallback, aCallbackData);
callback, data);
}
// We send a Painted callback if we clear the valid region of the low
// precision buffer, so that the shadow buffer's valid region can be updated
// and the associated resources can be freed.
if (updatedLowPrecision) {
BasicManager()->Hold(this);
ClientManager()->Hold(this);
mContentClient->LockCopyAndWrite(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
}

View File

@ -2,12 +2,11 @@
* 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_BASICTILEDTHEBESLAYER_H
#define GFX_BASICTILEDTHEBESLAYER_H
#ifndef GFX_CLIENTTILEDTHEBESLAYER_H
#define GFX_CLIENTTILEDTHEBESLAYER_H
#include "mozilla/layers/ShadowLayers.h"
#include "BasicLayers.h"
#include "BasicImplData.h"
#include "ClientLayerManager.h"
#include "mozilla/layers/TiledContentClient.h" // tiles and tile buffer
namespace mozilla {
@ -30,15 +29,14 @@ class BasicTiledLayerBuffer;
*
* There is no ContentClient for tiled layers. There is a ContentHost, however.
*/
class BasicTiledThebesLayer : public ThebesLayer,
public BasicImplData,
public BasicShadowableLayer
class ClientTiledThebesLayer : public ThebesLayer,
public ClientLayer
{
typedef ThebesLayer Base;
public:
BasicTiledThebesLayer(BasicShadowLayerManager* const aManager);
~BasicTiledThebesLayer();
ClientTiledThebesLayer(ClientLayerManager* const aManager);
~ClientTiledThebesLayer();
// Thebes Layer
virtual Layer* AsLayer() { return this; }
@ -54,19 +52,15 @@ public:
virtual void Disconnect()
{
BasicShadowableLayer::Disconnect();
ClientLayer::Disconnect();
}
virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback);
virtual void RenderLayer();
private:
BasicShadowLayerManager* BasicManager()
ClientLayerManager* ClientManager()
{
return static_cast<BasicShadowLayerManager*>(mManager);
return static_cast<ClientLayerManager*>(mManager);
}
// BasicImplData

View File

@ -6,7 +6,7 @@
#include "mozilla/layers/TiledContentClient.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/MathAlgorithms.h"
#include "BasicTiledThebesLayer.h"
#include "ClientTiledThebesLayer.h"
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
#include "cairo.h"
@ -59,8 +59,8 @@ using namespace gfx;
namespace layers {
TiledContentClient::TiledContentClient(BasicTiledThebesLayer* aThebesLayer,
BasicShadowLayerManager* aManager)
TiledContentClient::TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
ClientLayerManager* aManager)
: CompositableClient(aManager->AsShadowForwarder())
, mTiledBuffer(aThebesLayer, aManager)
, mLowPrecisionTiledBuffer(aThebesLayer, aManager)
@ -87,8 +87,8 @@ TiledContentClient::LockCopyAndWrite(TiledBufferType aType)
buffer->ClearPaintedRegion();
}
BasicTiledLayerBuffer::BasicTiledLayerBuffer(BasicTiledThebesLayer* aThebesLayer,
BasicShadowLayerManager* aManager)
BasicTiledLayerBuffer::BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
ClientLayerManager* aManager)
: mThebesLayer(aThebesLayer)
, mManager(aManager)
, mLastPaintOpaque(false)

View File

@ -84,8 +84,8 @@ struct BasicTiledLayerPaintData {
bool mPaintFinished : 1;
};
class BasicTiledThebesLayer;
class BasicShadowLayerManager;
class ClientTiledThebesLayer;
class ClientLayerManager;
/**
* Provide an instance of TiledLayerBuffer backed by image surfaces.
@ -99,8 +99,8 @@ class BasicTiledLayerBuffer
friend class TiledLayerBuffer<BasicTiledLayerBuffer, BasicTiledLayerTile>;
public:
BasicTiledLayerBuffer(BasicTiledThebesLayer* aThebesLayer,
BasicShadowLayerManager* aManager);
BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
ClientLayerManager* aManager);
BasicTiledLayerBuffer()
: mThebesLayer(nullptr)
, mManager(nullptr)
@ -172,8 +172,8 @@ protected:
private:
gfxASurface::gfxContentType GetContentType() const;
BasicTiledThebesLayer* mThebesLayer;
BasicShadowLayerManager* mManager;
ClientTiledThebesLayer* mThebesLayer;
ClientLayerManager* mManager;
LayerManager::DrawThebesLayerCallback mCallback;
void* mCallbackData;
gfxSize mFrameResolution;
@ -221,11 +221,11 @@ class TiledContentClient : public CompositableClient
// We should have a content client for each tiled buffer which manages its
// own valid region, resolution, etc. Then we could have a much cleaner
// interface and tidy up BasicTiledThebesLayer::PaintThebes (bug 862547).
friend class BasicTiledThebesLayer;
friend class ClientTiledThebesLayer;
public:
TiledContentClient(BasicTiledThebesLayer* aThebesLayer,
BasicShadowLayerManager* aManager);
TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
ClientLayerManager* aManager);
~TiledContentClient()
{

View File

@ -10,7 +10,7 @@
#include "mozilla/layers/PCompositableParent.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "ThebesLayerBuffer.h"
#include "BasicTiledThebesLayer.h" // for BasicTiledLayerBuffer
#include "ClientTiledThebesLayer.h" // for BasicTiledLayerBuffer
#include "mozilla/RefPtr.h"
namespace mozilla {

View File

@ -7,7 +7,7 @@
#define GFX_TILEDCONTENTHOST_H
#include "ContentHost.h"
#include "BasicTiledThebesLayer.h" // for BasicTiledLayerBuffer
#include "ClientTiledThebesLayer.h" // for BasicTiledLayerBuffer
namespace mozilla {
namespace layers {

View File

@ -11,9 +11,14 @@ EXPORTS += [
'BasicImplData.h',
'BasicLayers.h',
'BasicLayersImpl.h',
'BasicTiledThebesLayer.h',
'BasicThebesLayer.h',
'CompositableHost.h',
'CopyableCanvasLayer.h',
'ClientLayerManager.h',
'ClientContainerLayer.h',
'ClientThebesLayer.h',
'ClientTiledThebesLayer.h',
'ClientCanvasLayer.h',
'Composer2D.h',
'GonkIOSurfaceImage.h',
'FrameMetrics.h',

View File

@ -26,6 +26,7 @@ var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
var xr = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
var windows = SpecialPowers.Services.ww.getWindowEnumerator();
var windowutils;
@ -93,7 +94,11 @@ switch(osName)
break;
default: // Linux and others.
is(acceleratedWindows, 0, "Acceleration not supported on '" + osName + "'");
if (xr.OS == "Android" && xr.widgetToolkit != "gonk") {
isnot(acceleratedWindows, 0, "Acceleration enabled on Android");
} else {
is(acceleratedWindows, 0, "Acceleration not supported on '" + osName + "'");
}
}
</script>

View File

@ -2830,7 +2830,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
nsAutoRetainCocoaObject kungFuDeathGrip(self);
bool painted;
{
if (mGeckoChild->GetLayerManager()->GetBackendType() == LAYERS_BASIC) {
nsBaseWidget::AutoLayerManagerSetup
setupLayerManager(mGeckoChild, targetContext, BUFFER_NONE);
painted = mGeckoChild->PaintWindow(region, aIsAlternate);

View File

@ -43,6 +43,7 @@
#include "nsWindow.h"
#include "nsIWidgetListener.h"
#include "cutils/properties.h"
#include "ClientLayerManager.h"
#include "BasicLayers.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
@ -225,6 +226,8 @@ nsWindow::DoDraw(void)
if (listener) {
listener->PaintWindow(gWindowToRedraw, region, 0);
}
} else if (mozilla::layers::LAYERS_CLIENT == lm->GetBackendType()) {
// No need to do anything, the compositor will handle drawing
} else if (mozilla::layers::LAYERS_BASIC == lm->GetBackendType()) {
MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
nsRefPtr<gfxASurface> targetSurface;
@ -552,7 +555,12 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
if (mLayerManager->GetBackendType() == LAYERS_BASIC) {
BasicLayerManager* manager =
static_cast<BasicLayerManager*>(mLayerManager.get());
manager->SetDefaultTargetConfiguration(mozilla::layers::BUFFER_NONE,
manager->SetDefaultTargetConfiguration(mozilla::layers::BUFFER_NONE,
ScreenRotation(EffectiveScreenRotation()));
} else if (mLayerManager->GetBackendType() == LAYERS_CLIENT) {
ClientLayerManager* manager =
static_cast<ClientLayerManager*>(mLayerManager.get());
manager->SetDefaultTargetConfiguration(mozilla::layers::BUFFER_NONE,
ScreenRotation(EffectiveScreenRotation()));
}
return mLayerManager;
@ -606,7 +614,7 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
}
mLayerManager = new BasicShadowLayerManager(this);
mLayerManager = new ClientLayerManager(this);
mUseLayersAcceleration = false;
return mLayerManager;

View File

@ -2123,15 +2123,6 @@ nsWindow::OnExposeEvent(cairo_t *cr)
}
// If this widget uses OMTC...
if (GetLayerManager()->AsShadowForwarder() && GetLayerManager()->AsShadowForwarder()->HasShadowManager()) {
#if defined(MOZ_WIDGET_GTK2)
nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface());
#else
nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface(cr));
#endif
nsBaseWidget::AutoLayerManagerSetup
setupLayerManager(this, ctx, mozilla::layers::BUFFER_NONE);
listener->PaintWindow(this, region, 0);
listener->DidPaintWindow();
g_free(rects);

View File

@ -21,6 +21,7 @@
#include "FrameworkView.h"
#include "nsTextStore.h"
#include "Layers.h"
#include "ClientLayerManager.h"
#include "BasicLayers.h"
#include "Windows.Graphics.Display.h"
#ifdef MOZ_CRASHREPORTER
@ -847,7 +848,7 @@ MetroWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
if (!mLayerManager) {
if (!mView) {
NS_WARNING("Using temporary basic layer manager.");
mLayerManager = new BasicShadowLayerManager(this);
mLayerManager = new BasicLayerManager(this);
mTempBasicLayerInUse = true;
} else {
#ifdef MOZ_CRASHREPORTER

View File

@ -7,7 +7,7 @@
#include "base/basictypes.h"
#include "BasicLayers.h"
#include "ClientLayerManager.h"
#include "gfxPlatform.h"
#if defined(MOZ_ENABLE_D3D10_LAYER)
# include "LayerManagerD3D10.h"
@ -322,7 +322,7 @@ PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
}
#endif
if (!mLayerManager) {
mLayerManager = new BasicShadowLayerManager(this);
mLayerManager = new ClientLayerManager(this);
mLayerManager->AsShadowForwarder()->SetShadowManager(aShadowManager);
}
}
@ -570,6 +570,11 @@ PuppetWidget::Paint()
if (mozilla::layers::LAYERS_D3D10 == mLayerManager->GetBackendType()) {
mAttachedWidgetListener->PaintWindow(this, region, 0);
} else if (mozilla::layers::LAYERS_CLIENT == mLayerManager->GetBackendType()) {
// Do nothing, the compositor will handle drawing
if (mTabChild) {
mTabChild->NotifyPainted();
}
} else {
nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
ctx->Rectangle(gfxRect(0,0,0,0));

View File

@ -20,6 +20,7 @@
#include "nsIServiceManager.h"
#include "mozilla/Preferences.h"
#include "BasicLayers.h"
#include "ClientLayerManager.h"
#include "LayerManagerOGL.h"
#include "mozilla/layers/Compositor.h"
#include "nsIXULRuntime.h"
@ -878,7 +879,7 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
{
mCompositorParent = NewCompositorParent(aWidth, aHeight);
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
LayerManager* lm = CreateBasicLayerManager();
LayerManager* lm = new ClientLayerManager(this);
MessageLoop *childMessageLoop = CompositorParent::CompositorLoop();
mCompositorChild = new CompositorChild(lm);
AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
@ -971,7 +972,7 @@ LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManag
BasicLayerManager* nsBaseWidget::CreateBasicLayerManager()
{
return new BasicShadowLayerManager(this);
return new BasicLayerManager(this);
}
CompositorChild* nsBaseWidget::GetRemoteRenderer()