зеркало из https://github.com/mozilla/gecko-dev.git
Bug 740580 - Add support for Azure DrawTargets to BasicLayers. r=Bas
This commit is contained in:
Родитель
7ac726b395
Коммит
e9fe9ba610
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче