Bug 765734, part 4: Add an RAII helper to open/close SurfaceDescriptors and mark usage of SurfaceDescriptor as ReadOnly or ReadWrite. r=BenWa,nrc sr=roc

--HG--
extra : rebase_source : 34d9f4f021bac540e96b82eceb855c9c2ce59ce6
This commit is contained in:
Chris Jones 2012-07-12 05:51:58 -07:00
Родитель 1ce07b9102
Коммит 54accca6a3
23 изменённых файлов: 720 добавлений и 219 удалений

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

@ -171,6 +171,16 @@ protected:
return tmp.forget();
}
/**
* Set the buffer only. This is intended to be used with the
* shadow-layer Open/CloseDescriptor interface, to ensure we don't
* accidentally touch a buffer when it's not mapped.
*/
void SetBuffer(gfxASurface* aBuffer)
{
mBuffer = aBuffer;
}
/**
* Get a context at the specified resolution for updating |aBounds|,
* which must be contained within a single quadrant.

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

@ -47,10 +47,10 @@ BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
// Pull out the mask surface and transform here, because the mask
// is internal to basic layers
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
DrawBufferWithRotation(aTarget, aOpacity, maskSurface, &maskTransform);
AutoMaskData mask;
if (GetMaskData(aMaskLayer, &mask)) {
DrawBufferWithRotation(aTarget, aOpacity,
mask.GetSurface(), &mask.GetTransform());
} else {
DrawBufferWithRotation(aTarget, aOpacity);
}

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

@ -58,6 +58,27 @@ public:
gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
const nsIntRegion& aUpdateRegion);
/**
* When BasicThebesLayerBuffer is used with layers that hold
* SurfaceDescriptor, this buffer only has a valid gfxASurface in
* the scope of an AutoOpenSurface for that SurfaceDescriptor. That
* is, it's sort of a "virtual buffer" that's only mapped an
* unmapped within the scope of AutoOpenSurface. None of the
* underlying buffer attributes (rect, rotation) are affected by
* mapping/unmapping.
*
* These helpers just exist to provide more descriptive names of the
* map/unmap process.
*/
void MapBuffer(gfxASurface* aBuffer)
{
SetBuffer(aBuffer);
}
void UnmapBuffer()
{
SetBuffer(nsnull);
}
private:
BasicThebesLayerBuffer(gfxASurface* aBuffer,
const nsIntRect& aRect, const nsIntPoint& aRotation)
@ -87,18 +108,25 @@ public:
MOZ_COUNT_DTOR(ShadowThebesLayerBuffer);
}
void Swap(gfxASurface* aNewBuffer,
const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
gfxASurface** aOldBuffer,
/**
* 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(aNewBuffer,
aNewRect, aNewRotation);
oldBuffer.forget(aOldBuffer);
oldBuffer = SetBuffer(nsnull, aNewRect, aNewRotation);
MOZ_ASSERT(!oldBuffer);
}
protected:
@ -113,4 +141,4 @@ protected:
}
}
#endif
#endif

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

@ -339,9 +339,8 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
// canvas resizes
if (IsSurfaceDescriptorValid(mBackBuffer)) {
nsRefPtr<gfxASurface> backSurface =
BasicManager()->OpenDescriptor(mBackBuffer);
if (gfxIntSize(mBounds.width, mBounds.height) != backSurface->GetSize()) {
AutoOpenSurface backSurface(OPEN_READ_ONLY, mBackBuffer);
if (gfxIntSize(mBounds.width, mBounds.height) != backSurface.Size()) {
DestroyBackBuffer();
}
}
@ -368,15 +367,13 @@ BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
NS_RUNTIMEABORT("creating CanvasLayer back buffer failed!");
}
nsRefPtr<gfxASurface> backSurface =
BasicManager()->OpenDescriptor(mBackBuffer);
AutoOpenSurface autoBackSurface(OPEN_READ_WRITE, mBackBuffer);
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nsnull);
}
UpdateSurface(backSurface, nsnull);
UpdateSurface(autoBackSurface.Get(), nsnull);
FireDidTransactionCallback();
BasicManager()->PaintedCanvas(BasicManager()->Hold(this),
@ -437,15 +434,14 @@ void
BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
CanvasSurface* aNewBack)
{
nsRefPtr<gfxASurface> surface =
BasicManager()->OpenDescriptor(aNewFront);
AutoOpenSurface autoSurface(OPEN_READ_ONLY, aNewFront);
// Destroy mFrontBuffer if size different
gfxIntSize sz = surface->GetSize();
gfxIntSize sz = autoSurface.Size();
bool surfaceConfigChanged = sz != gfxIntSize(mBounds.width, mBounds.height);
if (IsSurfaceDescriptorValid(mFrontSurface)) {
nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontSurface);
AutoOpenSurface autoFront(OPEN_READ_ONLY, mFrontSurface);
surfaceConfigChanged = surfaceConfigChanged ||
surface->GetContentType() != front->GetContentType();
autoSurface.ContentType() != autoFront.ContentType();
}
if (surfaceConfigChanged) {
DestroyFrontBuffer();
@ -459,7 +455,7 @@ BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
} else {
*aNewBack = null_t();
}
mFrontSurface = aNewFront.get_SurfaceDescriptor();
mFrontSurface = aNewFront;
}
void
@ -472,9 +468,8 @@ BasicShadowCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
return;
}
nsRefPtr<gfxASurface> surface =
BasicManager()->OpenDescriptor(mFrontSurface);
nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
AutoOpenSurface autoSurface(OPEN_READ_ONLY, mFrontSurface);
nsRefPtr<gfxPattern> pat = new gfxPattern(autoSurface.Get());
pat->SetFilter(mFilter);
pat->SetExtend(gfxPattern::EXTEND_PAD);

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

@ -41,7 +41,8 @@ public:
gfxContext* aContext,
Layer* aMaskLayer);
virtual already_AddRefed<gfxASurface> GetAsSurface();
virtual bool GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor);
protected:
BasicLayerManager* BasicManager()
@ -86,9 +87,6 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
return nsnull;
}
NS_ASSERTION(surface->GetContentType() != gfxASurface::CONTENT_ALPHA,
"Image layer has alpha image");
nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
if (!pat) {
return nsnull;
@ -154,15 +152,18 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
aPattern->SetExtend(extend);
}
already_AddRefed<gfxASurface>
BasicImageLayer::GetAsSurface()
bool
BasicImageLayer::GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor)
{
if (!mContainer) {
return nsnull;
return false;
}
gfxIntSize dontCare;
return mContainer->GetCurrentAsSurface(&dontCare);
nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&dontCare);
*aSurface = surface.forget().get();
return true;
}
class BasicShadowableImageLayer : public BasicImageLayer,
@ -295,8 +296,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
}
}
nsRefPtr<gfxASurface> dyas = BasicManager()->OpenDescriptor(mBackBufferY);
nsRefPtr<gfxImageSurface> dy = dyas->GetAsImageSurface();
AutoOpenSurface dyas(OPEN_READ_WRITE, mBackBufferY);
gfxImageSurface* dy = dyas.GetAsImage();
for (int i = 0; i < data->mYSize.height; i++) {
memcpy(dy->Data() + i * dy->Stride(),
@ -304,10 +305,10 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
data->mYSize.width);
}
nsRefPtr<gfxASurface> duas = BasicManager()->OpenDescriptor(mBackBufferU);
nsRefPtr<gfxImageSurface> du = duas->GetAsImageSurface();
nsRefPtr<gfxASurface> dvas = BasicManager()->OpenDescriptor(mBackBufferV);
nsRefPtr<gfxImageSurface> dv = dvas->GetAsImageSurface();
AutoOpenSurface duas(OPEN_READ_WRITE, mBackBufferU);
gfxImageSurface* du = duas.GetAsImage();
AutoOpenSurface dvas(OPEN_READ_WRITE, mBackBufferV);
gfxImageSurface* dv = dvas.GetAsImage();
for (int i = 0; i < data->mCbCrSize.height; i++) {
memcpy(du->Data() + i * du->Stride(),
@ -352,9 +353,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
}
nsRefPtr<gfxASurface> backSurface =
BasicManager()->OpenDescriptor(mBackBuffer);
nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
AutoOpenSurface backSurface(OPEN_READ_WRITE, mBackBuffer);
nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface.Get());
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
@ -393,7 +393,8 @@ public:
}
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
already_AddRefed<gfxASurface> GetAsSurface();
virtual bool GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor);
protected:
BasicShadowLayerManager* BasicManager()
@ -409,18 +410,17 @@ void
BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
SharedImage* aNewBack)
{
nsRefPtr<gfxASurface> surface =
BasicManager()->OpenDescriptor(aNewFront);
AutoOpenSurface autoSurface(OPEN_READ_ONLY, aNewFront);
// Destroy mFrontBuffer if size different or image type is different
bool surfaceConfigChanged = surface->GetSize() != mSize;
bool surfaceConfigChanged = autoSurface.Size() != mSize;
if (IsSurfaceDescriptorValid(mFrontBuffer)) {
nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontBuffer);
AutoOpenSurface autoFront(OPEN_READ_ONLY, mFrontBuffer);
surfaceConfigChanged = surfaceConfigChanged ||
surface->GetContentType() != front->GetContentType();
autoSurface.ContentType() != autoFront.ContentType();
}
if (surfaceConfigChanged) {
DestroyFrontBuffer();
mSize = surface->GetSize();
mSize = autoSurface.Size();
}
// If mFrontBuffer
@ -429,7 +429,7 @@ BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
} else {
*aNewBack = null_t();
}
mFrontBuffer = aNewFront.get_SurfaceDescriptor();
mFrontBuffer = aNewFront;
}
void
@ -439,9 +439,8 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
return;
}
nsRefPtr<gfxASurface> surface =
BasicManager()->OpenDescriptor(mFrontBuffer);
nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
AutoOpenSurface autoSurface(OPEN_READ_ONLY, mFrontBuffer);
nsRefPtr<gfxPattern> pat = new gfxPattern(autoSurface.Get());
pat->SetFilter(mFilter);
// The visible region can extend outside the image, so just draw
@ -453,14 +452,16 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
aMaskLayer);
}
already_AddRefed<gfxASurface>
BasicShadowImageLayer::GetAsSurface()
bool
BasicShadowImageLayer::GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor)
{
if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
return nsnull;
return false;
}
return BasicManager()->OpenDescriptor(mFrontBuffer);
*aDescriptor = mFrontBuffer;
return true;
}
already_AddRefed<ImageLayer>

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

@ -101,11 +101,14 @@ public:
/**
* Return a surface for this layer. Will use an existing surface, if
* possible, or may create a temporary surface.
* Implement this method for any layers that might be used as a mask.
* Should only return null if a surface cannor be created.
* possible, or may create a temporary surface. Implement this
* method for any layers that might be used as a mask. Should only
* return false if a surface cannot be created. If true is
* returned, only one of |aSurface| or |aDescriptor| is valid.
*/
virtual already_AddRefed<gfxASurface> GetAsSurface() { return nsnull; }
virtual bool GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor)
{ return false; }
bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }

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

