Bug 740580 - Add support for Azure DrawTargets to BasicLayers. r=Bas

This commit is contained in:
George Wright 2012-10-02 22:09:12 -04:00
parent 3a48f9d338
commit b65e8574f8
10 changed files with 365 additions and 28 deletions

View File

@ -13,10 +13,13 @@
#include "ipc/AutoOpenSurface.h"
#include "nsDeviceContext.h"
#include "sampler.h"
#include "mozilla/gfx/2D.h"
namespace mozilla {
namespace layers {
using namespace gfx;
nsIntRect
ThebesLayerBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide)
{
@ -60,7 +63,18 @@ ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget,
true);
gfxPoint quadrantTranslation(quadrantRect.x, quadrantRect.y);
nsRefPtr<gfxPattern> pattern = new gfxPattern(EnsureBuffer());
EnsureBuffer();
if (!BufferValid()) {
return;
}
nsRefPtr<gfxPattern> pattern;
if (mBuffer) {
pattern = new gfxPattern(mBuffer);
} else {
RefPtr<SourceSurface> source = mDTBuffer->Snapshot();
pattern = new gfxPattern(source, Matrix());
}
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
gfxPattern::GraphicsFilter filter = gfxPattern::FILTER_NEAREST;
@ -116,7 +130,11 @@ ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
already_AddRefed<gfxContext>
ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds)
{
nsRefPtr<gfxContext> ctx = new gfxContext(EnsureBuffer());
EnsureBuffer();
if (!BufferValid()) {
return nullptr;
}
nsRefPtr<gfxContext> ctx = mBuffer ? new gfxContext(mBuffer) : new gfxContext(mDTBuffer);
// Figure out which quadrant to draw in
int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x;
@ -133,7 +151,13 @@ ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds)
gfxASurface::gfxContentType
ThebesLayerBuffer::BufferContentType()
{
return mBuffer ? mBuffer->GetContentType() : mBufferProvider->ContentType();
if (mBuffer) {
return mBuffer->GetContentType();
}
if (mDTBuffer) {
return ContentForFormat(mDTBuffer->GetFormat());
}
return mBufferProvider->ContentType();
}
bool
@ -144,19 +168,29 @@ ThebesLayerBuffer::BufferSizeOkFor(const nsIntSize& aSize)
aSize < mBufferRect.Size()));
}
gfxASurface*
void
ThebesLayerBuffer::EnsureBuffer()
{
if (!mBuffer && mBufferProvider) {
mBuffer = mBufferProvider->Get();
if (mBuffer || mDTBuffer) {
return;
}
if (!mBufferProvider) {
NS_ASSERTION(false, "Doesn't have mBuffer, mDTBuffer or mBufferProvider");
return;
}
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
mDTBuffer = mBufferProvider->GetDrawTarget();
NS_ASSERTION(mDTBuffer, "Failed to create DrawTarget");
} else {
mBuffer = mBufferProvider->Get();
NS_ASSERTION(mBuffer, "Failed to create buffer");
}
return mBuffer;
}
bool
ThebesLayerBuffer::HaveBuffer()
{
return mBuffer || mBufferProvider;
return mBuffer || mDTBuffer || mBufferProvider;
}
static void
@ -253,6 +287,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
nsRefPtr<gfxASurface> destBuffer;
RefPtr<DrawTarget> destDT;
uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
if (canReuseBuffer) {
nsIntRect keepArea;
@ -274,10 +309,21 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
// The stuff we need to redraw will wrap around an edge of the
// buffer, so move the pixels we can keep into a position that
// lets us redraw in just one quadrant.
if (mBufferRotation == nsIntPoint(0,0)) {
nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
EnsureBuffer();
if (!BufferValid())
return result;
nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
EnsureBuffer()->MovePixels(srcRect, dest);
if (mBuffer) {
nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
mBuffer->MovePixels(srcRect, dest);
} else {
IntRect srcRect(0, 0, mBufferRect.width, mBufferRect.height);
RefPtr<SourceSurface> snapshot = mDTBuffer->Snapshot();
mDTBuffer->CopySurface(snapshot, srcRect, IntPoint(dest.x, dest.y));
}
result.mDidSelfCopy = true;
// Don't set destBuffer; we special-case self-copies, and
// just did the necessary work above.
@ -286,8 +332,12 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
// We can't do a real self-copy because the buffer is rotated.
// So allocate a new buffer for the destination.
destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
if (!destBuffer)
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
destDT = CreateDrawTarget(destBufferRect.Size(), contentType);
} else {
destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
}
if (!destBuffer && !destDT)
return result;
}
} else {
@ -303,8 +353,12 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
}
} else {
// The buffer's not big enough, so allocate a new one
destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
if (!destBuffer)
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
destDT = CreateDrawTarget(destBufferRect.Size(), contentType);
} else {
destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
}
if (!destBuffer && !destDT)
return result;
}
NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
@ -312,19 +366,23 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
// If we have no buffered data already, then destBuffer will be a fresh buffer
// and we do not need to clear it below.
bool isClear = mBuffer == nullptr;
bool isClear = !mBuffer && !mDTBuffer;
if (destBuffer) {
if (destBuffer || destDT) {
if (HaveBuffer()) {
// Copy the bits
nsRefPtr<gfxContext> tmpCtx = new gfxContext(destBuffer);
nsRefPtr<gfxContext> tmpCtx = destBuffer ? new gfxContext(destBuffer) : new gfxContext(destDT);
nsIntPoint offset = -destBufferRect.TopLeft();
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpCtx->Translate(gfxPoint(offset.x, offset.y));
DrawBufferWithRotation(tmpCtx, 1.0);
}
mBuffer = destBuffer.forget();
if (destBuffer) {
mBuffer = destBuffer.forget();
} else {
mDTBuffer = destDT.forget();
}
mBufferRect = destBufferRect;
mBufferRotation = nsIntPoint(0,0);
}

View File

@ -8,6 +8,7 @@
#include "gfxContext.h"
#include "gfxASurface.h"
#include "gfxPlatform.h"
#include "nsRegion.h"
namespace mozilla {
@ -69,6 +70,7 @@ public:
void Clear()
{
mBuffer = nullptr;
mDTBuffer = nullptr;
mBufferProvider = nullptr;
mBufferRect.SetEmpty();
}
@ -127,11 +129,32 @@ public:
virtual already_AddRefed<gfxASurface>
CreateBuffer(ContentType aType, const nsIntSize& aSize, uint32_t aFlags) = 0;
/**
* Return a new DrawTarget of |aSize| with SurfaceFormat |aFormat|.
*/
virtual TemporaryRef<gfx::DrawTarget>
CreateDrawTarget(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat)
{
return gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(aSize, aFormat);
}
/**
* Return a new DrawTarget of |aSize| with ContentType |aContent|.
*/
TemporaryRef<gfx::DrawTarget>
CreateDrawTarget(const nsIntSize& aSize, ContentType aContent)
{
gfx::SurfaceFormat format = gfx::SurfaceFormatForImageFormat(
gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent));
return CreateDrawTarget(gfx::IntSize(aSize.width, aSize.height), format);
}
/**
* Get the underlying buffer, if any. This is useful because we can pass
* in the buffer as the default "reference surface" if there is one.
* Don't use it for anything else!
*/
gfx::DrawTarget* GetDT() { return mDTBuffer; }
gfxASurface* GetBuffer() { return mBuffer; }
protected:
@ -174,6 +197,17 @@ protected:
return tmp.forget();
}
TemporaryRef<gfx::DrawTarget>
SetDT(gfx::DrawTarget* aBuffer,
const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation)
{
RefPtr<gfx::DrawTarget> tmp = mDTBuffer.forget();
mDTBuffer = aBuffer;
mBufferRect = aBufferRect;
mBufferRotation = aBufferRotation;
return tmp.forget();
}
/**
* Set the buffer provider only. This is used with surfaces that
* require explicit map/unmap, which |aProvider| is used to do on
@ -190,6 +224,7 @@ protected:
mBufferProvider = aProvider;
if (!mBufferProvider) {
mBuffer = nullptr;
mDTBuffer = nullptr;
} else {
// Only this buffer provider can give us a buffer. If we
// already have one, something has gone wrong.
@ -215,15 +250,24 @@ private:
gfxASurface::gfxContentType BufferContentType();
bool BufferSizeOkFor(const nsIntSize& aSize);
/**
* If the buffer hasn't been mapped, map it and return it.
* If the buffer hasn't been mapped, map it.
*/
gfxASurface* EnsureBuffer();
void EnsureBuffer();
/**
* Check if the buffer is valid
*/
bool BufferValid() {
return mBuffer || mDTBuffer;
}
/**
* True if we have a buffer where we can get it (but not necessarily
* mapped currently).
*/
bool HaveBuffer();
RefPtr<gfx::DrawTarget> mDTBuffer;
nsRefPtr<gfxASurface> mBuffer;
/**
* This member is only set transiently. It's used to map mBuffer

View File

@ -64,11 +64,38 @@ BasicThebesLayerBuffer::CreateBuffer(ContentType aType,
return mLayer->CreateBuffer(aType, aSize);
}
TemporaryRef<DrawTarget>
BasicThebesLayerBuffer::CreateDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
{
return mLayer->CreateDrawTarget(aSize, aFormat);
}
void
BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
gfxASurface* aBuffer,
gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
const nsIntRegion& aUpdateRegion)
{
SetBackingBuffer(aBuffer, aRect, aRotation);
nsRefPtr<gfxContext> destCtx =
GetContextForQuadrantUpdate(aUpdateRegion.GetBounds());
if (!destCtx) {
return;
}
destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
if (IsClippingCheap(destCtx, aUpdateRegion)) {
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
}
BasicThebesLayerBuffer srcBuffer(aSource, aRect, aRotation);
srcBuffer.DrawBufferWithRotation(destCtx, 1.0);
}
void
BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
DrawTarget* aBuffer,
DrawTarget* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
const nsIntRegion& aUpdateRegion)
{
SetBackingBuffer(aBuffer, aRect, aRotation);
nsRefPtr<gfxContext> destCtx =

View File

@ -8,6 +8,8 @@
#include "BasicLayersImpl.h"
#include "mozilla/gfx/2D.h"
namespace mozilla {
namespace layers {
@ -39,6 +41,10 @@ public:
virtual already_AddRefed<gfxASurface>
CreateBuffer(ContentType aType, const nsIntSize& aSize, uint32_t aFlags);
virtual TemporaryRef<mozilla::gfx::DrawTarget>
CreateDrawTarget(const mozilla::gfx::IntSize& aSize,
mozilla::gfx::SurfaceFormat aFormat);
/**
* Swap out the old backing buffer for |aBuffer| and attributes.
*/
@ -55,11 +61,27 @@ public:
oldBuffer = SetBuffer(aBuffer, aRect, aRotation);
}
void SetBackingBuffer(mozilla::gfx::DrawTarget* aBuffer,
const nsIntRect& aRect, const nsIntPoint& aRotation)
{
mozilla::gfx::IntSize prevSize = mozilla::gfx::IntSize(BufferRect().width, BufferRect().height);
mozilla::gfx::IntSize newSize = aBuffer->GetSize();
NS_ABORT_IF_FALSE(newSize == prevSize,
"Swapped-in buffer size doesn't match old buffer's!");
RefPtr<mozilla::gfx::DrawTarget> oldBuffer;
oldBuffer = SetDT(aBuffer, aRect, aRotation);
}
void SetBackingBufferAndUpdateFrom(
gfxASurface* aBuffer,
gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
const nsIntRegion& aUpdateRegion);
void SetBackingBufferAndUpdateFrom(
mozilla::gfx::DrawTarget* aBuffer,
mozilla::gfx::DrawTarget* 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
@ -91,6 +113,14 @@ private:
SetBuffer(aBuffer, aRect, aRotation);
}
BasicThebesLayerBuffer(mozilla::gfx::DrawTarget* aBuffer,
const nsIntRect& aRect, const nsIntPoint& aRotation)
: ThebesLayerBuffer(ContainsVisibleBounds)
{
SetDT(aBuffer, aRect, aRotation);
}
BasicThebesLayer* mLayer;
};
@ -138,6 +168,13 @@ protected:
NS_RUNTIMEABORT("ShadowThebesLayer can't paint content");
return nullptr;
}
virtual TemporaryRef<mozilla::gfx::DrawTarget>
CreateDrawTarget(const mozilla::gfx::IntSize&, mozilla::gfx::SurfaceFormat)
{
NS_RUNTIMEABORT("ShadowThebesLayer can't paint content");
return nullptr;
}
};
}

