--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -59,28 +59,37 @@ const TextureFlags TEXTURE_TILE
// from the previous texture.
const TextureFlags TEXTURE_COPY_PREVIOUS = 1 << 24;
// Who is responsible for deallocating the shared data.
// if TEXTURE_DEALLOCATE_CLIENT is set, the shared data is deallocated on the
// client side and requires some extra synchronizaion to ensure race-free
// deallocation.
// The default behaviour is to deallocate on the host side.
const TextureFlags TEXTURE_DEALLOCATE_CLIENT = 1 << 25;
+// The host side is responsible for deallocation, but that may not happen
+// immediately after the client side requests it. Exactly when the texture is
+// deallocated is up to the compositable. The texture must be deallocated by
+// the time the compositable or texture host is destroyed. A texture may not
+// have both TEXTURE_DEALLOCATE_CLIENT and TEXTURE_DEALLOCATE_DEFERRED flags.
+const TextureFlags TEXTURE_DEALLOCATE_DEFERRED = 1 << 26;
// After being shared ith the compositor side, an immutable texture is never
// modified, it can only be read. It is safe to not Lock/Unlock immutable
// textures.
const TextureFlags TEXTURE_IMMUTABLE = 1 << 27;
// The contents of the texture must be uploaded or copied immediately
// during the transaction, because the producer may want to write
// to it again.
const TextureFlags TEXTURE_IMMEDIATE_UPLOAD = 1 << 28;
// The texture is going to be used as part of a double
// buffered pair, and so we can guarantee that the producer/consumer
// won't be racing to access its contents.
const TextureFlags TEXTURE_DOUBLE_BUFFERED = 1 << 29;
+// We've previously tried a texture and it didn't work for some reason. If there
+// is a fallback available, try that.
+const TextureFlags TEXTURE_ALLOC_FALLBACK = 1 << 31;
// the default flags
const TextureFlags TEXTURE_FLAGS_DEFAULT = TEXTURE_FRONT;
static inline bool
TextureRequiresLocking(TextureFlags aFlags)
{
// If we're not double buffered, or uploading
@@ -162,16 +171,18 @@ enum CompositableType
BUFFER_BRIDGE, // image bridge protocol
BUFFER_CONTENT, // thebes layer interface, single buffering
BUFFER_CONTENT_DIRECT, // thebes layer interface, double buffering
BUFFER_CONTENT_INC, // thebes layer interface, only sends incremental
// updates to a texture on the compositor side.
BUFFER_TILED, // tiled thebes layer
// the new compositable types
COMPOSITABLE_IMAGE, // image with single buffering
+ COMPOSITABLE_CONTENT_SINGLE, // thebes layer interface, single buffering
+ COMPOSITABLE_CONTENT_DOUBLE, // thebes layer interface, double buffering
BUFFER_COUNT
};
/**
* How the texture host is used for composition,
*/
enum DeprecatedTextureHostFlags
{
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -276,73 +276,82 @@ RotatedContentBuffer::GetContextForQuadr
}
return ctx.forget();
}
gfxContentType
RotatedContentBuffer::BufferContentType()
{
- if (mBufferProvider) {
- return mBufferProvider->GetContentType();
+ if (mDeprecatedBufferProvider) {
+ return mDeprecatedBufferProvider->GetContentType();
}
- if (mDTBuffer) {
- switch (mDTBuffer->GetFormat()) {
- case FORMAT_A8:
- return GFX_CONTENT_ALPHA;
- case FORMAT_B8G8R8A8:
- case FORMAT_R8G8B8A8:
- return GFX_CONTENT_COLOR_ALPHA;
- default:
- return GFX_CONTENT_COLOR;
+ if (mBufferProvider || mDTBuffer) {
+ SurfaceFormat format;
+
+ if (mBufferProvider) {
+ format = mBufferProvider->AsTextureClientDrawTarget()->GetFormat();
+ } else if (mDTBuffer) {
+ format = mDTBuffer->GetFormat();
}
+
+ return ContentForFormat(format);
}
return GFX_CONTENT_SENTINEL;
}
bool
RotatedContentBuffer::BufferSizeOkFor(const nsIntSize& aSize)
{
return (aSize == mBufferRect.Size() ||
(SizedToVisibleBounds != mBufferSizePolicy &&
aSize < mBufferRect.Size()));
}
bool
RotatedContentBuffer::EnsureBuffer()
{
- if (!mDTBuffer && mBufferProvider) {
- mDTBuffer = mBufferProvider->LockDrawTarget();
+ if (!mDTBuffer) {
+ if (mDeprecatedBufferProvider) {
+ mDTBuffer = mDeprecatedBufferProvider->LockDrawTarget();
+ } else if (mBufferProvider) {
+ mDTBuffer = mBufferProvider->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ }
}
NS_WARN_IF_FALSE(mDTBuffer, "no buffer");
return !!mDTBuffer;
}
bool
RotatedContentBuffer::EnsureBufferOnWhite()
{
- if (!mDTBufferOnWhite && mBufferProviderOnWhite) {
- mDTBufferOnWhite = mBufferProviderOnWhite->LockDrawTarget();
+ if (!mDTBufferOnWhite) {
+ if (mDeprecatedBufferProviderOnWhite) {
+ mDTBufferOnWhite = mDeprecatedBufferProviderOnWhite->LockDrawTarget();
+ } else if (mBufferProviderOnWhite) {
+ mDTBufferOnWhite =
+ mBufferProviderOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ }
}
NS_WARN_IF_FALSE(mDTBufferOnWhite, "no buffer");
return mDTBufferOnWhite;
}
bool
RotatedContentBuffer::HaveBuffer() const
{
- return mDTBuffer || mBufferProvider;
+ return mDTBuffer || mDeprecatedBufferProvider || mBufferProvider;
}
bool
RotatedContentBuffer::HaveBufferOnWhite() const
{
- return mDTBufferOnWhite || mBufferProviderOnWhite;
+ return mDTBufferOnWhite || mDeprecatedBufferProviderOnWhite || mBufferProviderOnWhite;
}
static void
WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
{
if (*aRotationPoint < 0) {
*aRotationPoint += aSize;
} else if (*aRotationPoint >= aSize) {
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -28,16 +28,17 @@ struct nsIntSize;
namespace mozilla {
namespace gfx {
class Matrix;
}
namespace layers {
class DeprecatedTextureClient;
+class TextureClient;
class ThebesLayer;
/**
* This is a cairo/Thebes surface, but with a literal twist. Scrolling
* causes the layer's visible region to move. We want to keep
* reusing the same surface if the region size hasn't changed, but we don't
* want to keep moving the contents of the surface around in memory. So
* we use a trick.
@@ -152,17 +153,19 @@ public:
* fit visible bounds. May be larger.
*/
enum BufferSizePolicy {
SizedToVisibleBounds,
ContainsVisibleBounds
};
RotatedContentBuffer(BufferSizePolicy aBufferSizePolicy)
- : mBufferProvider(nullptr)
+ : mDeprecatedBufferProvider(nullptr)
+ , mDeprecatedBufferProviderOnWhite(nullptr)
+ , mBufferProvider(nullptr)
, mBufferProviderOnWhite(nullptr)
, mBufferSizePolicy(aBufferSizePolicy)
{
MOZ_COUNT_CTOR(RotatedContentBuffer);
}
virtual ~RotatedContentBuffer()
{
MOZ_COUNT_DTOR(RotatedContentBuffer);
@@ -171,16 +174,18 @@ public:
/**
* Wipe out all retained contents. Call this when the entire
* buffer becomes invalid.
*/
void Clear()
{
mDTBuffer = nullptr;
mDTBufferOnWhite = nullptr;
+ mDeprecatedBufferProvider = nullptr;
+ mDeprecatedBufferProviderOnWhite = nullptr;
mBufferProvider = nullptr;
mBufferProviderOnWhite = nullptr;
mBufferRect.SetEmpty();
}
/**
* This is returned by BeginPaint. The caller should draw into mContext.
* mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
@@ -285,33 +290,58 @@ protected:
* demand in this code.
*
* It's the caller's responsibility to ensure |aClient| is valid
* for the duration of operations it requests of this
* RotatedContentBuffer. It's also the caller's responsibility to
* unset the provider when inactive, by calling
* SetBufferProvider(nullptr).
*/
- void SetBufferProvider(DeprecatedTextureClient* aClient)
+ void SetDeprecatedBufferProvider(DeprecatedTextureClient* aClient)
{
// Only this buffer provider can give us a buffer. If we
// already have one, something has gone wrong.
- MOZ_ASSERT(!aClient || !mDTBuffer);
+ MOZ_ASSERT((!aClient || !mDTBuffer) && !mBufferProvider);
+
+ mDeprecatedBufferProvider = aClient;
+ if (!mDeprecatedBufferProvider) {
+ mDTBuffer = nullptr;
+ }
+ }
+
+ void SetDeprecatedBufferProviderOnWhite(DeprecatedTextureClient* aClient)
+ {
+ // Only this buffer provider can give us a buffer. If we
+ // already have one, something has gone wrong.
+ MOZ_ASSERT((!aClient || !mDTBufferOnWhite) && !mBufferProviderOnWhite);
+
+ mDeprecatedBufferProviderOnWhite = aClient;
+ if (!mDeprecatedBufferProviderOnWhite) {
+ mDTBufferOnWhite = nullptr;
+ }
+ }
+
+ // new texture client versions
+ void SetBufferProvider(TextureClient* aClient)
+ {
+ // Only this buffer provider can give us a buffer. If we
+ // already have one, something has gone wrong.
+ MOZ_ASSERT((!aClient || !mDTBuffer) && !mDeprecatedBufferProvider);
mBufferProvider = aClient;
if (!mBufferProvider) {
mDTBuffer = nullptr;
- }
+ }
}
-
- void SetBufferProviderOnWhite(DeprecatedTextureClient* aClient)
+
+ void SetBufferProviderOnWhite(TextureClient* aClient)
{
// Only this buffer provider can give us a buffer. If we
// already have one, something has gone wrong.
- MOZ_ASSERT(!aClient || !mDTBufferOnWhite);
+ MOZ_ASSERT((!aClient || !mDTBufferOnWhite) && !mDeprecatedBufferProviderOnWhite);
mBufferProviderOnWhite = aClient;
if (!mBufferProviderOnWhite) {
mDTBufferOnWhite = nullptr;
}
}
/**
@@ -344,18 +374,20 @@ protected:
virtual bool HaveBuffer() const;
virtual bool HaveBufferOnWhite() const;
/**
* These members are only set transiently. They're used to map mDTBuffer
* when we're using surfaces that require explicit map/unmap. Only one
* may be used at a time.
*/
- DeprecatedTextureClient* mBufferProvider;
- DeprecatedTextureClient* mBufferProviderOnWhite;
+ DeprecatedTextureClient* mDeprecatedBufferProvider;
+ DeprecatedTextureClient* mDeprecatedBufferProviderOnWhite;
+ TextureClient* mBufferProvider;
+ TextureClient* mBufferProviderOnWhite;
BufferSizePolicy mBufferSizePolicy;
};
}
}
#endif /* ROTATEDBUFFER_H_ */
--- a/gfx/layers/client/ClientThebesLayer.cpp
+++ b/gfx/layers/client/ClientThebesLayer.cpp
@@ -101,16 +101,28 @@ ClientThebesLayer::RenderLayer()
mContentClient->Connect();
ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
MOZ_ASSERT(mContentClient->GetForwarder());
}
mContentClient->BeginPaint();
PaintThebes();
mContentClient->EndPaint();
+ // It is very important that this is called after EndPaint, because destroying
+ // textures is a three stage process:
+ // 1. We are done with the buffer and move it to ContentClient::mOldTextures,
+ // that happens in DestroyBuffers which is may be called indirectly from
+ // PaintThebes.
+ // 2. The content client calls RemoveTextureClient on the texture clients in
+ // mOldTextures and forgets them. They then become invalid. The compositable
+ // client keeps a record of IDs. This happens in EndPaint.
+ // 3. An IPC message is sent to destroy the corresponding texture host. That
+ // happens from OnTransaction.
+ // It is important that these steps happen in order.
+ mContentClient->OnTransaction();
}
void
ClientThebesLayer::PaintBuffer(gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aExtendedRegionToDraw,
const nsIntRegion& aRegionToInvalidate,
bool aDidSelfCopy, DrawRegionClip aClip)
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -10,18 +10,21 @@
#include "mozilla/layers/TextureClient.h" // for DeprecatedTextureClient, etc
#include "mozilla/layers/TextureClientOGL.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "gfxASurface.h" // for gfxContentType
#ifdef XP_WIN
#include "mozilla/layers/TextureD3D9.h"
#include "mozilla/layers/TextureD3D11.h"
#include "gfxWindowsPlatform.h"
+#include "gfx2DGlue.h"
#endif
+using namespace mozilla::gfx;
+
namespace mozilla {
namespace layers {
CompositableClient::CompositableClient(CompositableForwarder* aForwarder)
: mNextTextureID(1)
, mCompositableChild(nullptr)
, mForwarder(aForwarder)
{
@@ -188,18 +191,18 @@ CompositableClient::CreateDeprecatedText
MOZ_ASSERT(result->SupportsType(aDeprecatedTextureClientType),
"Created the wrong texture client?");
result->SetFlags(GetTextureInfo().mTextureFlags);
return result.forget();
}
TemporaryRef<BufferTextureClient>
-CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
- uint32_t aTextureFlags)
+CompositableClient::CreateBufferTextureClient(SurfaceFormat aFormat,
+ TextureFlags aTextureFlags)
{
// XXX - Once bug 908196 is fixed, we can use gralloc textures here which will
// improve performances of videos using SharedPlanarYCbCrImage on b2g.
//#ifdef MOZ_WIDGET_GONK
// {
// RefPtr<BufferTextureClient> result = new GrallocTextureClientOGL(this,
// aFormat,
// aTextureFlags);
@@ -209,25 +212,66 @@ CompositableClient::CreateBufferTextureC
if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
RefPtr<BufferTextureClient> result = new MemoryTextureClient(this, aFormat, aTextureFlags);
return result.forget();
}
RefPtr<BufferTextureClient> result = new ShmemTextureClient(this, aFormat, aTextureFlags);
return result.forget();
}
-bool
-CompositableClient::AddTextureClient(TextureClient* aClient)
+TemporaryRef<TextureClient>
+CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat,
+ TextureFlags aTextureFlags)
+{
+ RefPtr<TextureClient> result;
+
+#ifdef XP_WIN
+ LayersBackend parentBackend = GetForwarder()->GetCompositorBackendType();
+ // XXX[nrc] uncomment once we have new texture clients for windows
+ if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
+ !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
+ //result = new TextureClientD3D11(GetForwarder(), GetTextureInfo());
+ }
+ if (parentBackend == LAYERS_D3D9 &&
+ !GetForwarder()->ForwardsToDifferentProcess() &&
+ !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
+ // non-DIB textures don't work with alpha, see notes in TextureD3D9.
+ if (ContentForFormat(aFormat) == GFX_CONTENT_COLOR_ALPHA) {
+ //result = new TextureClientDIB(GetForwarder(), GetTextureInfo());
+ } else {
+ //result = new TextureClientD3D9(GetForwarder(), GetTextureInfo());
+ }
+ }
+#endif
+ // Can't do any better than a buffer texture client.
+ if (!result) {
+ result = CreateBufferTextureClient(aFormat, aTextureFlags);
+ }
+
+ MOZ_ASSERT(!result || result->AsTextureClientDrawTarget(),
+ "Not a TextureClientDrawTarget?");
+ return result;
+}
+
+uint64_t
+CompositableClient::NextTextureID()
{
++mNextTextureID;
// 0 is always an invalid ID
if (mNextTextureID == 0) {
++mNextTextureID;
}
- aClient->SetID(mNextTextureID);
+
+ return mNextTextureID;
+}
+
+bool
+CompositableClient::AddTextureClient(TextureClient* aClient)
+{
+ aClient->SetID(NextTextureID());
return mForwarder->AddTexture(this, aClient);
}
void
CompositableClient::RemoveTextureClient(TextureClient* aClient)
{
MOZ_ASSERT(aClient);
mTexturesToRemove.AppendElement(TextureIDAndFlags(aClient->GetID(),
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -83,16 +83,22 @@ public:
TemporaryRef<DeprecatedTextureClient>
CreateDeprecatedTextureClient(DeprecatedTextureClientType aDeprecatedTextureClientType,
gfxContentType aContentType = GFX_CONTENT_SENTINEL);
virtual TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+ // If we return a non-null TextureClient, then AsTextureClientDrawTarget will
+ // always be non-null.
+ TemporaryRef<TextureClient>
+ CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat,
+ TextureFlags aTextureFlags);
+
virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
const SurfaceDescriptor& aDescriptor)
{
MOZ_CRASH("If you want to call this, you should have implemented it");
}
/**
* Establishes the connection with compositor side through IPDL
@@ -163,16 +169,19 @@ public:
void FlushTexturesToRemoveCallbacks();
/**
* Our IPDL actor is being destroyed, get rid of any shmem resources now.
*/
virtual void OnActorDestroy() = 0;
protected:
+ // return the next texture ID
+ uint64_t NextTextureID();
+
struct TextureIDAndFlags {
TextureIDAndFlags(uint64_t aID, TextureFlags aFlags)
: mID(aID), mFlags(aFlags) {}
uint64_t mID;
TextureFlags mFlags;
};
// The textures to destroy in the next transaction;
nsTArray<TextureIDAndFlags> mTexturesToRemove;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -57,25 +57,32 @@ ContentClient::CreateContentClient(Compo
} else
#endif
{
useDoubleBuffering = LayerManagerComposite::SupportsDirectTexturing() ||
backend == LAYERS_BASIC;
}
if (useDoubleBuffering || PR_GetEnv("MOZ_FORCE_DOUBLE_BUFFERING")) {
- return new ContentClientDoubleBuffered(aForwarder);
+ if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+ return new DeprecatedContentClientDoubleBuffered(aForwarder);
+ } else {
+ return new ContentClientDoubleBuffered(aForwarder);
+ }
}
#ifdef XP_MACOSX
if (backend == LAYERS_OPENGL) {
return new ContentClientIncremental(aForwarder);
}
#endif
- return new ContentClientSingleBuffered(aForwarder);
-
+ if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+ return new DeprecatedContentClientSingleBuffered(aForwarder);
+ } else {
+ return new ContentClientSingleBuffered(aForwarder);
+ }
}
// We pass a null pointer for the ContentClient Forwarder argument, which means
// this client will not have a ContentHost on the other side.
ContentClientBasic::ContentClientBasic()
: ContentClient(nullptr)
, RotatedContentBuffer(ContainsVisibleBounds)
{}
@@ -95,61 +102,261 @@ ContentClientBasic::CreateBuffer(Content
*aBlackDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
IntSize(aRect.width, aRect.height),
ImageFormatToSurfaceFormat(format));
}
void
ContentClientRemoteBuffer::DestroyBuffers()
{
- if (!mDeprecatedTextureClient) {
+ if (!mTextureClient) {
return;
}
- MOZ_ASSERT(mDeprecatedTextureClient->GetAccessMode() == DeprecatedTextureClient::ACCESS_READ_WRITE);
- mDeprecatedTextureClient = nullptr;
- mDeprecatedTextureClientOnWhite = nullptr;
+ mOldTextures.AppendElement(mTextureClient);
+ mTextureClient = nullptr;
+ if (mTextureClientOnWhite) {
+ mOldTextures.AppendElement(mTextureClientOnWhite);
+ mTextureClientOnWhite = nullptr;
+ }
DestroyFrontBuffer();
-
- mForwarder->DestroyThebesBuffer(this);
}
void
ContentClientRemoteBuffer::BeginPaint()
{
// XXX: So we might not have a DeprecatedTextureClient yet.. because it will
// only be created by CreateBuffer.. which will deliver a locked surface!.
- if (mDeprecatedTextureClient) {
- SetBufferProvider(mDeprecatedTextureClient);
+ if (mTextureClient) {
+ SetBufferProvider(mTextureClient);
}
- if (mDeprecatedTextureClientOnWhite) {
- SetBufferProviderOnWhite(mDeprecatedTextureClientOnWhite);
+ if (mTextureClientOnWhite) {
+ SetBufferProviderOnWhite(mTextureClientOnWhite);
}
}
void
ContentClientRemoteBuffer::EndPaint()
{
// XXX: We might still not have a texture client if PaintThebes
// decided we didn't need one yet because the region to draw was empty.
SetBufferProvider(nullptr);
SetBufferProviderOnWhite(nullptr);
+ for (size_t i = 0; i < mOldTextures.Length(); ++i) {
+ RemoveTextureClient(mOldTextures[i]);
+ }
+ mOldTextures.Clear();
+
+ if (mTextureClient) {
+ mTextureClient->Unlock();
+ }
+ if (mTextureClientOnWhite) {
+ mTextureClientOnWhite->Unlock();
+ }
+}
+
+bool
+ContentClientRemoteBuffer::CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
+ TextureFlags aFlags)
+{
+ aClient = CreateTextureClientForDrawing(mSurfaceFormat,
+ mTextureInfo.mTextureFlags | aFlags);
+ if (!aClient) {
+ return false;
+ }
+
+ if (!aClient->AsTextureClientDrawTarget()->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) {
+ aClient = CreateTextureClientForDrawing(mSurfaceFormat,
+ mTextureInfo.mTextureFlags | TEXTURE_ALLOC_FALLBACK | aFlags);
+ if (!aClient) {
+ return false;
+ }
+ if (!aClient->AsTextureClientDrawTarget()->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) {
+ NS_WARNING("Could not allocate texture client");
+ aClient = nullptr;
+ return false;
+ }
+ }
+
+ NS_WARN_IF_FALSE(aClient->IsValid(), "Created an invalid texture client");
+ return true;
+}
+
+void
+ContentClientRemoteBuffer::BuildTextureClients(SurfaceFormat aFormat,
+ const nsIntRect& aRect,
+ uint32_t aFlags)
+{
+ // If we hit this assertion, then it might be due to an empty transaction
+ // followed by a real transaction. Our buffers should be created (but not
+ // painted in the empty transaction) and then painted (but not created) in the
+ // real transaction. That is kind of fragile, and this assert will catch
+ // circumstances where we screw that up, e.g., by unnecessarily recreating our
+ // buffers.
+ NS_ABORT_IF_FALSE(!mIsNewBuffer,
+ "Bad! Did we create a buffer twice without painting?");
+
+ mIsNewBuffer = true;
+
+ DestroyBuffers();
+
+ mSurfaceFormat = aFormat;
+ mSize = gfx::IntSize(aRect.width, aRect.height);
+ mTextureInfo.mTextureFlags = (aFlags & ~TEXTURE_DEALLOCATE_CLIENT) |
+ TEXTURE_DEALLOCATE_DEFERRED;
+
+ if (!CreateAndAllocateTextureClient(mTextureClient, TEXTURE_ON_BLACK) ||
+ !AddTextureClient(mTextureClient)) {
+ AbortTextureClientCreation();
+ return;
+ }
+
+ if (aFlags & BUFFER_COMPONENT_ALPHA) {
+ if (!CreateAndAllocateTextureClient(mTextureClientOnWhite, TEXTURE_ON_WHITE) ||
+ !AddTextureClient(mTextureClientOnWhite)) {
+ AbortTextureClientCreation();
+ return;
+ }
+ mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA;
+ }
+
+ CreateFrontBuffer(aRect);
+}
+
+void
+ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
+ const nsIntRect& aRect,
+ uint32_t aFlags,
+ RefPtr<gfx::DrawTarget>* aBlackDT,
+ RefPtr<gfx::DrawTarget>* aWhiteDT)
+{
+ BuildTextureClients(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aType), aRect, aFlags);
+ if (!mTextureClient) {
+ return;
+ }
+
+ *aBlackDT = mTextureClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ if (aFlags & BUFFER_COMPONENT_ALPHA) {
+ *aWhiteDT = mTextureClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ }
+}
+
+nsIntRegion
+ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
+ const nsIntRegion& aVisibleRegion,
+ bool aDidSelfCopy)
+{
+ nsIntRegion updatedRegion;
+ if (mIsNewBuffer || aDidSelfCopy) {
+ // A buffer reallocation clears both buffers. The front buffer has all the
+ // content by now, but the back buffer is still clear. Here, in effect, we
+ // are saying to copy all of the pixels of the front buffer to the back.
+ // Also when we self-copied in the buffer, the buffer space
+ // changes and some changed buffer content isn't reflected in the
+ // draw or invalidate region (on purpose!). When this happens, we
+ // need to read back the entire buffer too.
+ updatedRegion = aVisibleRegion;
+ mIsNewBuffer = false;
+ } else {
+ updatedRegion = aRegionToDraw;
+ }
+
+ NS_ASSERTION(BufferRect().Contains(aRegionToDraw.GetBounds()),
+ "Update outside of buffer rect!");
+ NS_ABORT_IF_FALSE(mTextureClient, "should have a back buffer by now");
+
+ return updatedRegion;
+}
+
+void
+ContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
+ const nsIntRegion& aVisibleRegion,
+ bool aDidSelfCopy)
+{
+ nsIntRegion updatedRegion = GetUpdatedRegion(aRegionToDraw,
+ aVisibleRegion,
+ aDidSelfCopy);
+
+ MOZ_ASSERT(mTextureClient);
+ mForwarder->UseTexture(this, mTextureClient);
+ mForwarder->UpdateTextureRegion(this,
+ ThebesBufferData(BufferRect(),
+ BufferRotation()),
+ updatedRegion);
+}
+
+void
+ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+{
+ MOZ_ASSERT(mTextureClient);
+ mFrontAndBackBufferDiffer = true;
+}
+
+void
+ContentClientRemoteBuffer::OnActorDestroy()
+{
+ if (mTextureClient) {
+ mTextureClient->OnActorDestroy();
+ }
+ if (mTextureClientOnWhite) {
+ mTextureClientOnWhite->OnActorDestroy();
+ }
+ for (size_t i = 0; i < mOldTextures.Length(); ++i) {
+ mOldTextures[i]->OnActorDestroy();
+ }
+}
+
+void
+DeprecatedContentClientRemoteBuffer::DestroyBuffers()
+{
+ if (!mDeprecatedTextureClient) {
+ return;
+ }
+
+ mDeprecatedTextureClient = nullptr;
+ mDeprecatedTextureClientOnWhite = nullptr;
+
+ DestroyFrontBuffer();
+
+ mForwarder->DestroyThebesBuffer(this);
+}
+
+void
+DeprecatedContentClientRemoteBuffer::BeginPaint()
+{
+ // XXX: So we might not have a DeprecatedTextureClient yet.. because it will
+ // only be created by CreateBuffer.. which will deliver a locked surface!.
+ if (mDeprecatedTextureClient) {
+ SetDeprecatedBufferProvider(mDeprecatedTextureClient);
+ }
+ if (mDeprecatedTextureClientOnWhite) {
+ SetDeprecatedBufferProviderOnWhite(mDeprecatedTextureClientOnWhite);
+ }
+}
+
+void
+DeprecatedContentClientRemoteBuffer::EndPaint()
+{
+ // XXX: We might still not have a texture client if PaintThebes
+ // decided we didn't need one yet because the region to draw was empty.
+ SetDeprecatedBufferProvider(nullptr);
+ SetDeprecatedBufferProviderOnWhite(nullptr);
mOldTextures.Clear();
if (mDeprecatedTextureClient) {
mDeprecatedTextureClient->Unlock();
}
if (mDeprecatedTextureClientOnWhite) {
mDeprecatedTextureClientOnWhite->Unlock();
}
}
bool
-ContentClientRemoteBuffer::CreateAndAllocateDeprecatedTextureClient(RefPtr<DeprecatedTextureClient>& aClient)
+DeprecatedContentClientRemoteBuffer::CreateAndAllocateDeprecatedTextureClient(RefPtr<DeprecatedTextureClient>& aClient)
{
aClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT, mContentType);
MOZ_ASSERT(aClient, "Failed to create texture client");
if (!aClient->EnsureAllocated(mSize, mContentType)) {
aClient = CreateDeprecatedTextureClient(TEXTURE_FALLBACK, mContentType);
MOZ_ASSERT(aClient, "Failed to create texture client");
if (!aClient->EnsureAllocated(mSize, mContentType)) {
@@ -160,17 +367,17 @@ ContentClientRemoteBuffer::CreateAndAllo
}
}
MOZ_ASSERT(IsSurfaceDescriptorValid(*aClient->GetDescriptor()));
return true;
}
void
-ContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType aType,
+DeprecatedContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType aType,
const nsIntRect& aRect,
uint32_t aFlags)
{
NS_ABORT_IF_FALSE(!mIsNewBuffer,
"Bad! Did we create a buffer twice without painting?");
if (mDeprecatedTextureClient) {
mOldTextures.AppendElement(mDeprecatedTextureClient);
@@ -197,17 +404,17 @@ ContentClientRemoteBuffer::BuildDeprecat
mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA;
}
CreateFrontBufferAndNotify(aRect);
mIsNewBuffer = true;
}
void
-ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
+DeprecatedContentClientRemoteBuffer::CreateBuffer(ContentType aType,
const nsIntRect& aRect,
uint32_t aFlags,
RefPtr<gfx::DrawTarget>* aBlackDT,
RefPtr<gfx::DrawTarget>* aWhiteDT)
{
BuildDeprecatedTextureClients(aType, aRect, aFlags);
if (!mDeprecatedTextureClient) {
return;
@@ -217,17 +424,17 @@ ContentClientRemoteBuffer::CreateBuffer(
mDeprecatedTextureClient->BackendType()));
*aBlackDT = mDeprecatedTextureClient->LockDrawTarget();
if (aFlags & BUFFER_COMPONENT_ALPHA) {
*aWhiteDT = mDeprecatedTextureClientOnWhite->LockDrawTarget();
}
}
nsIntRegion
-ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
+DeprecatedContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,
bool aDidSelfCopy)
{
nsIntRegion updatedRegion;
if (mIsNewBuffer || aDidSelfCopy) {
// A buffer reallocation clears both buffers. The front buffer has all the
// content by now, but the back buffer is still clear. Here, in effect, we
// are saying to copy all of the pixels of the front buffer to the back.
@@ -244,17 +451,17 @@ ContentClientRemoteBuffer::GetUpdatedReg
NS_ASSERTION(BufferRect().Contains(aRegionToDraw.GetBounds()),
"Update outside of buffer rect!");
NS_ABORT_IF_FALSE(mDeprecatedTextureClient, "should have a back buffer by now");
return updatedRegion;
}
void
-ContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
+DeprecatedContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,
bool aDidSelfCopy)
{
nsIntRegion updatedRegion = GetUpdatedRegion(aRegionToDraw,
aVisibleRegion,
aDidSelfCopy);
MOZ_ASSERT(mDeprecatedTextureClient);
@@ -265,60 +472,234 @@ ContentClientRemoteBuffer::Updated(const
LockFrontBuffer();
mForwarder->UpdateTextureRegion(this,
ThebesBufferData(BufferRect(),
BufferRotation()),
updatedRegion);
}
void
-ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+DeprecatedContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
{
MOZ_ASSERT(mDeprecatedTextureClient->GetAccessMode() == DeprecatedTextureClient::ACCESS_NONE);
MOZ_ASSERT(!mDeprecatedTextureClientOnWhite || mDeprecatedTextureClientOnWhite->GetAccessMode() == DeprecatedTextureClient::ACCESS_NONE);
MOZ_ASSERT(mDeprecatedTextureClient);
mFrontAndBackBufferDiffer = true;
mDeprecatedTextureClient->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_WRITE);
if (mDeprecatedTextureClientOnWhite) {
mDeprecatedTextureClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_WRITE);
}
}
void
-ContentClientRemoteBuffer::OnActorDestroy()
+DeprecatedContentClientRemoteBuffer::OnActorDestroy()
{
if (mDeprecatedTextureClient) {
mDeprecatedTextureClient->OnActorDestroy();
}
if (mDeprecatedTextureClientOnWhite) {
mDeprecatedTextureClientOnWhite->OnActorDestroy();
}
for (size_t i = 0; i < mOldTextures.Length(); ++i) {
mOldTextures[i]->OnActorDestroy();
}
}
+
+void
+ContentClientDoubleBuffered::CreateFrontBuffer(const nsIntRect& aBufferRect)
+{
+ if (!CreateAndAllocateTextureClient(mFrontClient, TEXTURE_ON_BLACK) ||
+ !AddTextureClient(mFrontClient)) {
+ AbortTextureClientCreation();
+ return;
+ }
+ if (mTextureInfo.mTextureFlags & TEXTURE_COMPONENT_ALPHA) {
+ if (!CreateAndAllocateTextureClient(mFrontClientOnWhite, TEXTURE_ON_WHITE) ||
+ !AddTextureClient(mFrontClientOnWhite)) {
+ AbortTextureClientCreation();
+ return;
+ }
+ }
-ContentClientDoubleBuffered::~ContentClientDoubleBuffered()
+ mFrontBufferRect = aBufferRect;
+ mFrontBufferRotation = nsIntPoint();
+}
+
+void
+ContentClientDoubleBuffered::DestroyFrontBuffer()
+{
+ MOZ_ASSERT(mFrontClient);
+
+ mOldTextures.AppendElement(mFrontClient);
+ mFrontClient = nullptr;
+ if (mFrontClientOnWhite) {
+ mOldTextures.AppendElement(mFrontClientOnWhite);
+ mFrontClientOnWhite = nullptr;
+ }
+}
+
+void
+ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+{
+ mFrontUpdatedRegion = aFrontUpdatedRegion;
+
+ RefPtr<TextureClient> oldBack = mTextureClient;
+ mTextureClient = mFrontClient;
+ mFrontClient = oldBack;
+
+ oldBack = mTextureClientOnWhite;
+ mTextureClientOnWhite = mFrontClientOnWhite;
+ mFrontClientOnWhite = oldBack;
+
+ nsIntRect oldBufferRect = mBufferRect;
+ mBufferRect = mFrontBufferRect;
+ mFrontBufferRect = oldBufferRect;
+
+ nsIntPoint oldBufferRotation = mBufferRotation;
+ mBufferRotation = mFrontBufferRotation;
+ mFrontBufferRotation = oldBufferRotation;
+
+ MOZ_ASSERT(mFrontClient);
+
+ ContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
+}
+
+void
+ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
+{
+ if (!mFrontAndBackBufferDiffer) {
+ return;
+ }
+ MOZ_ASSERT(mFrontClient);
+
+ MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
+ this,
+ mFrontUpdatedRegion.GetBounds().x,
+ mFrontUpdatedRegion.GetBounds().y,
+ mFrontUpdatedRegion.GetBounds().width,
+ mFrontUpdatedRegion.GetBounds().height));
+
+ nsIntRegion updateRegion = mFrontUpdatedRegion;
+
+ // This is a tricky trade off, we're going to get stuff out of our
+ // frontbuffer now, but the next PaintThebes might throw it all (or mostly)
+ // away if the visible region has changed. This is why in reality we want
+ // this code integrated with PaintThebes to always do the optimal thing.
+
+ if (mDidSelfCopy) {
+ mDidSelfCopy = false;
+ // We can't easily draw our front buffer into us, since we're going to be
+ // copying stuff around anyway it's easiest if we just move our situation
+ // to non-rotated while we're at it. If this situation occurs we'll have
+ // hit a self-copy path in PaintThebes before as well anyway.
+ mBufferRect.MoveTo(mFrontBufferRect.TopLeft());
+ mBufferRotation = nsIntPoint();
+ updateRegion = mBufferRect;
+ } else {
+ mBufferRect = mFrontBufferRect;
+ mBufferRotation = mFrontBufferRotation;
+ }
+
+ mIsNewBuffer = false;
+ mFrontAndBackBufferDiffer = false;
+
+ // We need to ensure that we lock these two buffers in the same
+ // order as the compositor to prevent deadlocks.
+ if (!mFrontClient->Lock(OPEN_READ_ONLY)) {
+ return;
+ }
+ if (mFrontClientOnWhite &&
+ !mFrontClientOnWhite->Lock(OPEN_READ_ONLY)) {
+ mFrontClient->Unlock();
+ return;
+ }
+ RefPtr<DrawTarget> dt =
+ mFrontClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ RefPtr<DrawTarget> dtOnWhite = mFrontClientOnWhite
+ ? mFrontClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget()
+ : nullptr;
+ RotatedBuffer frontBuffer(dt,
+ dtOnWhite,
+ mFrontBufferRect,
+ mFrontBufferRotation);
+ UpdateDestinationFrom(frontBuffer, updateRegion);
+ mFrontClient->Unlock();
+ if (mFrontClientOnWhite) {
+ mFrontClientOnWhite->Unlock();
+ }
+}
+
+void
+ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
+ const nsIntRegion& aUpdateRegion)
+{
+ nsRefPtr<gfxContext> destCtx =
+ GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
+ destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+
+ bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
+ if (isClippingCheap) {
+ gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
+ }
+
+ aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK, 1.0, OP_SOURCE);
+
+ if (aSource.HaveBufferOnWhite()) {
+ MOZ_ASSERT(HaveBufferOnWhite());
+ nsRefPtr<gfxContext> destCtx =
+ GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
+ destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+
+ bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
+ if (isClippingCheap) {
+ gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
+ }
+
+ aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
+ }
+}
+
+void
+ContentClientDoubleBuffered::OnActorDestroy()
+{
+ if (mTextureClient) {
+ mTextureClient->OnActorDestroy();
+ }
+ if (mTextureClientOnWhite) {
+ mTextureClientOnWhite->OnActorDestroy();
+ }
+ for (size_t i = 0; i < mOldTextures.Length(); ++i) {
+ mOldTextures[i]->OnActorDestroy();
+ }
+ if (mFrontClient) {
+ mFrontClient->OnActorDestroy();
+ }
+ if (mFrontClientOnWhite) {
+ mFrontClientOnWhite->OnActorDestroy();
+ }
+}
+
+DeprecatedContentClientDoubleBuffered::~DeprecatedContentClientDoubleBuffered()
{
if (mDeprecatedTextureClient) {
MOZ_ASSERT(mFrontClient);
mDeprecatedTextureClient->SetDescriptor(SurfaceDescriptor());
mFrontClient->SetDescriptor(SurfaceDescriptor());
}
if (mDeprecatedTextureClientOnWhite) {
MOZ_ASSERT(mFrontClientOnWhite);
mDeprecatedTextureClientOnWhite->SetDescriptor(SurfaceDescriptor());
mFrontClientOnWhite->SetDescriptor(SurfaceDescriptor());
}
}
void
-ContentClientDoubleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
+DeprecatedContentClientDoubleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
{
if (!CreateAndAllocateDeprecatedTextureClient(mFrontClient)) {
mDeprecatedTextureClient->SetFlags(0);
mDeprecatedTextureClient = nullptr;
if (mDeprecatedTextureClientOnWhite) {
mDeprecatedTextureClientOnWhite->SetFlags(0);
mDeprecatedTextureClientOnWhite = nullptr;
}
@@ -344,37 +725,37 @@ ContentClientDoubleBuffered::CreateFront
*mFrontClient->LockSurfaceDescriptor(),
*mDeprecatedTextureClient->LockSurfaceDescriptor(),
mTextureInfo,
mFrontClientOnWhite ? mFrontClientOnWhite->LockSurfaceDescriptor() : nullptr,
mDeprecatedTextureClientOnWhite ? mDeprecatedTextureClientOnWhite->LockSurfaceDescriptor() : nullptr);
}
void
-ContentClientDoubleBuffered::DestroyFrontBuffer()
+DeprecatedContentClientDoubleBuffered::DestroyFrontBuffer()
{
MOZ_ASSERT(mFrontClient);
MOZ_ASSERT(mFrontClient->GetAccessMode() != DeprecatedTextureClient::ACCESS_NONE);
mFrontClient = nullptr;
mFrontClientOnWhite = nullptr;
}
void
-ContentClientDoubleBuffered::LockFrontBuffer()
+DeprecatedContentClientDoubleBuffered::LockFrontBuffer()
{
MOZ_ASSERT(mFrontClient);
mFrontClient->SetAccessMode(DeprecatedTextureClient::ACCESS_NONE);
if (mFrontClientOnWhite) {
mFrontClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_NONE);
}
}
void
-ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+DeprecatedContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
{
mFrontUpdatedRegion = aFrontUpdatedRegion;
RefPtr<DeprecatedTextureClient> oldBack = mDeprecatedTextureClient;
mDeprecatedTextureClient = mFrontClient;
mFrontClient = oldBack;
oldBack = mDeprecatedTextureClientOnWhite;
@@ -390,21 +771,21 @@ ContentClientDoubleBuffered::SwapBuffers
mFrontBufferRotation = oldBufferRotation;
MOZ_ASSERT(mFrontClient);
mFrontClient->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_ONLY);
if (mFrontClientOnWhite) {
mFrontClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_ONLY);
}
- ContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
+ DeprecatedContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
}
void
-ContentClientDoubleBuffered::OnActorDestroy()
+DeprecatedContentClientDoubleBuffered::OnActorDestroy()
{
if (mDeprecatedTextureClient) {
mDeprecatedTextureClient->OnActorDestroy();
}
if (mDeprecatedTextureClientOnWhite) {
mDeprecatedTextureClientOnWhite->OnActorDestroy();
}
for (size_t i = 0; i < mOldTextures.Length(); ++i) {
@@ -437,17 +818,17 @@ struct AutoDeprecatedTextureClient {
}
return nullptr;
}
private:
DeprecatedTextureClient* mTexture;
};
void
-ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
+DeprecatedContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
{
mIsNewBuffer = false;
if (!mFrontAndBackBufferDiffer) {
return;
}
MOZ_ASSERT(mFrontClient);
MOZ_ASSERT(mFrontClient->GetAccessMode() == DeprecatedTextureClient::ACCESS_READ_ONLY);
@@ -493,17 +874,17 @@ ContentClientDoubleBuffered::SyncFrontBu
mFrontBufferRect,
mFrontBufferRotation);
UpdateDestinationFrom(frontBuffer, updateRegion);
mFrontAndBackBufferDiffer = false;
}
void
-ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
+DeprecatedContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
const nsIntRegion& aUpdateRegion)
{
nsRefPtr<gfxContext> destCtx =
GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
if (!destCtx) {
return;
}
destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
@@ -525,37 +906,65 @@ ContentClientDoubleBuffered::UpdateDesti
if (isClippingCheap) {
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
}
}
-ContentClientSingleBuffered::~ContentClientSingleBuffered()
+void
+ContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
+{
+ if (!mFrontAndBackBufferDiffer) {
+ return;
+ }
+
+ RefPtr<DrawTarget> backBuffer = GetDTBuffer();
+ if (!backBuffer && mTextureClient) {
+ backBuffer = mTextureClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ }
+
+ RefPtr<DrawTarget> oldBuffer;
+ oldBuffer = SetDTBuffer(backBuffer,
+ mBufferRect,
+ mBufferRotation);
+
+ backBuffer = GetDTBufferOnWhite();
+ if (!backBuffer && mTextureClientOnWhite) {
+ backBuffer = mTextureClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
+ }
+
+ oldBuffer = SetDTBufferOnWhite(backBuffer);
+
+ mIsNewBuffer = false;
+ mFrontAndBackBufferDiffer = false;
+}
+
+DeprecatedContentClientSingleBuffered::~DeprecatedContentClientSingleBuffered()
{
if (mDeprecatedTextureClient) {
mDeprecatedTextureClient->SetDescriptor(SurfaceDescriptor());
}
if (mDeprecatedTextureClientOnWhite) {
mDeprecatedTextureClientOnWhite->SetDescriptor(SurfaceDescriptor());
}
}
void
-ContentClientSingleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
+DeprecatedContentClientSingleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
{
mForwarder->CreatedSingleBuffer(this,
*mDeprecatedTextureClient->LockSurfaceDescriptor(),
mTextureInfo,
mDeprecatedTextureClientOnWhite ? mDeprecatedTextureClientOnWhite->LockSurfaceDescriptor() : nullptr);
}
void
-ContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
+DeprecatedContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
{
mIsNewBuffer = false;
if (!mFrontAndBackBufferDiffer) {
return;
}
mFrontAndBackBufferDiffer = false;
DrawTarget* backBuffer = GetDTBuffer();
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -173,25 +173,127 @@ public:
* compositing side with the create message (send from CreateBuffer) which
* tells the compositor that TextureClients have been created and that the
* compositor should assign the corresponding TextureHosts to our corresponding
* ContentHost.
*
* If the size or type of our buffer(s) change(s), then we simply destroy and
* create them.
*/
+// Version using new texture clients
class ContentClientRemoteBuffer : public ContentClientRemote
, protected RotatedContentBuffer
{
using RotatedContentBuffer::BufferRect;
using RotatedContentBuffer::BufferRotation;
public:
ContentClientRemoteBuffer(CompositableForwarder* aForwarder)
: ContentClientRemote(aForwarder)
, RotatedContentBuffer(ContainsVisibleBounds)
+ , mIsNewBuffer(false)
+ , mFrontAndBackBufferDiffer(false)
+ , mSurfaceFormat(gfx::FORMAT_B8G8R8A8)
+ {}
+
+ typedef RotatedContentBuffer::PaintState PaintState;
+ typedef RotatedContentBuffer::ContentType ContentType;
+
+ virtual void Clear() { RotatedContentBuffer::Clear(); }
+ PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
+ uint32_t aFlags)
+ {
+ return RotatedContentBuffer::BeginPaint(aLayer, aContentType, aFlags);
+ }
+
+ /**
+ * Begin/End Paint map a gfxASurface from the texture client
+ * into the buffer of RotatedBuffer. The surface is only
+ * valid when the texture client is locked, so is mapped out
+ * of RotatedContentBuffer when we are done painting.
+ * None of the underlying buffer attributes (rect, rotation)
+ * are affected by mapping/unmapping.
+ */
+ virtual void BeginPaint() MOZ_OVERRIDE;
+ virtual void EndPaint() MOZ_OVERRIDE;
+
+ virtual void Updated(const nsIntRegion& aRegionToDraw,
+ const nsIntRegion& aVisibleRegion,
+ bool aDidSelfCopy);
+
+ virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
+
+ // Expose these protected methods from the superclass.
+ virtual const nsIntRect& BufferRect() const
+ {
+ return RotatedContentBuffer::BufferRect();
+ }
+ virtual const nsIntPoint& BufferRotation() const
+ {
+ return RotatedContentBuffer::BufferRotation();
+ }
+
+ virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
+ RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
+
+ virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
+ {
+ return mTextureInfo;
+ }
+
+ virtual void OnActorDestroy() MOZ_OVERRIDE;
+
+protected:
+ void DestroyBuffers();
+
+ virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
+ const nsIntRegion& aVisibleRegion,
+ bool aDidSelfCopy);
+
+ void BuildTextureClients(gfx::SurfaceFormat aFormat,
+ const nsIntRect& aRect,
+ uint32_t aFlags);
+
+ // Create the front buffer for the ContentClient/Host pair if necessary
+ // and notify the compositor that we have created the buffer(s).
+ virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) = 0;
+ virtual void DestroyFrontBuffer() {}
+
+ bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
+ TextureFlags aFlags = 0);
+
+ virtual void AbortTextureClientCreation()
+ {
+ mTextureClient = nullptr;
+ mTextureClientOnWhite = nullptr;
+ mIsNewBuffer = false;
+ }
+
+ RefPtr<TextureClient> mTextureClient;
+ RefPtr<TextureClient> mTextureClientOnWhite;
+ // keep a record of texture clients we have created and need to keep around
+ // (for RotatedBuffer to access), then unlock and remove them when we are done
+ // painting.
+ nsTArray<RefPtr<TextureClient> > mOldTextures;
+
+ TextureInfo mTextureInfo;
+ bool mIsNewBuffer;
+ bool mFrontAndBackBufferDiffer;
+ gfx::IntSize mSize;
+ gfx::SurfaceFormat mSurfaceFormat;
+};
+
+class DeprecatedContentClientRemoteBuffer : public ContentClientRemote
+ , protected RotatedContentBuffer
+{
+ using RotatedContentBuffer::BufferRect;
+ using RotatedContentBuffer::BufferRotation;
+public:
+ DeprecatedContentClientRemoteBuffer(CompositableForwarder* aForwarder)
+ : ContentClientRemote(aForwarder)
+ , RotatedContentBuffer(ContainsVisibleBounds)
, mDeprecatedTextureClient(nullptr)
, mIsNewBuffer(false)
, mFrontAndBackBufferDiffer(false)
, mContentType(GFX_CONTENT_COLOR_ALPHA)
{}
typedef RotatedContentBuffer::PaintState PaintState;
typedef RotatedContentBuffer::ContentType ContentType;
@@ -228,26 +330,26 @@ public:
virtual const nsIntPoint& BufferRotation() const
{
return RotatedContentBuffer::BufferRotation();
}
virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
- void DestroyBuffers();
-
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
{
return mTextureInfo;
}
virtual void OnActorDestroy() MOZ_OVERRIDE;
protected:
+ void DestroyBuffers();
+
virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,
bool aDidSelfCopy);
// create and configure mDeprecatedTextureClient
void BuildDeprecatedTextureClients(ContentType aType,
const nsIntRect& aRect,
uint32_t aFlags);
@@ -287,31 +389,70 @@ protected:
* (in SwapBuffers).
*/
class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
{
public:
ContentClientDoubleBuffered(CompositableForwarder* aFwd)
: ContentClientRemoteBuffer(aFwd)
{
- mTextureInfo.mCompositableType = BUFFER_CONTENT_DIRECT;
+ mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE;
}
- ~ContentClientDoubleBuffered();
+ virtual ~ContentClientDoubleBuffered() {}
virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
+ virtual void OnActorDestroy() MOZ_OVERRIDE;
+
+protected:
+ virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
+ virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
+
+private:
+ void UpdateDestinationFrom(const RotatedBuffer& aSource,
+ const nsIntRegion& aUpdateRegion);
+
+ virtual void AbortTextureClientCreation() MOZ_OVERRIDE
+ {
+ mTextureClient = nullptr;
+ mTextureClientOnWhite = nullptr;
+ mFrontClient = nullptr;
+ mFrontClientOnWhite = nullptr;
+ }
+
+ RefPtr<TextureClient> mFrontClient;
+ RefPtr<TextureClient> mFrontClientOnWhite;
+ nsIntRegion mFrontUpdatedRegion;
+ nsIntRect mFrontBufferRect;
+ nsIntPoint mFrontBufferRotation;
+};
+
+class DeprecatedContentClientDoubleBuffered : public DeprecatedContentClientRemoteBuffer
+{
+public:
+ DeprecatedContentClientDoubleBuffered(CompositableForwarder* aFwd)
+ : DeprecatedContentClientRemoteBuffer(aFwd)
+ {
+ mTextureInfo.mCompositableType = BUFFER_CONTENT_DIRECT;
+ }
+ ~DeprecatedContentClientDoubleBuffered();
+
+ virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
+
+ virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
+
+ virtual void OnActorDestroy() MOZ_OVERRIDE;
+
protected:
virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
virtual void LockFrontBuffer() MOZ_OVERRIDE;
- virtual void OnActorDestroy() MOZ_OVERRIDE;
-
private:
void UpdateDestinationFrom(const RotatedBuffer& aSource,
const nsIntRegion& aUpdateRegion);
RefPtr<DeprecatedTextureClient> mFrontClient;
RefPtr<DeprecatedTextureClient> mFrontClientOnWhite;
nsIntRegion mFrontUpdatedRegion;
nsIntRect mFrontBufferRect;
@@ -327,19 +468,35 @@ private:
* the compositor.
*/
class ContentClientSingleBuffered : public ContentClientRemoteBuffer
{
public:
ContentClientSingleBuffered(CompositableForwarder* aFwd)
: ContentClientRemoteBuffer(aFwd)
{
+ mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_SINGLE;
+ }
+ virtual ~ContentClientSingleBuffered() {}
+
+ virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
+
+protected:
+ virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE {}
+};
+
+class DeprecatedContentClientSingleBuffered : public DeprecatedContentClientRemoteBuffer
+{
+public:
+ DeprecatedContentClientSingleBuffered(CompositableForwarder* aFwd)
+ : DeprecatedContentClientRemoteBuffer(aFwd)
+ {
mTextureInfo.mCompositableType = BUFFER_CONTENT;
}
- ~ContentClientSingleBuffered();
+ ~DeprecatedContentClientSingleBuffered();
virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
protected:
virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
};
/**
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -300,32 +300,50 @@ BufferTextureClient::GetAsSurface()
}
RefPtr<gfxImageSurface> surf = serializer.GetAsThebesSurface();
nsRefPtr<gfxASurface> result = surf.get();
return result.forget();
}
bool
-BufferTextureClient::AllocateForSurface(gfx::IntSize aSize)
+BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This textureClient cannot use YCbCr data");
int bufSize
= ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
if (!Allocate(bufSize)) {
return false;
}
+
+ if (aFlags & ALLOC_CLEAR_BUFFER) {
+ memset(GetBuffer(), 0, bufSize);
+ }
+
ImageDataSerializer serializer(GetBuffer());
serializer.InitializeBufferInfo(aSize, mFormat);
mSize = aSize;
return true;
}
+TemporaryRef<gfx::DrawTarget>
+BufferTextureClient::GetAsDrawTarget()
+{
+ MOZ_ASSERT(IsValid());
+
+ ImageDataSerializer serializer(GetBuffer());
+ if (!serializer.IsValid()) {
+ return nullptr;
+ }
+
+ return serializer.GetAsDrawTarget();
+}
+
bool
BufferTextureClient::UpdateYCbCr(const PlanarYCbCrData& aData)
{
MOZ_ASSERT(mFormat == gfx::FORMAT_YUV, "This textureClient can only use YCbCr data");
MOZ_ASSERT(!IsImmutable());
MOZ_ASSERT(IsValid());
MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -43,25 +43,57 @@ class Image;
/**
* TextureClient is the abstraction that allows us to share data between the
* content and the compositor side.
* TextureClient can also provide with some more "producer" facing APIs
* such as TextureClientSurface and TextureClientYCbCr, that can be queried
* using AsTextureCLientSurface(), etc.
*/
+enum TextureAllocationFlags {
+ ALLOC_DEFAULT = 0,
+ ALLOC_CLEAR_BUFFER = 1
+};
+
/**
* Interface for TextureClients that can be updated using a gfxASurface.
*/
class TextureClientSurface
{
public:
virtual bool UpdateSurface(gfxASurface* aSurface) = 0;
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
- virtual bool AllocateForSurface(gfx::IntSize aSize) = 0;
+ /**
+ * Allocates for a given surface size, taking into account the pixel format
+ * which is part of the state of the TextureClient.
+ *
+ * Does not clear the surface by default, clearing the surface can be done
+ * by passing the CLEAR_BUFFER flag.
+ */
+ virtual bool AllocateForSurface(gfx::IntSize aSize,
+ TextureAllocationFlags flags = ALLOC_DEFAULT) = 0;
+};
+
+/**
+ * Interface for TextureClients that can be updated using a DrawTarget.
+ */
+class TextureClientDrawTarget
+{
+public:
+ virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() = 0;
+ virtual gfx::SurfaceFormat GetFormat() const = 0;
+ /**
+ * Allocates for a given surface size, taking into account the pixel format
+ * which is part of the state of the TextureClient.
+ *
+ * Does not clear the surface by default, clearing the surface can be done
+ * by passing the CLEAR_BUFFER flag.
+ */
+ virtual bool AllocateForSurface(gfx::IntSize aSize,
+ TextureAllocationFlags flags = ALLOC_DEFAULT) = 0;
};
/**
* Interface for TextureClients that can be updated using YCbCr data.
*/
class TextureClientYCbCr
{
public:
@@ -119,16 +151,17 @@ public:
*/
class TextureClient : public AtomicRefCounted<TextureClient>
{
public:
TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
virtual ~TextureClient();
virtual TextureClientSurface* AsTextureClientSurface() { return nullptr; }
+ virtual TextureClientDrawTarget* AsTextureClientDrawTarget() { return nullptr; }
virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
/**
* Locks the shared data, allowing the caller to get access to it.
*
* Please always lock/unlock when accessing the shared data.
* If Lock() returns false, you should not attempt to access the shared data.
*/
@@ -235,17 +268,18 @@ protected:
/**
* TextureClient that wraps a random access buffer such as a Shmem or raw memory.
* This class must be inherited to implement the memory allocation and access bits.
* (see ShmemTextureClient and MemoryTextureClient)
*/
class BufferTextureClient : public TextureClient
, public TextureClientSurface
- , TextureClientYCbCr
+ , public TextureClientYCbCr
+ , public TextureClientDrawTarget
{
public:
BufferTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat,
TextureFlags aFlags);
virtual ~BufferTextureClient();
virtual bool IsAllocated() const = 0;
@@ -259,29 +293,36 @@ public:
// TextureClientSurface
virtual TextureClientSurface* AsTextureClientSurface() MOZ_OVERRIDE { return this; }
virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE;
virtual already_AddRefed<gfxASurface> GetAsSurface() MOZ_OVERRIDE;
- virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
+ virtual bool AllocateForSurface(gfx::IntSize aSize,
+ TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
+
+ // TextureClientDrawTarget
+
+ virtual TextureClientDrawTarget* AsTextureClientDrawTarget() MOZ_OVERRIDE { return this; }
+
+ virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE;
// TextureClientYCbCr
virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; }
virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) MOZ_OVERRIDE;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode) MOZ_OVERRIDE;
- gfx::SurfaceFormat GetFormat() const { return mFormat; }
+ virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
// XXX - Bug 908196 - Make Allocate(uint32_t) and GetBufferSize() protected.
// these two methods should only be called by methods of BufferTextureClient
// that are overridden in GrallocTextureClient (which does not implement the
// two methods below)
virtual bool Allocate(uint32_t aSize) = 0;
virtual size_t GetBufferSize() const = 0;
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -54,30 +54,29 @@ CompositableHost::AddTextureHost(Texture
"A texture is already present with this ID");
RefPtr<TextureHost> second = mFirstTexture;
mFirstTexture = aTexture;
aTexture->SetNextSibling(second);
aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
void
-CompositableHost::RemoveTextureHost(uint64_t aTextureID)
+CompositableHost::RemoveTextureHost(TextureHost* aTexture)
{
- if (mFirstTexture && mFirstTexture->GetID() == aTextureID) {
- RefPtr<TextureHost> toRemove = mFirstTexture;
+ uint64_t textureID = aTexture->GetID();
+ if (mFirstTexture && mFirstTexture->GetID() == textureID) {
mFirstTexture = mFirstTexture->GetNextSibling();
- toRemove->SetNextSibling(nullptr);
+ aTexture->SetNextSibling(nullptr);
}
RefPtr<TextureHost> it = mFirstTexture;
while (it) {
if (it->GetNextSibling() &&
- it->GetNextSibling()->GetID() == aTextureID) {
- RefPtr<TextureHost> toRemove = it->GetNextSibling();
+ it->GetNextSibling()->GetID() == textureID) {
it->SetNextSibling(it->GetNextSibling()->GetNextSibling());
- toRemove->SetNextSibling(nullptr);
+ aTexture->SetNextSibling(nullptr);
}
it = it->GetNextSibling();
}
if (!mFirstTexture && mBackendData) {
mBackendData->ClearData();
}
}
@@ -89,16 +88,25 @@ CompositableHost::GetTextureHost(uint64_
if (it->GetID() == aTextureID) {
return it;
}
it = it->GetNextSibling();
}
return nullptr;
}
+void
+CompositableHost::OnActorDestroy()
+{
+ TextureHost* it = mFirstTexture;
+ while (it) {
+ it->OnActorDestroy();
+ it = it->GetNextSibling();
+ }
+}
void
CompositableHost::SetCompositor(Compositor* aCompositor)
{
mCompositor = aCompositor;
RefPtr<TextureHost> it = mFirstTexture;
while (!!it) {
it->SetCompositor(aCompositor);
@@ -127,17 +135,17 @@ CompositableHost::AddMaskEffect(EffectCh
bool aIs3D)
{
RefPtr<TextureSource> source;
RefPtr<DeprecatedTextureHost> oldHost = GetDeprecatedTextureHost();
if (oldHost) {
oldHost->Lock();
source = oldHost;
} else {
- RefPtr<TextureHost> host = GetTextureHost();
+ RefPtr<TextureHost> host = GetAsTextureHost();
if (host) {
host->Lock();
source = host->GetTextureSources();
}
}
if (!source) {
NS_WARNING("Using compositable with no texture host as mask layer");
@@ -154,52 +162,61 @@ CompositableHost::AddMaskEffect(EffectCh
void
CompositableHost::RemoveMaskEffect()
{
RefPtr<DeprecatedTextureHost> oldHost = GetDeprecatedTextureHost();
if (oldHost) {
oldHost->Unlock();
} else {
- RefPtr<TextureHost> host = GetTextureHost();
+ RefPtr<TextureHost> host = GetAsTextureHost();
if (host) {
host->Unlock();
}
}
}
// implemented in TextureHostOGL.cpp
TemporaryRef<CompositableBackendSpecificData> CreateCompositableBackendSpecificDataOGL();
/* static */ TemporaryRef<CompositableHost>
CompositableHost::Create(const TextureInfo& aTextureInfo)
{
RefPtr<CompositableHost> result;
switch (aTextureInfo.mCompositableType) {
- case COMPOSITABLE_IMAGE:
- result = new ImageHost(aTextureInfo);
+ case BUFFER_IMAGE_SINGLE:
+ result = new DeprecatedImageHostSingle(aTextureInfo);
break;
case BUFFER_IMAGE_BUFFERED:
result = new DeprecatedImageHostBuffered(aTextureInfo);
break;
- case BUFFER_IMAGE_SINGLE:
- result = new DeprecatedImageHostSingle(aTextureInfo);
+ case BUFFER_BRIDGE:
+ MOZ_CRASH("Cannot create an image bridge compositable this way");
+ break;
+ case BUFFER_CONTENT:
+ result = new DeprecatedContentHostSingleBuffered(aTextureInfo);
+ break;
+ case BUFFER_CONTENT_DIRECT:
+ result = new DeprecatedContentHostDoubleBuffered(aTextureInfo);
+ break;
+ case BUFFER_CONTENT_INC:
+ result = new ContentHostIncremental(aTextureInfo);
break;
case BUFFER_TILED:
result = new TiledContentHost(aTextureInfo);
break;
- case BUFFER_CONTENT:
+ case COMPOSITABLE_IMAGE:
+ result = new ImageHost(aTextureInfo);
+ break;
+ case COMPOSITABLE_CONTENT_SINGLE:
result = new ContentHostSingleBuffered(aTextureInfo);
break;
- case BUFFER_CONTENT_DIRECT:
+ case COMPOSITABLE_CONTENT_DOUBLE:
result = new ContentHostDoubleBuffered(aTextureInfo);
break;
- case BUFFER_CONTENT_INC:
- result = new ContentHostIncremental(aTextureInfo);
- break;
default:
MOZ_CRASH("Unknown CompositableType");
}
if (result) {
RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
result->SetCompositableBackendSpecificData(data);
}
return result;
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -107,17 +107,17 @@ public:
{
mBackendData = aBackendData;
}
/**
* Our IPDL actor is being destroyed, get rid of any shmem resources now and
* don't worry about compositing anymore.
*/
- virtual void OnActorDestroy() = 0;
+ virtual void OnActorDestroy();
// If base class overrides, it should still call the parent implementation
virtual void SetCompositor(Compositor* aCompositor);
// composite the contents of this buffer host to the compositor's surface
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
@@ -206,17 +206,17 @@ public:
MOZ_ASSERT(false, "should be implemented or not used");
}
virtual DeprecatedTextureHost* GetDeprecatedTextureHost() { return nullptr; }
/**
* Returns the front buffer.
*/
- virtual TextureHost* GetTextureHost() { return nullptr; }
+ virtual TextureHost* GetAsTextureHost() { return nullptr; }
virtual LayerRenderState GetRenderState() = 0;
virtual void SetPictureRect(const nsIntRect& aPictureRect)
{
MOZ_ASSERT(false, "Should have been overridden");
}
@@ -291,17 +291,23 @@ public:
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
#endif
virtual void PrintInfo(nsACString& aTo, const char* aPrefix) { }
void AddTextureHost(TextureHost* aTexture);
virtual void UseTextureHost(TextureHost* aTexture) {}
- virtual void RemoveTextureHost(uint64_t aTextureID);
+ // If a texture host is flagged for deferred removal, the compositable will
+ // get an option to run any cleanup code early, that is when it would have
+ // been run if the texture host was not marked deferred.
+ // If the compositable does not cleanup the texture host now, it is the
+ // compositable's responsibility to cleanup the texture host before the
+ // texture host dies.
+ virtual void RemoveTextureHost(TextureHost* aTexture);
TextureHost* GetTextureHost(uint64_t aTextureID);
protected:
TextureInfo mTextureInfo;
Compositor* mCompositor;
Layer* mLayer;
RefPtr<CompositableBackendSpecificData> mBackendData;
RefPtr<TextureHost> mFirstTexture;
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -26,54 +26,377 @@ namespace layers {
ContentHostBase::ContentHostBase(const TextureInfo& aTextureInfo)
: ContentHost(aTextureInfo)
, mPaintWillResample(false)
, mInitialised(false)
{}
ContentHostBase::~ContentHostBase()
+{
+ DestroyTextureHost();
+ DestroyTextureHostOnWhite();
+}
+
+TextureHost*
+ContentHostBase::GetAsTextureHost()
+{
+ return mTextureHost;
+}
+
+void
+ContentHostBase::DestroyTextureHost()
+{
+ // The third clause in the if statement checks that we are in fact done with
+ // this texture. We don't want to prematurely deallocate a texture we might
+ // use again or double deallocate. Deallocation will happen in
+ // RemoveTextureHost.
+ // Note that GetTextureHost is linear in the number of texture hosts, but as
+ // long as that number is small (I expect a maximum of 6 for now) then it
+ // should be ok.
+ if (mTextureHost &&
+ mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED &&
+ !GetTextureHost(mTextureHost->GetID())) {
+ MOZ_ASSERT(!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+ mTextureHost->DeallocateSharedData();
+ }
+ mTextureHost = nullptr;
+}
+
+void
+ContentHostBase::DestroyTextureHostOnWhite()
+{
+ if (mTextureHostOnWhite &&
+ mTextureHostOnWhite->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED &&
+ !GetTextureHost(mTextureHostOnWhite->GetID())) {
+ MOZ_ASSERT(!(mTextureHostOnWhite->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+ mTextureHostOnWhite->DeallocateSharedData();
+ }
+ mTextureHostOnWhite = nullptr;
+}
+
+void
+ContentHostBase::RemoveTextureHost(TextureHost* aTexture)
+{
+ if ((aTexture->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED) &&
+ !(mTextureHost && mTextureHost == aTexture) &&
+ !(mTextureHostOnWhite && mTextureHostOnWhite == aTexture)) {
+ MOZ_ASSERT(!(aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+ aTexture->DeallocateSharedData();
+ }
+
+ CompositableHost::RemoveTextureHost(aTexture);
+}
+
+class MOZ_STACK_CLASS AutoLockTextureHost
+{
+public:
+ AutoLockTextureHost(TextureHost* aHost)
+ : mHost(aHost)
+ {
+ mLockSuccess = mHost ? mHost->Lock() : true;
+ }
+
+ ~AutoLockTextureHost()
+ {
+ if (mHost) {
+ mHost->Unlock();
+ }
+ }
+
+ bool IsValid()
+ {
+ return mLockSuccess;
+ }
+
+private:
+ TextureHost* mHost;
+ bool mLockSuccess;
+};
+
+void
+ContentHostBase::Composite(EffectChain& aEffectChain,
+ float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const Filter& aFilter,
+ const Rect& aClipRect,
+ const nsIntRegion* aVisibleRegion,
+ TiledLayerProperties* aLayerProperties)
+{
+ NS_ASSERTION(aVisibleRegion, "Requires a visible region");
+
+ AutoLockTextureHost lock(mTextureHost);
+ AutoLockTextureHost lockOnWhite(mTextureHostOnWhite);
+
+ if (!mTextureHost ||
+ !lock.IsValid() ||
+ !lockOnWhite.IsValid()) {
+ return;
+ }
+
+ RefPtr<NewTextureSource> source = mTextureHost->GetTextureSources();
+ RefPtr<NewTextureSource> sourceOnWhite = mTextureHostOnWhite
+ ? mTextureHostOnWhite->GetTextureSources()
+ : nullptr;
+ if (!source) {
+ return;
+ }
+ RefPtr<TexturedEffect> effect =
+ CreateTexturedEffect(source, sourceOnWhite, aFilter);
+
+ aEffectChain.mPrimaryEffect = effect;
+
+ nsIntRegion tmpRegion;
+ const nsIntRegion* renderRegion;
+ if (PaintWillResample()) {
+ // If we're resampling, then the texture image will contain exactly the
+ // entire visible region's bounds, and we should draw it all in one quad
+ // to avoid unexpected aliasing.
+ tmpRegion = aVisibleRegion->GetBounds();
+ renderRegion = &tmpRegion;
+ } else {
+ renderRegion = aVisibleRegion;
+ }
+
+ nsIntRegion region(*renderRegion);
+ nsIntPoint origin = GetOriginOffset();
+ // translate into TexImage space, buffer origin might not be at texture (0,0)
+ region.MoveBy(-origin);
+
+ // Figure out the intersecting draw region
+ gfx::IntSize texSize = source->GetSize();
+ nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
+ textureRect.MoveBy(region.GetBounds().TopLeft());
+ nsIntRegion subregion;
+ subregion.And(region, textureRect);
+ if (subregion.IsEmpty()) {
+ // Region is empty, nothing to draw
+ return;
+ }
+
+ nsIntRegion screenRects;
+ nsIntRegion regionRects;
+
+ // Collect texture/screen coordinates for drawing
+ nsIntRegionRectIterator iter(subregion);
+ while (const nsIntRect* iterRect = iter.Next()) {
+ nsIntRect regionRect = *iterRect;
+ nsIntRect screenRect = regionRect;
+ screenRect.MoveBy(origin);
+
+ screenRects.Or(screenRects, screenRect);
+ regionRects.Or(regionRects, regionRect);
+ }
+
+ TileIterator* tileIter = source->AsTileIterator();
+ TileIterator* iterOnWhite = nullptr;
+ if (tileIter) {
+ tileIter->BeginTileIteration();
+ }
+
+ if (mTextureHostOnWhite) {
+ iterOnWhite = sourceOnWhite->AsTileIterator();
+ MOZ_ASSERT(!tileIter || tileIter->GetTileCount() == iterOnWhite->GetTileCount(),
+ "Tile count mismatch on component alpha texture");
+ if (iterOnWhite) {
+ iterOnWhite->BeginTileIteration();
+ }
+ }
+
+ bool usingTiles = (tileIter && tileIter->GetTileCount() > 1);
+ do {
+ if (iterOnWhite) {
+ MOZ_ASSERT(iterOnWhite->GetTileRect() == tileIter->GetTileRect(),
+ "component alpha textures should be the same size.");
+ }
+
+ nsIntRect texRect = tileIter ? tileIter->GetTileRect()
+ : nsIntRect(0, 0,
+ texSize.width,
+ texSize.height);
+
+ // Draw texture. If we're using tiles, we do repeating manually, as texture
+ // repeat would cause each individual tile to repeat instead of the
+ // compound texture as a whole. This involves drawing at most 4 sections,
+ // 2 for each axis that has texture repeat.
+ for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
+ for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
+ nsIntRect currentTileRect(texRect);
+ currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
+
+ nsIntRegionRectIterator screenIter(screenRects);
+ nsIntRegionRectIterator regionIter(regionRects);
+
+ const nsIntRect* screenRect;
+ const nsIntRect* regionRect;
+ while ((screenRect = screenIter.Next()) &&
+ (regionRect = regionIter.Next())) {
+ nsIntRect tileScreenRect(*screenRect);
+ nsIntRect tileRegionRect(*regionRect);
+
+ // When we're using tiles, find the intersection between the tile
+ // rect and this region rect. Tiling is then handled by the
+ // outer for-loops and modifying the tile rect.
+ if (usingTiles) {
+ tileScreenRect.MoveBy(-origin);
+ tileScreenRect = tileScreenRect.Intersect(currentTileRect);
+ tileScreenRect.MoveBy(origin);
+
+ if (tileScreenRect.IsEmpty())
+ continue;
+
+ tileRegionRect = regionRect->Intersect(currentTileRect);
+ tileRegionRect.MoveBy(-currentTileRect.TopLeft());
+ }
+ gfx::Rect rect(tileScreenRect.x, tileScreenRect.y,
+ tileScreenRect.width, tileScreenRect.height);
+
+ effect->mTextureCoords = Rect(Float(tileRegionRect.x) / texRect.width,
+ Float(tileRegionRect.y) / texRect.height,
+ Float(tileRegionRect.width) / texRect.width,
+ Float(tileRegionRect.height) / texRect.height);
+ GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform);
+ if (usingTiles) {
+ DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT | DIAGNOSTIC_BIGIMAGE;
+ diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
+ GetCompositor()->DrawDiagnostics(diagnostics, rect, aClipRect,
+ aTransform);
+ }
+ }
+ }
+ }
+
+ if (iterOnWhite) {
+ iterOnWhite->NextTile();
+ }
+ } while (usingTiles && tileIter->NextTile());
+
+ if (tileIter) {
+ tileIter->EndTileIteration();
+ }
+ if (iterOnWhite) {
+ iterOnWhite->EndTileIteration();
+ }
+
+ DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT;
+ diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
+ GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform);
+}
+
+
+void
+ContentHostBase::UseTextureHost(TextureHost* aTexture)
+{
+ if (aTexture->GetFlags() & TEXTURE_ON_WHITE) {
+ DestroyTextureHost();
+ mTextureHostOnWhite = aTexture;
+ } else {
+ DestroyTextureHostOnWhite();
+ mTextureHost = aTexture;
+ }
+}
+
+void
+ContentHostBase::SetCompositor(Compositor* aCompositor)
+{
+ CompositableHost::SetCompositor(aCompositor);
+ if (mTextureHost) {
+ mTextureHost->SetCompositor(aCompositor);
+ }
+ if (mTextureHostOnWhite) {
+ mTextureHostOnWhite->SetCompositor(aCompositor);
+ }
+}
+
+#ifdef MOZ_DUMP_PAINTING
+void
+ContentHostBase::Dump(FILE* aFile,
+ const char* aPrefix,
+ bool aDumpHtml)
+{
+ if (!aDumpHtml) {
+ return;
+ }
+ if (!aFile) {
+ aFile = stderr;
+ }
+ fprintf(aFile, "<ul>");
+ if (mTextureHost) {
+ fprintf(aFile, "%s", aPrefix);
+ fprintf(aFile, "<li> <a href=");
+ DumpTextureHost(aFile, mTextureHost);
+ fprintf(aFile, "> Front buffer </a></li> ");
+ }
+ if (mTextureHostOnWhite) {
+ fprintf(aFile, "%s", aPrefix);
+ fprintf(aFile, "<li> <a href=");
+ DumpTextureHost(aFile, mTextureHostOnWhite);
+ fprintf(aFile, "> Front buffer on white </a> </li> ");
+ }
+ fprintf(aFile, "</ul>");
+}
+#endif
+
+void
+ContentHostBase::OnActorDestroy()
+{
+ if (mTextureHost) {
+ mTextureHost->OnActorDestroy();
+ }
+ if (mTextureHostOnWhite) {
+ mTextureHostOnWhite->OnActorDestroy();
+ }
+ CompositableHost::OnActorDestroy();
+}
+
+DeprecatedContentHostBase::DeprecatedContentHostBase(const TextureInfo& aTextureInfo)
+ : ContentHost(aTextureInfo)
+ , mPaintWillResample(false)
+ , mInitialised(false)
+{}
+
+DeprecatedContentHostBase::~DeprecatedContentHostBase()
{}
DeprecatedTextureHost*
-ContentHostBase::GetDeprecatedTextureHost()
+DeprecatedContentHostBase::GetDeprecatedTextureHost()
{
return mDeprecatedTextureHost;
}
void
-ContentHostBase::DestroyFrontHost()
+DeprecatedContentHostBase::DestroyFrontHost()
{
MOZ_ASSERT(!mDeprecatedTextureHost || mDeprecatedTextureHost->GetDeAllocator(),
"We won't be able to destroy our SurfaceDescriptor");
MOZ_ASSERT(!mDeprecatedTextureHostOnWhite || mDeprecatedTextureHostOnWhite->GetDeAllocator(),
"We won't be able to destroy our SurfaceDescriptor");
mDeprecatedTextureHost = nullptr;
mDeprecatedTextureHostOnWhite = nullptr;
}
void
-ContentHostBase::OnActorDestroy()
+DeprecatedContentHostBase::OnActorDestroy()
{
if (mDeprecatedTextureHost) {
mDeprecatedTextureHost->OnActorDestroy();
}
if (mDeprecatedTextureHostOnWhite) {
mDeprecatedTextureHostOnWhite->OnActorDestroy();
}
if (mNewFrontHost) {
mNewFrontHost->OnActorDestroy();
}
if (mNewFrontHostOnWhite) {
mNewFrontHostOnWhite->OnActorDestroy();
}
}
void
-ContentHostBase::Composite(EffectChain& aEffectChain,
+DeprecatedContentHostBase::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const Filter& aFilter,
const Rect& aClipRect,
const nsIntRegion* aVisibleRegion,
TiledLayerProperties* aLayerProperties)
{
NS_ASSERTION(aVisibleRegion, "Requires a visible region");
@@ -229,31 +552,31 @@ ContentHostBase::Composite(EffectChain&
}
DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT;
diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform);
}
void
-ContentHostBase::SetCompositor(Compositor* aCompositor)
+DeprecatedContentHostBase::SetCompositor(Compositor* aCompositor)
{
CompositableHost::SetCompositor(aCompositor);
if (mDeprecatedTextureHost) {
mDeprecatedTextureHost->SetCompositor(aCompositor);
}
if (mDeprecatedTextureHostOnWhite) {
mDeprecatedTextureHostOnWhite->SetCompositor(aCompositor);
}
}
#ifdef MOZ_DUMP_PAINTING
void
-ContentHostBase::Dump(FILE* aFile,
+DeprecatedContentHostBase::Dump(FILE* aFile,
const char* aPrefix,
bool aDumpHtml)
{
if (!aDumpHtml) {
return;
}
if (!aFile) {
aFile = stderr;
@@ -271,24 +594,66 @@ ContentHostBase::Dump(FILE* aFile,
DumpDeprecatedTextureHost(aFile, mDeprecatedTextureHostOnWhite);
fprintf_stderr(aFile, "> Front buffer on white </a> </li> ");
}
fprintf_stderr(aFile, "</ul>");
}
#endif
-ContentHostSingleBuffered::~ContentHostSingleBuffered()
+void
+ContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
+ const nsIntRegion& aUpdated,
+ const nsIntRegion& aOldValidRegionBack,
+ nsIntRegion* aUpdatedRegionBack)
+{
+ aUpdatedRegionBack->SetEmpty();
+
+ if (!mTextureHost) {
+ mInitialised = false;
+ return;
+ }
+
+ // updated is in screen coordinates. Convert it to buffer coordinates.
+ nsIntRegion destRegion(aUpdated);
+ destRegion.MoveBy(-aData.rect().TopLeft());
+
+ // Correct for rotation
+ destRegion.MoveBy(aData.rotation());
+
+ gfxIntSize size = aData.rect().Size();
+ nsIntRect destBounds = destRegion.GetBounds();
+ destRegion.MoveBy((destBounds.x >= size.width) ? -size.width : 0,
+ (destBounds.y >= size.height) ? -size.height : 0);
+
+ // There's code to make sure that updated regions don't cross rotation
+ // boundaries, so assert here that this is the case
+ MOZ_ASSERT((destBounds.x % size.width) + destBounds.width <= size.width,
+ "updated region lies across rotation boundaries!");
+ MOZ_ASSERT((destBounds.y % size.height) + destBounds.height <= size.height,
+ "updated region lies across rotation boundaries!");
+
+ mTextureHost->Updated(&destRegion);
+ if (mTextureHostOnWhite) {
+ mTextureHostOnWhite->Updated(&destRegion);
+ }
+ mInitialised = true;
+
+ mBufferRect = aData.rect();
+ mBufferRotation = aData.rotation();
+}
+
+DeprecatedContentHostSingleBuffered::~DeprecatedContentHostSingleBuffered()
{
DestroyTextures();
DestroyFrontHost();
}
void
-ContentHostSingleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
+DeprecatedContentHostSingleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
{
MOZ_ASSERT(aTextureId == TextureFront ||
aTextureId == TextureOnWhiteFront);
RefPtr<DeprecatedTextureHost> *newHost =
(aTextureId == TextureFront) ? &mNewFrontHost : &mNewFrontHostOnWhite;
@@ -301,30 +666,30 @@ ContentHostSingleBuffered::EnsureDepreca
(*newHost)->SetBuffer(new SurfaceDescriptor(aSurface), aAllocator);
Compositor* compositor = GetCompositor();
if (compositor) {
(*newHost)->SetCompositor(compositor);
}
}
void
-ContentHostSingleBuffered::DestroyTextures()
+DeprecatedContentHostSingleBuffered::DestroyTextures()
{
MOZ_ASSERT(!mNewFrontHost || mNewFrontHost->GetDeAllocator(),
"We won't be able to destroy our SurfaceDescriptor");
MOZ_ASSERT(!mNewFrontHostOnWhite || mNewFrontHostOnWhite->GetDeAllocator(),
"We won't be able to destroy our SurfaceDescriptor");
mNewFrontHost = nullptr;
mNewFrontHostOnWhite = nullptr;
// don't touch mDeprecatedTextureHost, we might need it for compositing
}
void
-ContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
+DeprecatedContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
const nsIntRegion& aUpdated,
const nsIntRegion& aOldValidRegionBack,
nsIntRegion* aUpdatedRegionBack)
{
aUpdatedRegionBack->SetEmpty();
if (!mDeprecatedTextureHost && !mNewFrontHost) {
mInitialised = false;
@@ -368,24 +733,61 @@ ContentHostSingleBuffered::UpdateThebes(
mDeprecatedTextureHostOnWhite->Update(*mDeprecatedTextureHostOnWhite->LockSurfaceDescriptor(), &destRegion);
}
mInitialised = true;
mBufferRect = aData.rect();
mBufferRotation = aData.rotation();
}
-ContentHostDoubleBuffered::~ContentHostDoubleBuffered()
+void
+ContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
+ const nsIntRegion& aUpdated,
+ const nsIntRegion& aOldValidRegionBack,
+ nsIntRegion* aUpdatedRegionBack)
+{
+ if (!mTextureHost) {
+ mInitialised = false;
+
+ *aUpdatedRegionBack = aUpdated;
+ return;
+ }
+
+ // We don't need to calculate an update region because we assume that if we
+ // are using double buffering then we have render-to-texture and thus no
+ // upload to do.
+ mTextureHost->Updated();
+ if (mTextureHostOnWhite) {
+ mTextureHostOnWhite->Updated();
+ }
+ mInitialised = true;
+
+ mBufferRect = aData.rect();
+ mBufferRotation = aData.rotation();
+
+ *aUpdatedRegionBack = aUpdated;
+
+ // Save the current valid region of our front buffer, because if
+ // we're double buffering, it's going to be the valid region for the
+ // next back buffer sent back to the renderer.
+ //
+ // NB: we rely here on the fact that mValidRegion is initialized to
+ // empty, and that the first time Swap() is called we don't have a
+ // valid front buffer that we're going to return to content.
+ mValidRegionForNextBackBuffer = aOldValidRegionBack;
+}
+
+DeprecatedContentHostDoubleBuffered::~DeprecatedContentHostDoubleBuffered()
{
DestroyTextures();
DestroyFrontHost();
}
void
-ContentHostDoubleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
+DeprecatedContentHostDoubleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
const SurfaceDescriptor& aSurface,
ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo)
{
RefPtr<DeprecatedTextureHost> newHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(aSurface.type(),
aTextureInfo.mDeprecatedTextureHostFlags,
aTextureInfo.mTextureFlags,
this);
@@ -415,17 +817,17 @@ ContentHostDoubleBuffered::EnsureDepreca
mBackHostOnWhite = newHost;
return;
}
NS_ERROR("Bad texture identifier");
}
void
-ContentHostDoubleBuffered::DestroyTextures()
+DeprecatedContentHostDoubleBuffered::DestroyTextures()
{
if (mNewFrontHost) {
MOZ_ASSERT(mNewFrontHost->GetDeAllocator(),
"We won't be able to destroy our SurfaceDescriptor");
mNewFrontHost = nullptr;
}
if (mNewFrontHostOnWhite) {
MOZ_ASSERT(mNewFrontHostOnWhite->GetDeAllocator(),
@@ -442,17 +844,17 @@ ContentHostDoubleBuffered::DestroyTextur
"We won't be able to destroy our SurfaceDescriptor");
mBackHostOnWhite = nullptr;
}
// don't touch mDeprecatedTextureHost, we might need it for compositing
}
void
-ContentHostDoubleBuffered::OnActorDestroy()
+DeprecatedContentHostDoubleBuffered::OnActorDestroy()
{
if (mDeprecatedTextureHost) {
mDeprecatedTextureHost->OnActorDestroy();
}
if (mDeprecatedTextureHostOnWhite) {
mDeprecatedTextureHostOnWhite->OnActorDestroy();
}
if (mNewFrontHost) {
@@ -465,17 +867,17 @@ ContentHostDoubleBuffered::OnActorDestro
mBackHost->OnActorDestroy();
}
if (mBackHostOnWhite) {
mBackHostOnWhite->OnActorDestroy();
}
}
void
-ContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
+DeprecatedContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
const nsIntRegion& aUpdated,
const nsIntRegion& aOldValidRegionBack,
nsIntRegion* aUpdatedRegionBack)
{
if (!mDeprecatedTextureHost && !mNewFrontHost) {
mInitialised = false;
*aUpdatedRegionBack = aUpdated;
@@ -750,20 +1152,41 @@ ContentHostIncremental::TextureUpdateReq
if (mTextureId == TextureFront) {
aHost->mDeprecatedTextureHost->Update(mDescriptor, &mUpdated, &offset);
} else {
aHost->mDeprecatedTextureHostOnWhite->Update(mDescriptor, &mUpdated, &offset);
}
}
void
-ContentHostSingleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
+ContentHostBase::PrintInfo(nsACString& aTo, const char* aPrefix)
{
aTo += aPrefix;
- aTo += nsPrintfCString("ContentHostSingleBuffered (0x%p)", this);
+ aTo += nsPrintfCString("ContentHost (0x%p)", this);
+
+ AppendToString(aTo, mBufferRect, " [buffer-rect=", "]");
+ AppendToString(aTo, mBufferRotation, " [buffer-rotation=", "]");
+ if (PaintWillResample()) {
+ aTo += " [paint-will-resample]";
+ }
+
+ nsAutoCString pfx(aPrefix);
+ pfx += " ";
+
+ if (mTextureHost) {
+ aTo += "\n";
+ mTextureHost->PrintInfo(aTo, pfx.get());
+ }
+}
+
+void
+DeprecatedContentHostSingleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
+{
+ aTo += aPrefix;
+ aTo += nsPrintfCString("DeprecatedContentHostSingleBuffered (0x%p)", this);
AppendToString(aTo, mBufferRect, " [buffer-rect=", "]");
AppendToString(aTo, mBufferRotation, " [buffer-rotation=", "]");
if (PaintWillResample()) {
aTo += " [paint-will-resample]";
}
nsAutoCString pfx(aPrefix);
@@ -771,20 +1194,20 @@ ContentHostSingleBuffered::PrintInfo(nsA
if (mDeprecatedTextureHost) {
aTo += "\n";
mDeprecatedTextureHost->PrintInfo(aTo, pfx.get());
}
}
void
-ContentHostDoubleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
+DeprecatedContentHostDoubleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
{
aTo += aPrefix;
- aTo += nsPrintfCString("ContentHostDoubleBuffered (0x%p)", this);
+ aTo += nsPrintfCString("DeprecatedContentHostDoubleBuffered (0x%p)", this);
AppendToString(aTo, mBufferRect, " [buffer-rect=", "]");
AppendToString(aTo, mBufferRotation, " [buffer-rotation=", "]");
if (PaintWillResample()) {
aTo += " [paint-will-resample]";
}
nsAutoCString prefix(aPrefix);
@@ -798,21 +1221,21 @@ ContentHostDoubleBuffered::PrintInfo(nsA
if (mBackHost) {
aTo += "\n";
mBackHost->PrintInfo(aTo, prefix.get());
}
}
#ifdef MOZ_DUMP_PAINTING
void
-ContentHostDoubleBuffered::Dump(FILE* aFile,
+DeprecatedContentHostDoubleBuffered::Dump(FILE* aFile,
const char* aPrefix,
bool aDumpHtml)
{
- ContentHostBase::Dump(aFile, aPrefix, aDumpHtml);
+ DeprecatedContentHostBase::Dump(aFile, aPrefix, aDumpHtml);
if (!aDumpHtml) {
return;
}
if (!aFile) {
aFile = stderr;
}
fprintf_stderr(aFile, "<ul>");
if (mBackHost) {
@@ -829,28 +1252,54 @@ ContentHostDoubleBuffered::Dump(FILE* aF
}
fprintf_stderr(aFile, "</ul>");
}
#endif
LayerRenderState
ContentHostBase::GetRenderState()
{
+ if (!mTextureHost) {
+ return LayerRenderState();
+ }
+
+ LayerRenderState result = mTextureHost->GetRenderState();
+
+ if (mBufferRotation != nsIntPoint()) {
+ result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
+ }
+ result.SetOffset(GetOriginOffset());
+ return result;
+}
+
+LayerRenderState
+DeprecatedContentHostBase::GetRenderState()
+{
LayerRenderState result = mDeprecatedTextureHost->GetRenderState();
if (mBufferRotation != nsIntPoint()) {
result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
}
result.SetOffset(GetOriginOffset());
return result;
}
#ifdef MOZ_DUMP_PAINTING
TemporaryRef<gfx::DataSourceSurface>
ContentHostBase::GetAsSurface()
{
+ if (!mTextureHost) {
+ return nullptr;
+ }
+
+ return mTextureHost->GetAsSurface();
+}
+
+TemporaryRef<gfx::DataSourceSurface>
+DeprecatedContentHostBase::GetAsSurface()
+{
return mDeprecatedTextureHost->GetAsSurface();
}
#endif
} // namespace
} // namespace
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -84,17 +84,77 @@ protected:
*/
class ContentHostBase : public ContentHost
{
public:
typedef RotatedContentBuffer::ContentType ContentType;
typedef RotatedContentBuffer::PaintState PaintState;
ContentHostBase(const TextureInfo& aTextureInfo);
- ~ContentHostBase();
+ virtual ~ContentHostBase();
+
+ virtual void Composite(EffectChain& aEffectChain,
+ float aOpacity,
+ const gfx::Matrix4x4& aTransform,
+ const gfx::Filter& aFilter,
+ const gfx::Rect& aClipRect,
+ const nsIntRegion* aVisibleRegion = nullptr,
+ TiledLayerProperties* aLayerProperties = nullptr);
+
+ virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
+
+ virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+#ifdef MOZ_DUMP_PAINTING
+ virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
+
+ virtual void Dump(FILE* aFile=nullptr,
+ const char* aPrefix="",
+ bool aDumpHtml=false) MOZ_OVERRIDE;
+#endif
+
+ virtual void PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
+
+ virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
+
+ virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
+
+ virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
+
+ virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
+
+ virtual void OnActorDestroy() MOZ_OVERRIDE;
+
+protected:
+ virtual nsIntPoint GetOriginOffset()
+ {
+ return mBufferRect.TopLeft() - mBufferRotation;
+ }
+
+ bool PaintWillResample() { return mPaintWillResample; }
+
+ // These must be called before forgetting mTextureHost or mTextureHostOnWhite
+ void DestroyTextureHost();
+ void DestroyTextureHostOnWhite();
+
+ nsIntRect mBufferRect;
+ nsIntPoint mBufferRotation;
+ RefPtr<TextureHost> mTextureHost;
+ RefPtr<TextureHost> mTextureHostOnWhite;
+ bool mPaintWillResample;
+ bool mInitialised;
+};
+class DeprecatedContentHostBase : public ContentHost
+{
+public:
+ typedef RotatedContentBuffer::ContentType ContentType;
+ typedef RotatedContentBuffer::PaintState PaintState;
+
+ DeprecatedContentHostBase(const TextureInfo& aTextureInfo);
+ ~DeprecatedContentHostBase();
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr,
TiledLayerProperties* aLayerProperties = nullptr);
@@ -148,26 +208,48 @@ protected:
// here and move it to mDeprecatedTextureHost once we do the first buffer swap.
RefPtr<DeprecatedTextureHost> mNewFrontHost;
RefPtr<DeprecatedTextureHost> mNewFrontHostOnWhite;
bool mPaintWillResample;
bool mInitialised;
};
/**
- * Double buffering is implemented by swapping the front and back DeprecatedTextureHosts.
+ * Double buffering is implemented by swapping the front and back TextureHosts.
+ * We assume that whenever we use double buffering, then we have
+ * render-to-texture and thus no texture upload to do.
*/
class ContentHostDoubleBuffered : public ContentHostBase
{
public:
ContentHostDoubleBuffered(const TextureInfo& aTextureInfo)
: ContentHostBase(aTextureInfo)
{}
- ~ContentHostDoubleBuffered();
+ virtual ~ContentHostDoubleBuffered() {}
+
+ virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_DOUBLE; }
+
+ virtual void UpdateThebes(const ThebesBufferData& aData,
+ const nsIntRegion& aUpdated,
+ const nsIntRegion& aOldValidRegionBack,
+ nsIntRegion* aUpdatedRegionBack);
+
+protected:
+ nsIntRegion mValidRegionForNextBackBuffer;
+};
+
+class DeprecatedContentHostDoubleBuffered : public DeprecatedContentHostBase
+{
+public:
+ DeprecatedContentHostDoubleBuffered(const TextureInfo& aTextureInfo)
+ : DeprecatedContentHostBase(aTextureInfo)
+ {}
+
+ ~DeprecatedContentHostDoubleBuffered();
virtual CompositableType GetType() { return BUFFER_CONTENT_DIRECT; }
virtual void UpdateThebes(const ThebesBufferData& aData,
const nsIntRegion& aUpdated,
const nsIntRegion& aOldValidRegionBack,
nsIntRegion* aUpdatedRegionBack);
@@ -200,17 +282,33 @@ protected:
* DeprecatedTextureHost in the layers transaction (i.e., in UpdateThebes).
*/
class ContentHostSingleBuffered : public ContentHostBase
{
public:
ContentHostSingleBuffered(const TextureInfo& aTextureInfo)
: ContentHostBase(aTextureInfo)
{}
- virtual ~ContentHostSingleBuffered();
+ virtual ~ContentHostSingleBuffered() {}
+
+ virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_SINGLE; }
+
+ virtual void UpdateThebes(const ThebesBufferData& aData,
+ const nsIntRegion& aUpdated,
+ const nsIntRegion& aOldValidRegionBack,
+ nsIntRegion* aUpdatedRegionBack);
+};
+
+class DeprecatedContentHostSingleBuffered : public DeprecatedContentHostBase
+{
+public:
+ DeprecatedContentHostSingleBuffered(const TextureInfo& aTextureInfo)
+ : DeprecatedContentHostBase(aTextureInfo)
+ {}
+ virtual ~DeprecatedContentHostSingleBuffered();
virtual CompositableType GetType() { return BUFFER_CONTENT; }
virtual void UpdateThebes(const ThebesBufferData& aData,
const nsIntRegion& aUpdated,
const nsIntRegion& aOldValidRegionBack,
nsIntRegion* aUpdatedRegionBack);
@@ -228,21 +326,21 @@ public:
* surfaces that only cover the changed pixels during an update.
*
* Takes ownership of the passed in update surfaces, and must
* free them once texture upload is complete.
*
* Delays texture uploads until the next composite to
* avoid blocking the main thread.
*/
-class ContentHostIncremental : public ContentHostBase
+class ContentHostIncremental : public DeprecatedContentHostBase
{
public:
ContentHostIncremental(const TextureInfo& aTextureInfo)
- : ContentHostBase(aTextureInfo)
+ : DeprecatedContentHostBase(aTextureInfo)
, mDeAllocator(nullptr)
{}
virtual CompositableType GetType() { return BUFFER_CONTENT; }
virtual void EnsureDeprecatedTextureHostIncremental(ISurfaceAllocator* aAllocator,
const TextureInfo& aTextureInfo,
const nsIntRect& aBufferRect) MOZ_OVERRIDE;
@@ -274,17 +372,17 @@ public:
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr,
TiledLayerProperties* aLayerProperties = nullptr)
{
ProcessTextureUpdates();
- ContentHostBase::Composite(aEffectChain, aOpacity,
+ DeprecatedContentHostBase::Composite(aEffectChain, aOpacity,
aTransform, aFilter,
aClipRect, aVisibleRegion,
aLayerProperties);
}
virtual void DestroyTextures()
{
mDeprecatedTextureHost = nullptr;
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -37,26 +37,26 @@ ImageHost::~ImageHost() {}
void
ImageHost::UseTextureHost(TextureHost* aTexture)
{
mFrontBuffer = aTexture;
}
void
-ImageHost::RemoveTextureHost(uint64_t aTextureID)
+ImageHost::RemoveTextureHost(TextureHost* aTexture)
{
- CompositableHost::RemoveTextureHost(aTextureID);
- if (mFrontBuffer && mFrontBuffer->GetID() == aTextureID) {
+ CompositableHost::RemoveTextureHost(aTexture);
+ if (mFrontBuffer && mFrontBuffer->GetID() == aTexture->GetID()) {
mFrontBuffer = nullptr;
}
}
TextureHost*
-ImageHost::GetTextureHost()
+ImageHost::GetAsTextureHost()
{
return mFrontBuffer;
}
void
ImageHost::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -50,19 +50,19 @@ public:
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr,
TiledLayerProperties* aLayerProperties = nullptr) MOZ_OVERRIDE;
virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
- virtual void RemoveTextureHost(uint64_t aTextureID) MOZ_OVERRIDE;
+ virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
- virtual TextureHost* GetTextureHost() MOZ_OVERRIDE;
+ virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
virtual void SetPictureRect(const nsIntRect& aPictureRect) MOZ_OVERRIDE
{
mPictureRect = aPictureRect;
mHasPictureRect = true;
}
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -116,20 +116,20 @@ void
ImageLayerComposite::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
gfx3DMatrix local = GetLocalTransform();
// Snap image edges to pixel boundaries
gfxRect sourceRect(0, 0, 0, 0);
if (mImageHost &&
mImageHost->IsAttached() &&
- (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetTextureHost())) {
+ (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetAsTextureHost())) {
IntSize size =
- mImageHost->GetTextureHost() ? mImageHost->GetTextureHost()->GetSize()
- : mImageHost->GetDeprecatedTextureHost()->GetSize();
+ mImageHost->GetAsTextureHost() ? mImageHost->GetAsTextureHost()->GetSize()
+ : mImageHost->GetDeprecatedTextureHost()->GetSize();
sourceRect.SizeTo(size.width, size.height);
if (mScaleMode != SCALE_NONE &&
sourceRect.width != 0.0 && sourceRect.height != 0.0) {
NS_ASSERTION(mScaleMode == SCALE_STRETCH,
"No other scalemodes than stretch and none supported yet.");
local.Scale(mScaleToSize.width / sourceRect.width,
mScaleToSize.height / sourceRect.height, 1.0);
}
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -508,16 +508,17 @@ ShmemTextureHost::~ShmemTextureHost()
void
ShmemTextureHost::DeallocateSharedData()
{
if (mShmem) {
MOZ_ASSERT(mDeallocator,
"Shared memory would leak without a ISurfaceAllocator");
mDeallocator->DeallocShmem(*mShmem);
+ mShmem = nullptr;
}
}
void
ShmemTextureHost::OnActorDestroy()
{
delete mShmem;
mShmem = nullptr;
@@ -546,16 +547,17 @@ MemoryTextureHost::~MemoryTextureHost()
void
MemoryTextureHost::DeallocateSharedData()
{
if (mBuffer) {
GfxMemoryImageReporter::WillFree(mBuffer);
}
delete[] mBuffer;
+ mBuffer = nullptr;
}
uint8_t* MemoryTextureHost::GetBuffer()
{
return mBuffer;
}
} // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -303,17 +303,17 @@ public:
* Is called before compositing if the shared data has changed since last
* composition.
* This method should be overload in cases like when we need to do a texture
* upload for example.
*
* @param aRegion The region that has been changed, if nil, it means that the
* entire surface should be updated.
*/
- virtual void Updated(const nsIntRegion* aRegion) {}
+ virtual void Updated(const nsIntRegion* aRegion = nullptr) {}
/**
* Sets this TextureHost's compositor.
* A TextureHost can change compositor on certain occasions, in particular if
* it belongs to an async Compositable.
* aCompositor can be null, in which case the TextureHost must cleanup all
* of it's device textures.
*/
@@ -417,17 +417,17 @@ public:
BufferTextureHost(uint64_t aID,
gfx::SurfaceFormat aFormat,
TextureFlags aFlags);
~BufferTextureHost();
virtual uint8_t* GetBuffer() = 0;
- virtual void Updated(const nsIntRegion* aRegion) MOZ_OVERRIDE;
+ virtual void Updated(const nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
virtual bool Lock() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE;
virtual void DeallocateDeviceData() MOZ_OVERRIDE;
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -93,17 +93,17 @@ CompositableParentManager::ReceiveCompos
op.textureInfo(),
op.bufferRect());
break;
}
case CompositableOperation::TOpDestroyThebesBuffer: {
MOZ_LAYERS_LOG(("[ParentSide] Created double buffer"));
const OpDestroyThebesBuffer& op = aEdit.get_OpDestroyThebesBuffer();
CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
- ContentHostBase* content = static_cast<ContentHostBase*>(compositableParent->GetCompositableHost());
+ DeprecatedContentHostBase* content = static_cast<DeprecatedContentHostBase*>(compositableParent->GetCompositableHost());
content->DestroyTextures();
break;
}
case CompositableOperation::TOpPaintTexture: {
MOZ_LAYERS_LOG(("[ParentSide] Paint Texture X"));
const OpPaintTexture& op = aEdit.get_OpPaintTexture();
@@ -266,21 +266,22 @@ CompositableParentManager::ReceiveCompos
}
CompositableHost* compositable = AsCompositable(op);
RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
MOZ_ASSERT(texture);
TextureFlags flags = texture->GetFlags();
- if (!(flags & TEXTURE_DEALLOCATE_CLIENT)) {
+ if (!(flags & TEXTURE_DEALLOCATE_CLIENT) &&
+ !(flags & TEXTURE_DEALLOCATE_DEFERRED)) {
texture->DeallocateSharedData();
}
- compositable->RemoveTextureHost(op.textureID());
+ compositable->RemoveTextureHost(texture);
// if it is not the host that deallocates the shared data, then we need
// to notfy the client side to tell when it is safe to deallocate or
// reuse it.
if (flags & TEXTURE_DEALLOCATE_CLIENT) {
replyv.push_back(ReplyTextureRemoved(op.compositableParent(), nullptr,
op.textureID()));
}
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -181,17 +181,18 @@ uint8_t*
GrallocTextureClientOGL::GetBuffer() const
{
MOZ_ASSERT(IsValid());
NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
return mMappedBuffer;
}
bool
-GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize)
+GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
+ TextureAllocationFlags)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mCompositable);
ISurfaceAllocator* allocator = mCompositable->GetForwarder();
uint32_t format;
uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN;
bool swapRB = GetFlags() & TEXTURE_RB_SWAPPED;
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -75,17 +75,18 @@ public:
*/
void SetGrallocOpenFlags(uint32_t aFlags)
{
mGrallocFlags = aFlags;
}
virtual uint8_t* GetBuffer() const MOZ_OVERRIDE;
- virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
+ virtual bool AllocateForSurface(gfx::IntSize aSize,
+ TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode) MOZ_OVERRIDE;
bool AllocateGralloc(gfx::IntSize aYSize, uint32_t aAndroidFormat, uint32_t aUsage);
virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;