@ -4,41 +4,91 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BasicLayersImpl.h"
#include "mozilla/layers/PLayers.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
already_AddRefed<gfxASurface>
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform)
void
AutoMaskData::Construct(const gfxMatrix& aTransform,
gfxASurface* aSurface)
{
if (aMaskLayer) {
nsRefPtr<gfxASurface> maskSurface =
static_cast<BasicImplData*>(aMaskLayer->ImplData())->GetAsSurface();
if (maskSurface) {
bool maskIs2D =
aMaskLayer->GetEffectiveTransform().CanDraw2D(aMaskTransform);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
return maskSurface.forget();
}
}
return nsnull;
MOZ_ASSERT(!IsConstructed());
mTransform = aTransform;
mSurface = aSurface;
}
void
AutoMaskData::Construct(const gfxMatrix& aTransform,
const SurfaceDescriptor& aSurface)
{
MOZ_ASSERT(!IsConstructed());
mTransform = aTransform;
mSurfaceOpener.construct(OPEN_READ_ONLY, aSurface);
}
gfxASurface*
AutoMaskData::GetSurface()
{
MOZ_ASSERT(IsConstructed());
if (mSurface) {
return mSurface.get();
}
return mSurfaceOpener.ref().Get();
}
const gfxMatrix&
AutoMaskData::GetTransform()
{
MOZ_ASSERT(IsConstructed());
return mTransform;
}
bool
AutoMaskData::IsConstructed()
{
return !!mSurface || !mSurfaceOpener.empty();
}
bool
GetMaskData(Layer* aMaskLayer, AutoMaskData* aMaskData)
{
if (aMaskLayer) {
nsRefPtr<gfxASurface> surface;
SurfaceDescriptor descriptor;
if (static_cast<BasicImplData*>(aMaskLayer->ImplData())
->GetAsSurface(getter_AddRefs(surface), &descriptor) &&
(surface || IsSurfaceDescriptorValid(descriptor))) {
gfxMatrix transform;
DebugOnly<bool> maskIs2D =
aMaskLayer->GetEffectiveTransform().CanDraw2D(&transform);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
if (surface) {
aMaskData->Construct(transform, surface);
} else {
aMaskData->Construct(transform, descriptor);
}
return true;
}
}
return false;
}
void
PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
AutoMaskData mask;
if (GetMaskData(aMaskLayer, &mask)) {
if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->Paint(aOpacity);
aContext->PopGroupToSource();
}
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->SetMatrix(mask.GetTransform());
aContext->Mask(mask.GetSurface());
return;
}
@ -49,20 +99,19 @@ PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
void
FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
AutoMaskData mask;
if (GetMaskData(aMaskLayer, &mask)) {
if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->FillWithOpacity(aOpacity);
aContext->PopGroupToSource();
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->SetMatrix(mask.GetTransform());
aContext->Mask(mask.GetSurface());
} else {
aContext->Save();
aContext->Clip();
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->SetMatrix(mask.GetTransform());
aContext->Mask(mask.GetSurface());
aContext->NewPath();
aContext->Restore();
}

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