View File

@ -8,6 +8,7 @@
#include "nsIWidget.h"
#include "RenderTrace.h"
#include "sampler.h"
#include "gfxSharedImageSurface.h"
#include "prprf.h"
@ -35,6 +36,13 @@ BasicThebesLayer::CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize
aType, gfxIntSize(aSize.width, aSize.height));
}
TemporaryRef<DrawTarget>
BasicThebesLayer::CreateDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
{
return gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(aSize, aFormat);
}
static nsIntRegion
IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
{
@ -265,6 +273,10 @@ struct NS_STACK_CLASS AutoBufferTracker {
gfxASurface* GetInitialBuffer() { return mInitialBuffer.ref().Get(); }
DrawTarget* GetInitialDrawTarget() {
return mInitialBuffer.ref().GetDrawTarget();
}
gfxASurface*
CreatedBuffer(const SurfaceDescriptor& aDescriptor) {
Maybe<AutoOpenSurface>* surface = mNewBuffers.AppendElement();
@ -346,8 +358,10 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
MOZ_ASSERT(mBufferTracker);
nsRefPtr<gfxASurface> backBuffer = mBuffer.GetBuffer();
DrawTarget* backDT = mBuffer.GetDT();
if (!IsSurfaceDescriptorValid(mBackBuffer)) {
MOZ_ASSERT(!backBuffer);
MOZ_ASSERT(!backBuffer && !backDT);
MOZ_ASSERT(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer);
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
AutoOpenSurface roFrontBuffer(OPEN_READ_ONLY, roFront.buffer());
@ -355,8 +369,12 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
}
mFrontAndBackBufferDiffer = false;
if (!backBuffer) {
backBuffer = mBufferTracker->GetInitialBuffer();
if (!backBuffer && !backDT) {
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
backDT = mBufferTracker->GetInitialDrawTarget();
} else {
backBuffer = mBufferTracker->GetInitialBuffer();
}
}
if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
@ -365,7 +383,11 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
// to a texture it owns, then we probably got back the same buffer
// we pushed in the update and all is well. If not, ...
mValidRegion = mFrontValidRegion;
mBuffer.SetBackingBuffer(backBuffer, mBackBufferRect, mBackBufferRectRotation);
if (backDT) {
mBuffer.SetBackingBuffer(backDT, mBackBufferRect, mBackBufferRectRotation);
} else {
mBuffer.SetBackingBuffer(backBuffer, mBackBufferRect, mBackBufferRectRotation);
}
return;
}
@ -378,10 +400,19 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
AutoOpenSurface autoROFront(OPEN_READ_ONLY, roFront.buffer());
mBuffer.SetBackingBufferAndUpdateFrom(
backBuffer,
autoROFront.Get(), roFront.rect(), roFront.rotation(),
mFrontUpdatedRegion);
if (backDT) {
mBuffer.SetBackingBufferAndUpdateFrom(
backDT,
autoROFront.GetDrawTarget(), roFront.rect(), roFront.rotation(),
mFrontUpdatedRegion);
} else {
mBuffer.SetBackingBufferAndUpdateFrom(
backBuffer,
autoROFront.Get(), roFront.rect(), roFront.rotation(),
mFrontUpdatedRegion);
}
mIsNewBuffer = false;
// Now the new back buffer has the same (interesting) pixels as the
// new front buffer, and mValidRegion et al. are correct wrt the new
@ -469,6 +500,50 @@ BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
return buffer.forget();
}
TemporaryRef<DrawTarget>
BasicShadowableThebesLayer::CreateDrawTarget(const IntSize& aSize,
SurfaceFormat aFormat)
{
if (!HasShadow()) {
return BasicThebesLayer::CreateDrawTarget(aSize, aFormat);
}
MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): creating %d x %d buffer(x2)",
this,
aSize.width, aSize.height));
if (IsSurfaceDescriptorValid(mBackBuffer)) {
BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this),
mBackBuffer);
mBackBuffer = SurfaceDescriptor();
}
// XXX error handling
if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
mozilla::gfx::ContentForFormat(aFormat),
&mBackBuffer)) {
NS_RUNTIMEABORT("creating ThebesLayer 'back buffer' failed!");
}
NS_ABORT_IF_FALSE(!mIsNewBuffer,
"Bad! Did we create a buffer twice without painting?");
mIsNewBuffer = true;
mozilla::ipc::Shmem shm = mBackBuffer.get_Shmem();
if (!shm.IsWritable()) {
NS_RUNTIMEABORT("shmem not writable!");
return nullptr;
}
SharedImageInfo* shmInfo = gfxSharedImageSurface::GetShmInfoPtr(shm);
unsigned char* data = shm.get<unsigned char>();
int stride = gfxASurface::FormatStrideForWidth(
static_cast<gfxASurface::gfxImageFormat>(shmInfo->format), aSize.width);
return gfxPlatform::GetPlatform()->CreateDrawTargetForData(data, aSize, stride, aFormat);
}
void
BasicShadowableThebesLayer::Disconnect()
{

View File

@ -7,6 +7,7 @@
#define GFX_BASICTHEBESLAYER_H
#include "mozilla/layers/PLayersParent.h"
#include "mozilla/gfx/2D.h"
#include "BasicBuffers.h"
namespace mozilla {
@ -53,6 +54,11 @@ public:
virtual already_AddRefed<gfxASurface>
CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
virtual TemporaryRef<mozilla::gfx::DrawTarget>
CreateDrawTarget(const mozilla::gfx::IntSize& aSize,
mozilla::gfx::SurfaceFormat aFormat);
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
if (!BasicManager()->IsRetained()) {
@ -168,6 +174,11 @@ private:
virtual already_AddRefed<gfxASurface>
CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
virtual TemporaryRef<mozilla::gfx::DrawTarget>
CreateDrawTarget(const mozilla::gfx::IntSize& aSize,
mozilla::gfx::SurfaceFormat aFormat) MOZ_OVERRIDE;
void DestroyBackBuffer()
{
if (IsSurfaceDescriptorValid(mBackBuffer)) {

View File

@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "gfxASurface.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/PLayers.h"
#include "ShadowLayers.h"
@ -44,6 +45,8 @@ public:
/** This can't escape the scope of AutoOpenSurface. */
gfxASurface* Get();
mozilla::gfx::DrawTarget* GetDrawTarget();
/**
* This can't escape the scope of AutoOpenSurface.
*
@ -60,6 +63,7 @@ public:
private:
SurfaceDescriptor mDescriptor;
nsRefPtr<gfxASurface> mSurface;
RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
nsRefPtr<gfxImageSurface> mSurfaceAsImage;
OpenMode mMode;

View File

@ -486,6 +486,40 @@ ShadowLayerForwarder::OpenDescriptor(OpenMode aMode,
}
}
/*static*/ TemporaryRef<mozilla::gfx::DrawTarget>
ShadowLayerForwarder::OpenDescriptorForDrawTarget(OpenMode aMode,
const SurfaceDescriptor& aSurface)
{
switch (aSurface.type()) {
case SurfaceDescriptor::TShmem: {
mozilla::ipc::Shmem shm = aSurface.get_Shmem();
if (!shm.IsWritable()) {
NS_RUNTIMEABORT("shmem not writable!");
return nullptr;
}
SharedImageInfo* shmInfo = gfxSharedImageSurface::GetShmInfoPtr(shm);
unsigned char* data = shm.get<unsigned char>();
gfxASurface::gfxImageFormat imgFormat =
static_cast<gfxASurface::gfxImageFormat>(shmInfo->format);
mozilla::gfx::SurfaceFormat surfFormat =
mozilla::gfx::SurfaceFormatForImageFormat(imgFormat);
mozilla::gfx::IntSize size(shmInfo->width, shmInfo->height);
int stride = gfxASurface::FormatStrideForWidth(imgFormat, size.width);
return gfxPlatform::GetPlatform()->CreateDrawTargetForData(data, size,
stride, surfFormat);
}
default:
NS_RUNTIMEABORT("unexpected SurfaceDescriptor type!");
return nullptr;
}
}
/*static*/ gfxContentType
ShadowLayerForwarder::GetDescriptorSurfaceContentType(
const SurfaceDescriptor& aDescriptor, OpenMode aMode,
@ -710,6 +744,15 @@ AutoOpenSurface::Get()
return mSurface.get();
}
mozilla::gfx::DrawTarget*
AutoOpenSurface::GetDrawTarget()
{
if (!mDrawTarget) {
mDrawTarget = ShadowLayerForwarder::OpenDescriptorForDrawTarget(mMode, mDescriptor);
}
return mDrawTarget.get();
}
gfxImageSurface*
AutoOpenSurface::GetAsImage()
{

View File

@ -9,6 +9,7 @@
#define mozilla_layers_ShadowLayers_h 1
#include "gfxASurface.h"
#include "mozilla/gfx/2D.h"
#include "GLDefs.h"
#include "ImageLayers.h"
@ -368,6 +369,9 @@ private:
static already_AddRefed<gfxASurface>
OpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface);
static TemporaryRef<mozilla::gfx::DrawTarget>
OpenDescriptorForDrawTarget(OpenMode aMode, const SurfaceDescriptor& aSurface);
static already_AddRefed<gfxASurface>
PlatformOpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aDescriptor);

View File

@ -227,6 +227,40 @@ inline gfxASurface::gfxContentType ContentForFormat(const SurfaceFormat &aFormat
}
}
inline SurfaceFormat SurfaceFormatForImageFormat(const gfxASurface::gfxImageFormat &aImageFormat)
{
switch (aImageFormat) {
case gfxASurface::ImageFormatARGB32:
return FORMAT_B8G8R8A8;
case gfxASurface::ImageFormatRGB24:
return FORMAT_B8G8R8X8;
case gfxASurface::ImageFormatA8:
case gfxASurface::ImageFormatA1:
return FORMAT_A8;
case gfxASurface::ImageFormatRGB16_565:
return FORMAT_R5G6B5;
case gfxASurface::ImageFormatUnknown:
default:
return FORMAT_B8G8R8A8;
}
}
inline gfxASurface::gfxImageFormat ImageFormatForSurfaceFormat(const SurfaceFormat &aFormat)
{
switch (aFormat) {
case FORMAT_B8G8R8A8:
return gfxASurface::ImageFormatARGB32;
case FORMAT_B8G8R8X8:
return gfxASurface::ImageFormatRGB24;
case FORMAT_A8:
return gfxASurface::ImageFormatA8;
case FORMAT_R5G6B5:
return gfxASurface::ImageFormatRGB16_565;
default:
return gfxASurface::ImageFormatARGB32;
}
}
inline CompositionOp CompositionOpForOp(gfxContext::GraphicsOperator aOp)
{
switch (aOp) {