@ -6,6 +6,7 @@
#ifndef GFX_BASICLAYERSIMPL_H
#define GFX_BASICLAYERSIMPL_H
#include "ipc/AutoOpenSurface.h"
#include "ipc/ShadowLayerChild.h"
#include "BasicLayers.h"
#include "BasicImplData.h"
@ -62,14 +63,58 @@ protected:
}
};
/**
* Drawing with a mask requires a mask surface and a transform.
* Sometimes the mask surface is a direct gfxASurface, but other times
* it's a SurfaceDescriptor. For SurfaceDescriptor, we need to use a
* scoped AutoOpenSurface to get a gfxASurface for the
* SurfaceDescriptor.
*
* This helper class manages the gfxASurface-or-SurfaceDescriptor
* logic.
*/
class NS_STACK_CLASS AutoMaskData {
public:
AutoMaskData() { }
~AutoMaskData() { }
/**
* Construct this out of either a gfxASurface or a
* SurfaceDescriptor. Construct() must only be called once.
* GetSurface() and GetTransform() must not be called until this has
* been constructed.
*/
void Construct(const gfxMatrix& aTransform,
gfxASurface* aSurface);
void Construct(const gfxMatrix& aTransform,
const SurfaceDescriptor& aSurface);
/** The returned surface can't escape the scope of |this|. */
gfxASurface* GetSurface();
const gfxMatrix& GetTransform();
private:
bool IsConstructed();
gfxMatrix mTransform;
nsRefPtr<gfxASurface> mSurface;
Maybe<AutoOpenSurface> mSurfaceOpener;
AutoMaskData(const AutoMaskData&) MOZ_DELETE;
AutoMaskData& operator=(const AutoMaskData&) MOZ_DELETE;
};
/*
* Extract a mask surface for a mask layer
* Returns a surface for the mask layer if a mask layer is present and has a
* valid surface and transform; nsnull otherwise.
* The transform for the layer will be put in aMaskTransform
* Returns true and through outparams a surface for the mask layer if
* a mask layer is present and has a valid surface and transform;
* false otherwise.
* The transform for the layer will be put in aMaskData
*/
already_AddRefed<gfxASurface>
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform);
bool
GetMaskData(Layer* aMaskLayer, AutoMaskData* aMaskData);
// Paint the current source to a context using a mask, if present
void

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

@ -228,6 +228,58 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
}
}
/**
* AutoOpenBuffer is a helper that builds on top of AutoOpenSurface,
* which we need to get a gfxASurface from a SurfaceDescriptor. For
* other layer types, simple lexical scoping of AutoOpenSurface is
* easy. For ThebesLayers, the lifetime of buffer mappings doesn't
* exactly match simple lexical scopes, so naively putting
* AutoOpenSurfaces on the stack doesn't always work. We use this
* helper to track openings instead.
*
* Any surface that's opened while painting this ThebesLayer will
* notify this helper and register itself for unmapping.
*
* We ignore buffer destruction here because the shadow layers
* protocol already ensures that destroyed buffers stay alive until
* end-of-transaction.
*/
struct NS_STACK_CLASS AutoBufferTracker {
AutoBufferTracker(BasicShadowableThebesLayer* aLayer)
: mLayer(aLayer)
{
MOZ_ASSERT(!mLayer->mBufferTracker);
mLayer->mBufferTracker = this;
if (IsSurfaceDescriptorValid(mLayer->mBackBuffer)) {
mInitialBuffer.construct(OPEN_READ_WRITE, mLayer->mBackBuffer);
mLayer->mBuffer.MapBuffer(mInitialBuffer.ref().Get());
}
}
~AutoBufferTracker() {
mLayer->mBufferTracker = nsnull;
mLayer->mBuffer.UnmapBuffer();
// mInitialBuffer and mNewBuffer will clean up after themselves if
// they were constructed.
}
gfxASurface*
CreatedBuffer(const SurfaceDescriptor& aDescriptor) {
Maybe<AutoOpenSurface>* surface = mNewBuffers.AppendElement();
surface->construct(OPEN_READ_WRITE, aDescriptor);
return surface->ref().Get();
}
Maybe<AutoOpenSurface> mInitialBuffer;
nsAutoTArray<Maybe<AutoOpenSurface>, 2> mNewBuffers;
BasicShadowableThebesLayer* mLayer;
private:
AutoBufferTracker(const AutoBufferTracker&) MOZ_DELETE;
AutoBufferTracker& operator=(const AutoBufferTracker&) MOZ_DELETE;
};
void
BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
@ -240,6 +292,8 @@ BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
return;
}
AutoBufferTracker tracker(this);
BasicThebesLayer::PaintThebes(aContext, nsnull, aCallback, aCallbackData, aReadback);
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
@ -280,18 +334,22 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
return;
}
nsRefPtr<gfxASurface> backBuffer;
gfxASurface* backBuffer = mBuffer.GetBuffer();
if (!IsSurfaceDescriptorValid(mBackBuffer)) {
NS_ABORT_IF_FALSE(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer,
"should have a front RO buffer by now");
MOZ_ASSERT(!backBuffer);
MOZ_ASSERT(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer);
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
backBuffer = CreateBuffer(roFrontBuffer->GetContentType(), roFrontBuffer->GetSize());
} else {
backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
AutoOpenSurface roFrontBuffer(OPEN_READ_ONLY, roFront.buffer());
AllocBackBuffer(roFrontBuffer.ContentType(), roFrontBuffer.Size());
}
mFrontAndBackBufferDiffer = false;
Maybe<AutoOpenSurface> autoBackBuffer;
if (!backBuffer) {
autoBackBuffer.construct(OPEN_READ_WRITE, mBackBuffer);
backBuffer = autoBackBuffer.ref().Get();
}
if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
// We didn't get back a read-only ref to our old back buffer (the
// parent's new front buffer). If the parent is pushing updates
@ -310,10 +368,10 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
mFrontUpdatedRegion.GetBounds().height));
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
AutoOpenSurface autoROFront(OPEN_READ_ONLY, roFront.buffer());
mBuffer.SetBackingBufferAndUpdateFrom(
backBuffer,
roFrontBuffer, roFront.rect(), roFront.rotation(),
autoROFront.Get(), roFront.rect(), roFront.rotation(),
mFrontUpdatedRegion);
mIsNewBuffer = false;
// Now the new back buffer has the same (interesting) pixels as the
@ -364,6 +422,23 @@ BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
mBackBuffer);
}
void
BasicShadowableThebesLayer::AllocBackBuffer(Buffer::ContentType aType,
const nsIntSize& aSize)
{
// This function may *not* open the buffer it allocates.
if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
aType,
&mBackBuffer)) {
enum { buflen = 256 };
char buf[buflen];
PR_snprintf(buf, buflen,
"creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
aSize.width, aSize.height, int(aType));
NS_RUNTIMEABORT(buf);
}
}
already_AddRefed<gfxASurface>
BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
const nsIntSize& aSize)
@ -382,24 +457,15 @@ BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
mBackBuffer = SurfaceDescriptor();
}
// XXX error handling
if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
aType,
&mBackBuffer)) {
enum { buflen = 256 };
char buf[buflen];
PR_snprintf(buf, buflen,
"creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
aSize.width, aSize.height, int(aType));
NS_RUNTIMEABORT(buf);
}
AllocBackBuffer(aType, aSize);
NS_ABORT_IF_FALSE(!mIsNewBuffer,
"Bad! Did we create a buffer twice without painting?");
mIsNewBuffer = true;
return BasicManager()->OpenDescriptor(mBackBuffer);
nsRefPtr<gfxASurface> buffer = mBufferTracker->CreatedBuffer(mBackBuffer);
return buffer.forget();
}
void
@ -483,12 +549,10 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
OptionalThebesBuffer* aReadOnlyFront,
nsIntRegion* aFrontUpdatedRegion)
{
nsRefPtr<gfxASurface> newFrontBuffer =
BasicManager()->OpenDescriptor(aNewFront.buffer());
if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
nsRefPtr<gfxASurface> currentFront = BasicManager()->OpenDescriptor(mFrontBufferDescriptor);
if (currentFront->GetSize() != newFrontBuffer->GetSize()) {
AutoOpenSurface autoNewFrontBuffer(OPEN_READ_ONLY, aNewFront.buffer());
AutoOpenSurface autoCurrentFront(OPEN_READ_ONLY, mFrontBufferDescriptor);
if (autoCurrentFront.Size() != autoNewFrontBuffer.Size()) {
// Current front buffer is obsolete
DestroyFrontBuffer();
}
@ -504,12 +568,11 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
// They might overlap with our old pixels.
aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
nsRefPtr<gfxASurface> unused;
nsIntRect backRect;
nsIntPoint backRotation;
mFrontBuffer.Swap(
newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
getter_AddRefs(unused), &backRect, &backRotation);
aNewFront.rect(), aNewFront.rotation(),
&backRect, &backRotation);
if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
aNewBack->get_ThebesBuffer().rect() = backRect;
@ -534,11 +597,16 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
NS_ASSERTION(BasicManager()->IsRetained(),
"ShadowThebesLayer makes no sense without retained mode");
if (!mFrontBuffer.GetBuffer()) {
if (!IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
return;
}
AutoOpenSurface autoFrontBuffer(OPEN_READ_ONLY, mFrontBufferDescriptor);
mFrontBuffer.MapBuffer(autoFrontBuffer.Get());
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
mFrontBuffer.UnmapBuffer();
}
already_AddRefed<ThebesLayer>

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

@ -103,14 +103,19 @@ protected:
Buffer mBuffer;
};
struct AutoBufferTracker;
class BasicShadowableThebesLayer : public BasicThebesLayer,
public BasicShadowableLayer
{
friend struct AutoBufferTracker;
typedef BasicThebesLayer Base;
public:
BasicShadowableThebesLayer(BasicShadowLayerManager* aManager)
: BasicThebesLayer(aManager)
, mBufferTracker(nsnull)
, mIsNewBuffer(false)
, mFrontAndBackBufferDiffer(false)
{
@ -163,6 +168,10 @@ private:
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) MOZ_OVERRIDE;
// This function may *not* open the buffer it allocates.
void
AllocBackBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
virtual already_AddRefed<gfxASurface>
CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
@ -180,6 +189,12 @@ private:
nsIntRect mBackBufferRect;
nsIntPoint mBackBufferRectRotation;
// This helper object lives on the stack during its lifetime and
// keeps track of buffers we might have mapped and/or allocated.
// When it goes out of scope on the stack, it unmaps whichever
// buffers have been mapped (if any).
AutoBufferTracker* mBufferTracker;
bool mIsNewBuffer;
OptionalThebesBuffer mROFrontBuffer;
nsIntRegion mFrontUpdatedRegion;

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ipc/AutoOpenSurface.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
#include "ShadowBufferD3D9.h"
@ -311,12 +312,11 @@ ShadowCanvasLayerD3D9::Swap(const CanvasSurface& aNewFront,
NS_ASSERTION(aNewFront.type() == CanvasSurface::TSurfaceDescriptor,
"ShadowCanvasLayerD3D9::Swap expected CanvasSurface surface");
nsRefPtr<gfxASurface> surf =
ShadowLayerForwarder::OpenDescriptor(aNewFront);
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront);
if (!mBuffer) {
Init(needYFlip);
}
mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
mBuffer->Upload(surf.Get(), GetVisibleRegion().GetBounds());
*aNewBack = aNewFront;
}

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

@ -3,6 +3,7 @@
* 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 "ipc/AutoOpenSurface.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
#include "ShadowBufferD3D9.h"
@ -551,22 +552,17 @@ ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront,
if (!mBuffer) {
mBuffer = new ShadowBufferD3D9(this);
}
nsRefPtr<gfxASurface> surf =
ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront.get_SurfaceDescriptor());
mBuffer->Upload(surf.Get(), GetVisibleRegion().GetBounds());
} else {
const YUVImage& yuv = aNewFront.get_YUVImage();
nsRefPtr<gfxASurface> asurfY =
ShadowLayerForwarder::OpenDescriptor(yuv.Ydata());
nsRefPtr<gfxImageSurface> surfY = asurfY->GetAsImageSurface();
nsRefPtr<gfxASurface> asurfU =
ShadowLayerForwarder::OpenDescriptor(yuv.Udata());
nsRefPtr<gfxImageSurface> surfU = asurfU->GetAsImageSurface();
nsRefPtr<gfxASurface> asurfV =
ShadowLayerForwarder::OpenDescriptor(yuv.Vdata());
nsRefPtr<gfxImageSurface> surfV = asurfV->GetAsImageSurface();
AutoOpenSurface asurfY(OPEN_READ_ONLY, yuv.Ydata());
AutoOpenSurface asurfU(OPEN_READ_ONLY, yuv.Udata());
AutoOpenSurface asurfV(OPEN_READ_ONLY, yuv.Vdata());
gfxImageSurface* surfY = asurfY.GetAsImage();
gfxImageSurface* surfU = asurfU.GetAsImage();
gfxImageSurface* surfV = asurfV.GetAsImage();
PlanarYCbCrImage::Data data;
data.mYChannel = surfY->Data();

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

@ -8,6 +8,7 @@
/* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
#include "mozilla/Util.h"
#include "ipc/AutoOpenSurface.h"
#include "mozilla/layers/ShadowLayers.h"
#include "ShadowBufferD3D9.h"
@ -617,8 +618,8 @@ ShadowThebesLayerD3D9::Swap(const ThebesBuffer& aNewFront,
}
if (mBuffer) {
nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront.buffer());
mBuffer->Upload(surf.Get(), GetVisibleRegion().GetBounds());
}
*aNewBack = aNewFront;

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 mozilla_layers_AutoOpenSurface_h
#define mozilla_layers_AutoOpenSurface_h 1
#include "base/basictypes.h"
#include "gfxASurface.h"
#include "mozilla/layers/PLayers.h"
#include "ShadowLayers.h"
namespace mozilla {
namespace layers {
/**
* Some surface types can be fairly expensive to open. This helper
* tries to put off opening surfaces as long as it can, until
* ahsolutely necessary. And after being forced to open, it remembers
* the mapping so it doesn't need to be redone.
*/
class NS_STACK_CLASS AutoOpenSurface
{
public:
typedef gfxASurface::gfxContentType gfxContentType;
/** |aDescriptor| must be valid while AutoOpenSurface is
* in scope. */
AutoOpenSurface(OpenMode aMode, const SurfaceDescriptor& aDescriptor);
~AutoOpenSurface();
/**
* These helpers do not necessarily need to open the descriptor to
* return an answer.
*/
gfxContentType ContentType();
gfxIntSize Size();
/** This can't escape the scope of AutoOpenSurface. */
gfxASurface* Get();
/**
* This can't escape the scope of AutoOpenSurface.
*
* This method is currently just a convenience wrapper around
* gfxASurface::GetAsImageSurface() --- it returns a valid surface
* exactly when this->Get()->GetAsImageSurface() would. Clients
* that need guaranteed (fast) ImageSurfaces should allocate the
* underlying descriptor with capability MAP_AS_IMAGE_SURFACE, in
* which case this helper is guaranteed to succeed.
*/
gfxImageSurface* GetAsImage();
private:
SurfaceDescriptor mDescriptor;
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<gfxImageSurface> mSurfaceAsImage;
OpenMode mMode;
AutoOpenSurface(const AutoOpenSurface&) MOZ_DELETE;
AutoOpenSurface& operator=(const AutoOpenSurface&) MOZ_DELETE;
};
} // namespace layers
} // namespace mozilla
#endif // ifndef mozilla_layers_AutoOpenSurface_h

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

@ -26,11 +26,38 @@ ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize&,
}
/*static*/ already_AddRefed<gfxASurface>
ShadowLayerForwarder::PlatformOpenDescriptor(const SurfaceDescriptor&)
ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode,
const SurfaceDescriptor&)
{
return nsnull;
}
/*static*/ bool
ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor&)
{
return false;
}
/*static*/ bool
ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
const SurfaceDescriptor&,
OpenMode,
gfxContentType*,
gfxASurface**)
{
return false;
}
/*static*/ bool
ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
const SurfaceDescriptor&,
OpenMode,
gfxIntSize*,
gfxASurface**)
{
return false;
}
bool
ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor*)
{

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

@ -123,7 +123,8 @@ ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize& aSize,
}
/*static*/ already_AddRefed<gfxASurface>
ShadowLayerForwarder::PlatformOpenDescriptor(const SurfaceDescriptor& aSurface)
ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode aMode,
const SurfaceDescriptor& aSurface)
{
if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface.type()) {
return nsnull;
@ -131,6 +132,31 @@ ShadowLayerForwarder::PlatformOpenDescriptor(const SurfaceDescriptor& aSurface)
return aSurface.get_SurfaceDescriptorX11().OpenForeign();
}
/*static*/ bool
ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor)
{
// XIDs don't need to be "closed".
return false;
}
/*static*/ bool
ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
const SurfaceDescriptor& aDescriptor, OpenMode aMode,
gfxContentType* aContent,
gfxASurface** aSurface)
{
return false;
}
/*static*/ bool
ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
const SurfaceDescriptor& aDescriptor, OpenMode aMode,
gfxIntSize* aSize,
gfxASurface** aSurface)
{
return false;
}
bool
ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
{

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

@ -11,6 +11,7 @@
#include "gfxSharedImageSurface.h"
#include "gfxPlatform.h"
#include "AutoOpenSurface.h"
#include "mozilla/ipc/SharedMemorySysV.h"
#include "mozilla/layers/PLayerChild.h"
#include "mozilla/layers/PLayersChild.h"
@ -355,7 +356,7 @@ ShadowLayerForwarder::ShadowDrawToTarget(gfxContext* aTarget) {
return false;
}
nsRefPtr<gfxASurface> surface = OpenDescriptor(descriptorOut);
nsRefPtr<gfxASurface> surface = OpenDescriptor(OPEN_READ_WRITE, descriptorOut);
aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
aTarget->DrawSurface(surface, surface->GetSize());
@ -434,9 +435,10 @@ ShadowLayerForwarder::AllocBufferWithCaps(const gfxIntSize& aSize,
}
/*static*/ already_AddRefed<gfxASurface>
ShadowLayerForwarder::OpenDescriptor(const SurfaceDescriptor& aSurface)
ShadowLayerForwarder::OpenDescriptor(OpenMode aMode,
const SurfaceDescriptor& aSurface)
{
nsRefPtr<gfxASurface> surf = PlatformOpenDescriptor(aSurface);
nsRefPtr<gfxASurface> surf = PlatformOpenDescriptor(aMode, aSurface);
if (surf) {
return surf.forget();
}
@ -452,6 +454,46 @@ ShadowLayerForwarder::OpenDescriptor(const SurfaceDescriptor& aSurface)
}
}
/*static*/ gfxContentType
ShadowLayerForwarder::GetDescriptorSurfaceContentType(
const SurfaceDescriptor& aDescriptor, OpenMode aMode,
gfxASurface** aSurface)
{
gfxContentType content;
if (PlatformGetDescriptorSurfaceContentType(aDescriptor, aMode,
&content, aSurface)) {
return content;
}
nsRefPtr<gfxASurface> surface = OpenDescriptor(aMode, aDescriptor);
content = surface->GetContentType();
*aSurface = surface.forget().get();
return content;
}
/*static*/ gfxIntSize
ShadowLayerForwarder::GetDescriptorSurfaceSize(
const SurfaceDescriptor& aDescriptor, OpenMode aMode,
gfxASurface** aSurface)
{
gfxIntSize size;
if (PlatformGetDescriptorSurfaceSize(aDescriptor, aMode, &size, aSurface)) {
return size;
}
nsRefPtr<gfxASurface> surface = OpenDescriptor(aMode, aDescriptor);
size = surface->GetSize();
*aSurface = surface.forget().get();
return size;
}
/*static*/ void
ShadowLayerForwarder::CloseDescriptor(const SurfaceDescriptor& aDescriptor)
{
PlatformCloseDescriptor(aDescriptor);
// There's no "close" needed for Shmem surfaces.
}
// Destroy the Shmem SurfaceDescriptor |aSurface|.
template<class ShmemDeallocator>
static void
@ -522,11 +564,38 @@ ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize&,
}
/*static*/ already_AddRefed<gfxASurface>
ShadowLayerForwarder::PlatformOpenDescriptor(const SurfaceDescriptor&)
ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode,
const SurfaceDescriptor&)
{
return nsnull;
}
/*static*/ bool
ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor&)
{
return false;
}
/*static*/ bool
ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
const SurfaceDescriptor&,
OpenMode,
gfxContentType*,
gfxASurface**)
{
return false;
}
/*static*/ bool
ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
const SurfaceDescriptor&,
OpenMode,
gfxIntSize*,
gfxASurface**)
{
return false;
}
bool
ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor*)
{
@ -557,5 +626,60 @@ IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface)
return SurfaceDescriptor::T__None != aSurface.type();
}
AutoOpenSurface::AutoOpenSurface(OpenMode aMode,
const SurfaceDescriptor& aDescriptor)
: mDescriptor(aDescriptor)
, mMode(aMode)
{
MOZ_ASSERT(IsSurfaceDescriptorValid(mDescriptor));
}
AutoOpenSurface::~AutoOpenSurface()
{
if (mSurface) {
mSurface = nsnull;
ShadowLayerForwarder::CloseDescriptor(mDescriptor);
}
}
gfxContentType
AutoOpenSurface::ContentType()
{
if (mSurface) {
return mSurface->GetContentType();
}
return ShadowLayerForwarder::GetDescriptorSurfaceContentType(
mDescriptor, mMode, getter_AddRefs(mSurface));
}
gfxIntSize
AutoOpenSurface::Size()
{
if (mSurface) {
return mSurface->GetSize();
}
return ShadowLayerForwarder::GetDescriptorSurfaceSize(
mDescriptor, mMode, getter_AddRefs(mSurface));
}
gfxASurface*
AutoOpenSurface::Get()
{
if (!mSurface) {
mSurface = ShadowLayerForwarder::OpenDescriptor(mMode, mDescriptor);
}
return mSurface.get();
}
gfxImageSurface*
AutoOpenSurface::GetAsImage()
{
if (!mSurfaceAsImage) {
mSurfaceAsImage = Get()->GetAsImageSurface();
}
return mSurfaceAsImage.get();
}
} // namespace layers
} // namespace mozilla

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

@ -47,6 +47,11 @@ enum BufferCapabilities {
MAP_AS_IMAGE_SURFACE = 1 << 0
};
enum OpenMode {
OPEN_READ_ONLY,
OPEN_READ_WRITE
};
/**
* We want to share layer trees across thread contexts and address
* spaces for several reasons; chief among them
@ -90,7 +95,10 @@ enum BufferCapabilities {
class ShadowLayerForwarder
{
friend class AutoOpenSurface;
public:
typedef gfxASurface::gfxContentType gfxContentType;
typedef LayerManager::LayersBackend LayersBackend;
virtual ~ShadowLayerForwarder();
@ -276,9 +284,6 @@ public:
uint32_t aCaps,
SurfaceDescriptor* aBuffer);
static already_AddRefed<gfxASurface>
OpenDescriptor(const SurfaceDescriptor& aSurface);
void DestroySharedSurface(SurfaceDescriptor* aSurface);
/**
@ -315,8 +320,48 @@ private:
uint32_t aCaps,
SurfaceDescriptor* aBuffer);
/**
* Try to query the content type efficiently, but at worst map the
* surface and return it in *aSurface.
*/
static gfxContentType
GetDescriptorSurfaceContentType(const SurfaceDescriptor& aDescriptor,
OpenMode aMode,
gfxASurface** aSurface);
/**
* It can be expensive to open a descriptor just to query its
* content type. If the platform impl can do this cheaply, it will
* set *aContent and return true.
*/
static bool
PlatformGetDescriptorSurfaceContentType(const SurfaceDescriptor& aDescriptor,
OpenMode aMode,
gfxContentType* aContent,
gfxASurface** aSurface);
// (Same as above, but for surface size.)
static gfxIntSize
GetDescriptorSurfaceSize(const SurfaceDescriptor& aDescriptor,
OpenMode aMode,
gfxASurface** aSurface);
static bool
PlatformGetDescriptorSurfaceSize(const SurfaceDescriptor& aDescriptor,
OpenMode aMode,
gfxIntSize* aSize,
gfxASurface** aSurface);
static already_AddRefed<gfxASurface>
PlatformOpenDescriptor(const SurfaceDescriptor& aDescriptor);
OpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface);
static already_AddRefed<gfxASurface>
PlatformOpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aDescriptor);
/** Make this descriptor unusable for gfxASurface clients. A
* private interface with AutoOpenSurface. */
static void
CloseDescriptor(const SurfaceDescriptor& aDescriptor);
static bool
PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor);
bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
@ -329,7 +374,6 @@ private:
bool mIsFirstPaint;
};
class ShadowLayerManager : public LayerManager
{
public:

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

@ -7,6 +7,7 @@
#include <vector>
#include "AutoOpenSurface.h"
#include "ShadowLayersParent.h"
#include "ShadowLayerParent.h"
#include "ShadowLayers.h"
@ -420,16 +421,16 @@ ShadowLayersParent::RecvDrawToSurface(const SurfaceDescriptor& surfaceIn,
return true;
}
nsRefPtr<gfxASurface> sharedSurface = ShadowLayerForwarder::OpenDescriptor(surfaceIn);
AutoOpenSurface sharedSurface(OPEN_READ_WRITE, surfaceIn);
nsRefPtr<gfxASurface> localSurface =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(sharedSurface->GetSize(),
sharedSurface->GetContentType());
gfxPlatform::GetPlatform()->CreateOffscreenSurface(sharedSurface.Size(),
sharedSurface.ContentType());
nsRefPtr<gfxContext> context = new gfxContext(localSurface);
layer_manager()->BeginTransactionWithTarget(context);
layer_manager()->EndTransaction(NULL, NULL);
nsRefPtr<gfxContext> contextForCopy = new gfxContext(sharedSurface);
nsRefPtr<gfxContext> contextForCopy = new gfxContext(sharedSurface.Get());
contextForCopy->SetOperator(gfxContext::OPERATOR_SOURCE);
contextForCopy->DrawSurface(localSurface, localSurface->GetSize());
return true;

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

@ -3,6 +3,7 @@
* 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 "ipc/AutoOpenSurface.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
@ -305,12 +306,12 @@ ShadowCanvasLayerOGL::Initialize(const Data& aData)
void
ShadowCanvasLayerOGL::Init(const CanvasSurface& aNewFront, bool needYFlip)
{
nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
AutoOpenSurface autoSurf(OPEN_READ_ONLY, aNewFront);
mNeedsYFlip = needYFlip;
mTexImage = gl()->CreateTextureImage(surf->GetSize(),
surf->GetContentType(),
mTexImage = gl()->CreateTextureImage(autoSurf.Size(),
autoSurf.ContentType(),
LOCAL_GL_CLAMP_TO_EDGE,
mNeedsYFlip ? TextureImage::NeedsYFlip : TextureImage::NoFlags);
}
@ -321,14 +322,14 @@ ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
CanvasSurface* aNewBack)
{
if (!mDestroyed) {
nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
gfxIntSize sz = surf->GetSize();
AutoOpenSurface autoSurf(OPEN_READ_ONLY, aNewFront);
gfxIntSize sz = autoSurf.Size();
if (!mTexImage || mTexImage->GetSize() != sz ||
mTexImage->GetContentType() != surf->GetContentType()) {
mTexImage->GetContentType() != autoSurf.ContentType()) {
Init(aNewFront, needYFlip);
}
nsIntRegion updateRegion(nsIntRect(0, 0, sz.width, sz.height));
mTexImage->DirectUpdate(surf, updateRegion);
mTexImage->DirectUpdate(autoSurf.Get(), updateRegion);
}
*aNewBack = aNewFront;
@ -365,6 +366,10 @@ void
ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
const nsIntPoint& aOffset)
{
if (!mTexImage) {
return;
}
mOGLManager->MakeCurrent();
ShaderProgramOGL *program =

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

@ -5,6 +5,7 @@
#include "gfxSharedImageSurface.h"
#include "ipc/AutoOpenSurface.h"
#include "ImageLayerOGL.h"
#include "gfxImageSurface.h"
#include "gfxUtils.h"
@ -660,12 +661,10 @@ bool
ShadowImageLayerOGL::Init(const SharedImage& aFront)
{
if (aFront.type() == SharedImage::TSurfaceDescriptor) {
SurfaceDescriptor desc = aFront.get_SurfaceDescriptor();
nsRefPtr<gfxASurface> surf =
ShadowLayerForwarder::OpenDescriptor(desc);
mSize = surf->GetSize();
AutoOpenSurface autoSurf(OPEN_READ_ONLY, aFront.get_SurfaceDescriptor());
mSize = autoSurf.Size();
mTexImage = gl()->CreateTextureImage(nsIntSize(mSize.width, mSize.height),
surf->GetContentType(),
autoSurf.ContentType(),
LOCAL_GL_CLAMP_TO_EDGE,
mForceSingleTile
? TextureImage::ForceSingleTile
@ -674,15 +673,11 @@ ShadowImageLayerOGL::Init(const SharedImage& aFront)
} else {
YUVImage yuv = aFront.get_YUVImage();
nsRefPtr<gfxASurface> asurfY =
ShadowLayerForwarder::OpenDescriptor(yuv.Ydata());
nsRefPtr<gfxImageSurface> surfY = asurfY->GetAsImageSurface();
nsRefPtr<gfxASurface> asurfU =
ShadowLayerForwarder::OpenDescriptor(yuv.Udata());
nsRefPtr<gfxImageSurface> surfU = asurfU->GetAsImageSurface();
AutoOpenSurface surfY(OPEN_READ_ONLY, yuv.Ydata());
AutoOpenSurface surfU(OPEN_READ_ONLY, yuv.Udata());
mSize = surfY->GetSize();
mCbCrSize = surfU->GetSize();
mSize = surfY.Size();
mCbCrSize = surfU.Size();
if (!mYUVTexture[0].IsAllocated()) {
mYUVTexture[0].Allocate(gl());
@ -710,29 +705,24 @@ ShadowImageLayerOGL::Swap(const SharedImage& aNewFront,
{
if (!mDestroyed) {
if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
nsRefPtr<gfxASurface> surf =
ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
gfxIntSize size = surf->GetSize();
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront.get_SurfaceDescriptor());
gfxIntSize size = surf.Size();
if (mSize != size || !mTexImage ||
mTexImage->GetContentType() != surf->GetContentType()) {
mTexImage->GetContentType() != surf.ContentType()) {
Init(aNewFront);
}
// XXX this is always just ridiculously slow
nsIntRegion updateRegion(nsIntRect(0, 0, size.width, size.height));
mTexImage->DirectUpdate(surf, updateRegion);
mTexImage->DirectUpdate(surf.Get(), updateRegion);
} else {
const YUVImage& yuv = aNewFront.get_YUVImage();
nsRefPtr<gfxASurface> asurfY =
ShadowLayerForwarder::OpenDescriptor(yuv.Ydata());
nsRefPtr<gfxImageSurface> surfY = asurfY->GetAsImageSurface();
nsRefPtr<gfxASurface> asurfU =
ShadowLayerForwarder::OpenDescriptor(yuv.Udata());
nsRefPtr<gfxImageSurface> surfU = asurfU->GetAsImageSurface();
// XXX do we really need to open this?
nsRefPtr<gfxASurface> asurfV =
ShadowLayerForwarder::OpenDescriptor(yuv.Vdata());
nsRefPtr<gfxImageSurface> surfV = asurfV->GetAsImageSurface();
AutoOpenSurface asurfY(OPEN_READ_ONLY, yuv.Ydata());
AutoOpenSurface asurfU(OPEN_READ_ONLY, yuv.Udata());
AutoOpenSurface asurfV(OPEN_READ_ONLY, yuv.Vdata());
nsRefPtr<gfxImageSurface> surfY = asurfY.GetAsImage();
nsRefPtr<gfxImageSurface> surfU = asurfU.GetAsImage();
nsRefPtr<gfxImageSurface> surfV = asurfV.GetAsImage();
mPictureRect = yuv.picture();
gfxIntSize size = surfY->GetSize();

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

@ -3,6 +3,7 @@
* 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 "ipc/AutoOpenSurface.h"
#include "mozilla/layers/PLayers.h"
#include "TiledLayerBuffer.h"
@ -992,7 +993,8 @@ ShadowThebesLayerOGL::EnsureTextureUpdated()
if (mRegionPendingUpload.IsEmpty() || !IsSurfaceDescriptorValid(mFrontBufferDescriptor))
return;
mBuffer->DirectUpdate(mFrontBuffer.Buffer(), mRegionPendingUpload);
AutoOpenSurface frontSurface(OPEN_READ_ONLY, mFrontBuffer.Buffer());
mBuffer->DirectUpdate(frontSurface.Get(), mRegionPendingUpload);
mRegionPendingUpload.SetEmpty();
}
@ -1045,15 +1047,15 @@ ShadowThebesLayerOGL::EnsureTextureUpdated(nsIntRegion& aRegion)
if (updateRegion.IsEmpty())
continue;
AutoOpenSurface surface(OPEN_READ_ONLY, mFrontBuffer.Buffer());
nsRefPtr<TextureImage> texImage;
if (!gl()->CanUploadSubTextures()) {
// When sub-textures are unsupported, TiledTextureImage expands the
// boundaries of DirectUpdate to tile boundaries. So that we don't
// re-upload texture data, use the tile iteration to monitor how much
// of the texture was actually uploaded.
gfxASurface* surface = mFrontBuffer.Buffer();
gfxIntSize size = surface->GetSize();
mBuffer->EnsureTexture(size, surface->GetContentType());
gfxIntSize size = surface.Size();
mBuffer->EnsureTexture(size, surface.ContentType());
texImage = mBuffer->GetTextureImage().get();
if (texImage->GetTileCount() > 1)
texImage->SetIterationCallback(EnsureTextureUpdatedCallback, (void *)&updateRegion);
@ -1062,7 +1064,7 @@ ShadowThebesLayerOGL::EnsureTextureUpdated(nsIntRegion& aRegion)
}
// Upload this quadrant of the region.
mBuffer->DirectUpdate(mFrontBuffer.Buffer(), updateRegion);
mBuffer->DirectUpdate(surface.Get(), updateRegion);
if (!gl()->CanUploadSubTextures())
texImage->SetIterationCallback(nsnull, nsnull);
@ -1102,8 +1104,9 @@ ShadowThebesLayerOGL::ProgressiveUpload()
// Set a tile iteration callback so we can cancel the upload after a tile
// has been uploaded and subtract it from mRegionPendingUpload
mBuffer->EnsureTexture(mFrontBuffer.Buffer()->GetSize(),
mFrontBuffer.Buffer()->GetContentType());
AutoOpenSurface frontSurface(OPEN_READ_ONLY, mFrontBuffer.Buffer());
mBuffer->EnsureTexture(frontSurface.Size(),
frontSurface.ContentType());
nsRefPtr<gl::TextureImage> tiledImage = mBuffer->GetTextureImage().get();
if (tiledImage->GetTileCount() > 1)
tiledImage->SetIterationCallback(ProgressiveUploadCallback, (void *)&mRegionPendingUpload);
@ -1111,7 +1114,7 @@ ShadowThebesLayerOGL::ProgressiveUpload()
mRegionPendingUpload.SetEmpty();
// Upload a tile
mBuffer->DirectUpdate(mFrontBuffer.Buffer(), mRegionPendingUpload);
mBuffer->DirectUpdate(frontSurface.Get(), mRegionPendingUpload);
// Remove the iteration callback
tiledImage->SetIterationCallback(nsnull, nsnull);
@ -1135,13 +1138,11 @@ ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
{
// The double-buffer path is copied and adapted from BasicLayers.cpp
if (ShouldDoubleBuffer()) {
nsRefPtr<gfxASurface> newFrontBuffer =
ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
AutoOpenSurface newFrontBuffer(OPEN_READ_ONLY, aNewFront.buffer());
if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
nsRefPtr<gfxASurface> currentFront =
ShadowLayerForwarder::OpenDescriptor(mFrontBufferDescriptor);
if (currentFront->GetSize() != newFrontBuffer->GetSize()) {
AutoOpenSurface currentFront(OPEN_READ_ONLY, mFrontBufferDescriptor);
if (currentFront.Size() != newFrontBuffer.Size()) {
// Current front buffer is obsolete
DestroyFrontBuffer();
}
@ -1159,12 +1160,12 @@ ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
// They might overlap with our old pixels.
aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
nsRefPtr<gfxASurface> unused;
SurfaceDescriptor unused;
nsIntRect backRect;
nsIntPoint backRotation;
mFrontBuffer.Swap(
newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
getter_AddRefs(unused), &backRect, &backRotation);
aNewFront.buffer(), aNewFront.rect(), aNewFront.rotation(),
&unused, &backRect, &backRotation);
if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
aNewBack->get_ThebesBuffer().rect() = backRect;
@ -1178,12 +1179,13 @@ ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
if (!mBuffer) {
mBuffer = new ShadowBufferOGL(this);
}
nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(mFrontBufferDescriptor);
mBuffer->Upload(surf, aUpdatedRegion, aNewFront.rect(), aNewFront.rotation(), true, mRegionPendingUpload);
AutoOpenSurface frontSurface(OPEN_READ_ONLY, mFrontBufferDescriptor);
mBuffer->Upload(frontSurface.Get(), aUpdatedRegion, aNewFront.rect(), aNewFront.rotation(), true, mRegionPendingUpload);
// Schedule a task to progressively upload the texture
if (!mUploadTask) {
mUploadTask = NewRunnableMethod(this, &ShadowThebesLayerOGL::ProgressiveUpload);
// XXX magic delay constant
MessageLoop::current()->PostDelayedTask(FROM_HERE, mUploadTask, 5);
}
}
@ -1199,8 +1201,8 @@ ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
if (!mBuffer) {
mBuffer = new ShadowBufferOGL(this);
}
nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
mBuffer->Upload(surf, aUpdatedRegion, aNewFront.rect(), aNewFront.rotation(), false, mRegionPendingUpload);
AutoOpenSurface frontSurface(OPEN_READ_ONLY, aNewFront.buffer());
mBuffer->Upload(frontSurface.Get(), aUpdatedRegion, aNewFront.rect(), aNewFront.rotation(), false, mRegionPendingUpload);
}
*aNewBack = aNewFront;

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

@ -67,19 +67,18 @@ public:
MOZ_COUNT_DTOR(ShadowThebesLayerBufferOGL);
}
void Swap(gfxASurface* aNewBuffer,
void Swap(const SurfaceDescriptor& aDescriptor,
const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
gfxASurface** aOldBuffer,
SurfaceDescriptor* aOldDescriptor,
nsIntRect* aOldRect, nsIntPoint* aOldRotation)
{
*aOldDescriptor = mBuffer;
*aOldRect = mBufferRect;
*aOldRotation = mBufferRotation;
nsRefPtr<gfxASurface> oldBuffer = mBuffer;
mBuffer = aDescriptor;
mBufferRect = aNewRect;
mBufferRotation = aNewRotation;
mBuffer = aNewBuffer;
oldBuffer.forget(aOldBuffer);
}
nsIntRect Rect() {
@ -90,7 +89,7 @@ public:
return mBufferRotation;
}
gfxASurface* Buffer() {
SurfaceDescriptor Buffer() {
return mBuffer;
}
@ -100,12 +99,11 @@ public:
*/
void Clear()
{
mBuffer = nsnull;
mBufferRect.SetEmpty();
}
protected:
nsRefPtr<gfxASurface> mBuffer;
SurfaceDescriptor mBuffer;
nsIntRect mBufferRect;
nsIntPoint mBufferRotation;
};