Bug 1066280 - Add TexClient for ShSurf. - r=kamidphish,mattwoodrow

From a7c09c0f17e19fd2254cb1d7a8ddd07b327151ad Mon Sep 17 00:00:00 2001
---
 gfx/2d/HelpersCairo.h                   |   2 +
 gfx/gl/GLContext.cpp                    |   3 +-
 gfx/gl/GLContext.h                      |   2 -
 gfx/gl/GLReadTexImageHelper.cpp         |  21 +--
 gfx/gl/GLReadTexImageHelper.h           |   6 +
 gfx/gl/GLScreenBuffer.h                 |   6 +-
 gfx/gl/ScopedGLHelpers.cpp              |  40 +++++
 gfx/gl/ScopedGLHelpers.h                |  26 ++-
 gfx/gl/SharedSurface.cpp                |  94 +++++++++++
 gfx/gl/SharedSurface.h                  |  19 +++
 gfx/gl/SharedSurfaceIO.h                |   4 +
 gfx/layers/CopyableCanvasLayer.cpp      |   3 +-
 gfx/layers/client/CanvasClient.cpp      | 276 +++++++++++++++++++++++++++++---
 gfx/layers/client/CanvasClient.h        |  34 ++++
 gfx/layers/client/ClientCanvasLayer.cpp |  21 ++-
 gfx/layers/client/ClientCanvasLayer.h   |   9 +-
 gfx/layers/client/TextureClient.cpp     |  35 ++++
 gfx/layers/client/TextureClient.h       |  85 +++++++++-
 gfx/layers/composite/TextureHost.cpp    | 131 ++++++++++++++-
 gfx/layers/composite/TextureHost.h      |  64 ++++++++
 gfx/layers/d3d10/CanvasLayerD3D10.cpp   |   5 +-
 gfx/layers/ipc/LayersSurfaces.ipdlh     |   5 +
 22 files changed, 828 insertions(+), 63 deletions(-)
This commit is contained in:
jdashg 2014-10-07 21:01:51 -07:00
Родитель 70b2daa211
Коммит bd7ba17b6a
22 изменённых файлов: 828 добавлений и 63 удалений

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

@ -141,6 +141,7 @@ GfxFormatToCairoFormat(SurfaceFormat format)
return CAIRO_FORMAT_RGB16_565;
default:
gfxWarning() << "Unknown image format";
MOZ_ASSERT(false, "Unknown image format");
return CAIRO_FORMAT_ARGB32;
}
}
@ -159,6 +160,7 @@ GfxFormatToCairoContent(SurfaceFormat format)
return CAIRO_CONTENT_ALPHA;
default:
gfxWarning() << "Unknown image format";
MOZ_ASSERT(false, "Unknown image format");
return CAIRO_CONTENT_COLOR_ALPHA;
}
}

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

@ -2005,8 +2005,9 @@ SharedSurface*
GLContext::RequestFrame()
{
MOZ_ASSERT(mScreen);
MOZ_CRASH("Not anymore!");
return mScreen->Stream()->SwapConsumer();
return nullptr;
}

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

@ -1576,7 +1576,6 @@ public:
AFTER_GL_CALL;
}
private:
void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
BEFORE_GL_CALL;
@ -1585,7 +1584,6 @@ private:
mHeavyGLCallsSinceLastFlush = true;
}
public:
void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
BeforeGLReadCall();

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

@ -155,16 +155,19 @@ GLReadTexImageHelper::DidGLErrorOccur(const char* str)
return false;
}
static bool
bool
GetActualReadFormats(GLContext* gl,
GLenum destFormat, GLenum destType,
GLenum& readFormat, GLenum& readType)
GLenum* out_readFormat, GLenum* out_readType)
{
MOZ_ASSERT(out_readFormat);
MOZ_ASSERT(out_readType);
if (destFormat == LOCAL_GL_RGBA &&
destType == LOCAL_GL_UNSIGNED_BYTE)
{
readFormat = destFormat;
readType = destType;
*out_readFormat = destFormat;
*out_readType = destType;
return true;
}
@ -197,12 +200,12 @@ GetActualReadFormats(GLContext* gl,
}
if (fallback) {
readFormat = LOCAL_GL_RGBA;
readType = LOCAL_GL_UNSIGNED_BYTE;
*out_readFormat = LOCAL_GL_RGBA;
*out_readType = LOCAL_GL_UNSIGNED_BYTE;
return false;
} else {
readFormat = destFormat;
readType = destType;
*out_readFormat = destFormat;
*out_readType = destType;
return true;
}
}
@ -395,7 +398,7 @@ ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest)
GLenum readType = destType;
bool needsTempSurf = !GetActualReadFormats(gl,
destFormat, destType,
readFormat, readType);
&readFormat, &readType);
RefPtr<DataSourceSurface> tempSurf;
DataSourceSurface* readSurf = dest;

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

@ -22,6 +22,12 @@ class DataSourceSurface;
namespace gl {
// Returns true if the `dest{Format,Type}` are the same as the
// `read{Format,Type}`.
bool GetActualReadFormats(GLContext* gl,
GLenum destFormat, GLenum destType,
GLenum* out_readFormat, GLenum* out_readType);
void ReadPixelsIntoDataSurface(GLContext* aGL,
gfx::DataSourceSurface* aSurface);

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

@ -28,6 +28,8 @@ namespace gl {
class GLContext;
class SharedSurface;
class ShSurfHandle;
class SurfaceFactory;
class SurfaceStream;
class DrawBuffer
@ -173,8 +175,8 @@ public:
return mFactory.get();
}
SharedSurface* Front() const {
return mFront->Surf();
ShSurfHandle* Front() const {
return mFront;
}
SharedSurface* SharedSurf() const {

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

@ -11,6 +11,14 @@
namespace mozilla {
namespace gl {
#ifdef DEBUG
bool
IsContextCurrent(GLContext* gl)
{
return gl->IsCurrent();
}
#endif
/* ScopedGLState - Wraps glEnable/glDisable. **********************************/
// Use |newState = true| to enable, |false| to disable.
@ -483,5 +491,37 @@ ScopedGLDrawState::~ScopedGLDrawState()
mGL->fUseProgram(boundProgram);
}
////////////////////////////////////////////////////////////////////////
// ScopedPackAlignment
ScopedPackAlignment::ScopedPackAlignment(GLContext* gl, GLint scopedVal)
: ScopedGLWrapper<ScopedPackAlignment>(gl)
{
MOZ_ASSERT(scopedVal == 1 ||
scopedVal == 2 ||
scopedVal == 4 ||
scopedVal == 8);
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mOldVal);
if (scopedVal != mOldVal) {
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, scopedVal);
} else {
// Don't try to re-set it during unwrap.
mOldVal = 0;
}
}
void
ScopedPackAlignment::UnwrapImpl() {
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
if (mOldVal) {
mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mOldVal);
}
}
} /* namespace gl */
} /* namespace mozilla */

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

@ -6,13 +6,18 @@
#ifndef SCOPEDGLHELPERS_H_
#define SCOPEDGLHELPERS_H_
#include "GLDefs.h"
#include "mozilla/UniquePtr.h"
#include "GLContext.h"
namespace mozilla {
namespace gl {
class GLContext;
#ifdef DEBUG
bool IsContextCurrent(GLContext* gl);
#endif
//RAII via CRTP!
template <class Derived>
struct ScopedGLWrapper
@ -29,7 +34,7 @@ protected:
{
MOZ_ASSERT(&ScopedGLWrapper<Derived>::Unwrap == &Derived::Unwrap);
MOZ_ASSERT(&Derived::UnwrapImpl);
MOZ_ASSERT(mGL->IsCurrent());
MOZ_ASSERT(IsContextCurrent(mGL));
}
virtual ~ScopedGLWrapper() {
@ -338,6 +343,21 @@ struct ScopedGLDrawState {
GLContext* const mGL;
GLuint packAlign;
};
struct ScopedPackAlignment
: public ScopedGLWrapper<ScopedPackAlignment>
{
friend struct ScopedGLWrapper<ScopedPackAlignment>;
protected:
GLint mOldVal;
public:
ScopedPackAlignment(GLContext* aGL, GLint scopedVal);
protected:
void UnwrapImpl();
};
} /* namespace gl */
} /* namespace mozilla */

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

@ -353,5 +353,99 @@ SurfaceFactory::Recycle(UniquePtr<SharedSurface> surf)
}
}
////////////////////////////////////////////////////////////////////////////////
// ScopedReadbackFB
ScopedReadbackFB::ScopedReadbackFB(SharedSurface* src)
: mGL(src->mGL)
, mAutoFB(mGL)
, mTempFB(0)
, mTempTex(0)
, mSurfToUnlock(nullptr)
, mSurfToLock(nullptr)
{
switch (src->mAttachType) {
case AttachmentType::GLRenderbuffer:
{
mGL->fGenFramebuffers(1, &mTempFB);
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB);
GLuint rb = src->ProdRenderbuffer();
mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_RENDERBUFFER, rb);
break;
}
case AttachmentType::GLTexture:
{
mGL->fGenFramebuffers(1, &mTempFB);
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB);
GLuint tex = src->ProdTexture();
GLenum texImageTarget = src->ProdTextureTarget();
mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
texImageTarget, tex, 0);
break;
}
case AttachmentType::Screen:
{
SharedSurface* origLocked = mGL->GetLockedSurface();
if (origLocked != src) {
if (origLocked) {
mSurfToLock = origLocked;
mSurfToLock->UnlockProd();
}
mSurfToUnlock = src;
mSurfToUnlock->LockProd();
}
// TODO: This should just be BindFB, but we don't have
// the patch for this yet. (bug 1045955)
MOZ_ASSERT(mGL->Screen());
mGL->Screen()->BindReadFB_Internal(0);
break;
}
default:
MOZ_CRASH("Unhandled `mAttachType`.");
}
if (src->NeedsIndirectReads()) {
mGL->fGenTextures(1, &mTempTex);
{
ScopedBindTexture autoTex(mGL, mTempTex);
GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA
: LOCAL_GL_RGB;
auto width = src->mSize.width;
auto height = src->mSize.height;
mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width,
height, 0);
}
mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
LOCAL_GL_TEXTURE_2D, mTempTex, 0);
}
}
ScopedReadbackFB::~ScopedReadbackFB()
{
if (mTempFB) {
mGL->fDeleteFramebuffers(1, &mTempFB);
}
if (mTempTex) {
mGL->fDeleteTextures(1, &mTempTex);
}
if (mSurfToUnlock) {
mSurfToUnlock->UnlockProd();
}
if (mSurfToLock) {
mSurfToLock->LockProd();
}
}
} /* namespace gfx */
} /* namespace mozilla */

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

@ -25,6 +25,7 @@
#include "mozilla/gfx/Point.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "ScopedGLHelpers.h"
#include "SurfaceTypes.h"
class nsIThread;
@ -127,6 +128,10 @@ public:
{
return false;
}
virtual bool NeedsIndirectReads() const {
return false;
}
};
template<typename T>
@ -234,6 +239,20 @@ public:
}
};
class ScopedReadbackFB
{
GLContext* const mGL;
ScopedBindFramebuffer mAutoFB;
GLuint mTempFB;
GLuint mTempTex;
SharedSurface* mSurfToUnlock;
SharedSurface* mSurfToLock;
public:
ScopedReadbackFB(SharedSurface* src);
~ScopedReadbackFB();
};
} // namespace gl
} // namespace mozilla

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

@ -56,6 +56,10 @@ public:
return mIOSurf;
}
virtual bool NeedsIndirectReads() const MOZ_OVERRIDE {
return true;
}
private:
SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf,
GLContext* gl, const gfx::IntSize& size,

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

@ -101,7 +101,8 @@ CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
if (mStream) {
sharedSurf = mStream->SwapConsumer();
} else {
sharedSurf = mGLContext->RequestFrame();
auto screen = mGLContext->Screen();
sharedSurf = screen->Front()->Surf();
}
if (!sharedSurf) {

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

@ -9,10 +9,12 @@
#include "CompositorChild.h" // for CompositorChild
#include "GLContext.h" // for GLContext
#include "GLScreenBuffer.h" // for GLScreenBuffer
#include "ScopedGLHelpers.h"
#include "SurfaceStream.h" // for SurfaceStream
#include "SurfaceTypes.h" // for SurfaceStreamHandle
#include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat
#include "gfxPlatform.h" // for gfxPlatform
#include "GLReadTexImageHelper.h"
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/GrallocTextureClient.h"
@ -43,11 +45,18 @@ CanvasClient::CreateCanvasClient(CanvasClientType aType,
return new CanvasClient2D(aForwarder, aFlags);
}
#endif
if (aType == CanvasClientGLContext) {
switch (aType) {
case CanvasClientTypeShSurf:
return new CanvasClientShSurf(aForwarder, aFlags);
case CanvasClientGLContext:
aFlags |= TextureFlags::DEALLOCATE_CLIENT;
return new CanvasClientSurfaceStream(aForwarder, aFlags);
default:
return new CanvasClient2D(aForwarder, aFlags);
}
return new CanvasClient2D(aForwarder, aFlags);
}
void
@ -149,21 +158,16 @@ void
CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
aLayer->mGLContext->MakeCurrent();
GLScreenBuffer* screen = aLayer->mGLContext->Screen();
SurfaceStream* stream = nullptr;
if (aLayer->mStream) {
stream = aLayer->mStream;
SurfaceStream* stream = aLayer->mStream;
MOZ_ASSERT(stream);
// Copy our current surface to the current producer surface in our stream, then
// call SwapProducer to make a new buffer ready.
stream->CopySurfaceToProducer(aLayer->mTextureSurface.get(),
aLayer->mFactory.get());
stream->SwapProducer(aLayer->mFactory.get(),
gfx::IntSize(aSize.width, aSize.height));
} else {
stream = screen->Stream();
}
// Copy our current surface to the current producer surface in our stream, then
// call SwapProducer to make a new buffer ready.
stream->CopySurfaceToProducer(aLayer->mTextureSurface.get(),
aLayer->mFactory.get());
stream->SwapProducer(aLayer->mFactory.get(),
gfx::IntSize(aSize.width, aSize.height));
#ifdef MOZ_WIDGET_GONK
SharedSurface* surf = stream->SwapConsumer();
@ -211,10 +215,12 @@ CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
} else {
bool bufferCreated = false;
if (!mBuffer) {
StreamTextureClient* textureClient =
new StreamTextureClient(mTextureInfo.mTextureFlags);
textureClient->InitWith(stream);
mBuffer = textureClient;
// We need to dealloc in the client.
TextureFlags flags = GetTextureFlags() |
TextureFlags::DEALLOCATE_CLIENT;
StreamTextureClient* texClient = new StreamTextureClient(flags);
texClient->InitWith(stream);
mBuffer = texClient;
bufferCreated = true;
}
@ -232,5 +238,237 @@ CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
aLayer->Painted();
}
////////////////////////////////////////////////////////////////////////
CanvasClientShSurf::CanvasClientShSurf(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags)
: CanvasClient(aLayerForwarder, aFlags)
{
}
////////////////////////////////////////
// Accelerated backends
static TemporaryRef<TextureClient>
TexClientFromShSurf(SharedSurface* surf, TextureFlags baseFlags)
{
TextureFlags flags = baseFlags | TextureFlags::DEALLOCATE_CLIENT;
switch (surf->mType) {
case SharedSurfaceType::Basic:
return nullptr;
#ifdef MOZ_WIDGET_GONK
case SharedSurfaceType::Gralloc:
return GrallocTextureClientOGL::FromShSurf(surf, flags);
#endif
default:
return new ShSurfTexClient(flags, surf);
}
}
////////////////////////////////////////
// Readback
// For formats compatible with R8G8B8A8.
static inline void SwapRB_R8G8B8A8(uint8_t* pixel) {
// [RR, GG, BB, AA]
Swap(pixel[0], pixel[2]);
}
class TexClientFactory
{
ISurfaceAllocator* const mAllocator;
const bool mHasAlpha;
const gfx::IntSize mSize;
const gfx::BackendType mBackendType;
const TextureFlags mBaseTexFlags;
public:
TexClientFactory(ISurfaceAllocator* allocator, bool hasAlpha,
const gfx::IntSize& size, gfx::BackendType backendType,
TextureFlags baseTexFlags)
: mAllocator(allocator)
, mHasAlpha(hasAlpha)
, mSize(size)
, mBackendType(backendType)
, mBaseTexFlags(baseTexFlags)
{
}
protected:
TemporaryRef<BufferTextureClient> Create(gfx::SurfaceFormat format) {
return TextureClient::CreateForRawBufferAccess(mAllocator, format,
mSize, mBackendType,
mBaseTexFlags);
}
public:
TemporaryRef<BufferTextureClient> CreateB8G8R8AX8() {
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
: gfx::SurfaceFormat::B8G8R8X8;
return Create(format);
}
TemporaryRef<BufferTextureClient> CreateR8G8B8AX8() {
// For now, assume that all RGBA formats are broken.
RefPtr<BufferTextureClient> ret = CreateB8G8R8AX8();
if (ret) {
ret->AddFlags(TextureFlags::RB_SWAPPED);
}
return ret.forget();
}
};
static TemporaryRef<TextureClient>
TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator,
TextureFlags baseFlags, LayersBackend layersBackend)
{
auto backendType = gfx::BackendType::CAIRO;
TexClientFactory factory(allocator, src->mHasAlpha, src->mSize, backendType,
baseFlags);
RefPtr<BufferTextureClient> texClient;
{
gl::ScopedReadbackFB autoReadback(src);
// We have a source FB, now we need a format.
GLenum destFormat = LOCAL_GL_BGRA;
GLenum destType = LOCAL_GL_UNSIGNED_BYTE;
GLenum readFormat;
GLenum readType;
// We actually don't care if they match, since we can handle
// any read{Format,Type} we get.
auto gl = src->mGL;
GetActualReadFormats(gl, destFormat, destType, &readFormat, &readType);
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA ||
readFormat == LOCAL_GL_BGRA);
MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
// With a format and type, we can create texClient.
if (readFormat == LOCAL_GL_BGRA &&
readType == LOCAL_GL_UNSIGNED_BYTE)
{
// 0xAARRGGBB
// In Lendian: [BB, GG, RR, AA]
texClient = factory.CreateB8G8R8AX8();
} else if (readFormat == LOCAL_GL_RGBA &&
readType == LOCAL_GL_UNSIGNED_BYTE)
{
// [RR, GG, BB, AA]
texClient = factory.CreateR8G8B8AX8();
} else {
MOZ_CRASH("Bad `read{Format,Type}`.");
}
MOZ_ASSERT(texClient);
if (!texClient)
return nullptr;
// With a texClient, we can lock for writing.
MOZ_ALWAYS_TRUE( texClient->Lock(OpenMode::OPEN_WRITE) );
uint8_t* lockedBytes = texClient->GetLockedData();
// ReadPixels from the current FB into lockedBits.
auto width = src->mSize.width;
auto height = src->mSize.height;
{
ScopedPackAlignment autoAlign(gl, 4);
gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, lockedBytes);
}
// RB_SWAPPED doesn't work with D3D11. (bug 1051010)
// RB_SWAPPED doesn't work with Basic. (bug ???????)
bool layersNeedsManualSwap = layersBackend == LayersBackend::LAYERS_D3D11 ||
layersBackend == LayersBackend::LAYERS_BASIC;
if (texClient->HasFlags(TextureFlags::RB_SWAPPED) &&
layersNeedsManualSwap)
{
size_t pixels = width * height;
uint8_t* itr = lockedBytes;
for (size_t i = 0; i < pixels; i++) {
SwapRB_R8G8B8A8(itr);
itr += 4;
}
texClient->RemoveFlags(TextureFlags::RB_SWAPPED);
}
texClient->Unlock();
}
return texClient.forget();
}
////////////////////////////////////////
void
CanvasClientShSurf::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{
aLayer->mGLContext->MakeCurrent();
GLScreenBuffer* screen = aLayer->mGLContext->Screen();
if (mFront) {
mPrevFront = mFront;
mFront = nullptr;
}
mFront = screen->Front();
if (!mFront)
return;
// Alright, now sort out the IPC goop.
SharedSurface* surf = mFront->Surf();
auto forwarder = GetForwarder();
auto flags = GetTextureFlags() | TextureFlags::IMMUTABLE;
// Get a TexClient from our surf.
RefPtr<TextureClient> newTex = TexClientFromShSurf(surf, flags);
if (!newTex) {
auto manager = aLayer->ClientManager();
auto shadowForwarder = manager->AsShadowForwarder();
auto layersBackend = shadowForwarder->GetCompositorBackendType();
newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend);
}
MOZ_ASSERT(newTex);
// Add the new TexClient.
MOZ_ALWAYS_TRUE( newTex->InitIPDLActor(forwarder) );
MOZ_ASSERT(newTex->GetIPDLActor());
// Remove the old TexClient.
if (mFrontTex) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(mFrontTex);
mFrontTex->SetRemoveFromCompositableTracker(tracker);
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontTex);
mFrontTex = nullptr;
}
// Use the new TexClient.
mFrontTex = newTex;
forwarder->UpdatedTexture(this, mFrontTex, nullptr);
forwarder->UseTexture(this, mFrontTex);
aLayer->Painted();
}
}
}

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

@ -21,6 +21,7 @@
namespace mozilla {
namespace gl {
class SharedSurface;
class ShSurfHandle;
}
}
@ -44,6 +45,7 @@ public:
enum CanvasClientType {
CanvasClientSurface,
CanvasClientGLContext,
CanvasClientTypeShSurf,
};
static TemporaryRef<CanvasClient> CreateCanvasClient(CanvasClientType aType,
CompositableForwarder* aFwd,
@ -138,6 +140,38 @@ private:
RefPtr<TextureClient> mBuffer;
};
// Used for GL canvases where we don't need to do any readback, i.e., with a
// GL backend.
class CanvasClientShSurf : public CanvasClient
{
private:
RefPtr<gl::ShSurfHandle> mFront;
RefPtr<gl::ShSurfHandle> mPrevFront;
RefPtr<TextureClient> mFrontTex;
public:
CanvasClientShSurf(CompositableForwarder* aLayerForwarder,
TextureFlags aFlags);
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE {
return TextureInfo(CompositableType::IMAGE);
}
virtual void Clear() MOZ_OVERRIDE {
mFront = nullptr;
mPrevFront = nullptr;
mFrontTex = nullptr;
}
virtual void Update(gfx::IntSize aSize,
ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
virtual void OnDetach() MOZ_OVERRIDE {
CanvasClientShSurf::Clear();
}
};
}
}

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

@ -70,9 +70,6 @@ ClientCanvasLayer::Initialize(const Data& aData)
}
MOZ_ASSERT(caps.alpha == aData.mHasAlpha);
SurfaceStreamType streamType =
SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
screen->PreserveBuffer());
UniquePtr<SurfaceFactory> factory;
if (!gfxPrefs::WebGLForceLayersReadback()) {
@ -139,7 +136,7 @@ ClientCanvasLayer::Initialize(const Data& aData)
MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory");
}
} else if (factory) {
screen->Morph(Move(factory), streamType);
screen->Morph(Move(factory));
}
}
}
@ -167,10 +164,6 @@ ClientCanvasLayer::RenderLayer()
if (!mGLContext) {
// We don't support locking for buffer surfaces currently
flags |= TextureFlags::IMMEDIATE_UPLOAD;
} else {
// GLContext's SurfaceStream handles ownership itself,
// and doesn't require layers to do any deallocation.
flags |= TextureFlags::DEALLOCATE_CLIENT;
}
if (!mIsAlphaPremultiplied) {
@ -199,6 +192,18 @@ ClientCanvasLayer::RenderLayer()
mCanvasClient->OnTransaction();
}
CanvasClient::CanvasClientType
ClientCanvasLayer::GetCanvasClientType()
{
if (mGLContext) {
if (mGLContext->Screen()) {
return CanvasClient::CanvasClientTypeShSurf;
}
return CanvasClient::CanvasClientGLContext;
}
return CanvasClient::CanvasClientSurface;
}
already_AddRefed<CanvasLayer>
ClientLayerManager::CreateCanvasLayer()
{

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

@ -91,13 +91,7 @@ protected:
return static_cast<ClientLayerManager*>(mManager);
}
CanvasClientType GetCanvasClientType()
{
if (mGLContext) {
return CanvasClient::CanvasClientGLContext;
}
return CanvasClient::CanvasClientSurface;
}
CanvasClientType GetCanvasClientType();
RefPtr<CanvasClient> mCanvasClient;
@ -108,6 +102,7 @@ protected:
friend class CanvasClient2D;
friend class DeprecatedCanvasClientSurfaceStream;
friend class CanvasClientSurfaceStream;
friend class CanvasClientShSurf;
};
}
}

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

@ -19,6 +19,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/TextureClientOGL.h"
#include "mozilla/layers/PTextureChild.h"
#include "SharedSurface.h"
#include "SurfaceStream.h"
#include "GLContext.h"
@ -792,6 +793,17 @@ BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize,
return true;
}
uint8_t*
BufferTextureClient::GetLockedData() const
{
MOZ_ASSERT(IsLocked());
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
MOZ_ASSERT(serializer.IsValid());
return serializer.GetData();
}
////////////////////////////////////////////////////////////////////////
// StreamTextureClient
StreamTextureClient::StreamTextureClient(TextureFlags aFlags)
@ -848,6 +860,29 @@ StreamTextureClient::IsAllocated() const
return mStream != 0;
}
////////////////////////////////////////////////////////////////////////
// ShSurfTexClient
ShSurfTexClient::ShSurfTexClient(TextureFlags aFlags, gl::SharedSurface* surf)
: TextureClient(aFlags)
, mIsLocked(false)
, mSurf(surf)
, mGL(mSurf->mGL)
{
mSurf->Fence();
}
ShSurfTexClient::~ShSurfTexClient()
{
// the data is owned externally.
}
bool
ShSurfTexClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
aOutDescriptor = ShSurfDescriptor((uintptr_t)mSurf);
return true;
}
}
}

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

@ -34,6 +34,7 @@ class gfxImageSurface;
namespace mozilla {
namespace gl {
class GLContext;
class SharedSurface;
class SurfaceStream;
}
@ -296,6 +297,23 @@ public:
*/
TextureFlags GetFlags() const { return mFlags; }
bool HasFlags(TextureFlags aFlags) const
{
return (mFlags & aFlags) == aFlags;
}
void AddFlags(TextureFlags aFlags)
{
MOZ_ASSERT(!IsSharedWithCompositor());
mFlags |= aFlags;
}
void RemoveFlags(TextureFlags aFlags)
{
MOZ_ASSERT(!IsSharedWithCompositor());
mFlags &= ~aFlags;
}
/**
* valid only for TextureFlags::RECYCLE TextureClient.
* When called this texture client will grab a strong reference and release
@ -431,12 +449,6 @@ protected:
*/
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
void AddFlags(TextureFlags aFlags)
{
MOZ_ASSERT(!IsSharedWithCompositor());
mFlags |= aFlags;
}
ISurfaceAllocator* GetAllocator()
{
return mAllocator;
@ -504,6 +516,8 @@ public:
virtual bool IsLocked() const MOZ_OVERRIDE { return mLocked; }
uint8_t* GetLockedData() const;
virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
virtual gfx::DrawTarget* BorrowDrawTarget() MOZ_OVERRIDE;
@ -665,6 +679,65 @@ protected:
RefPtr<gl::GLContext> mGL; // Just for reference holding.
};
/**
* A TextureClient implementation to share SharedSurfaces.
*/
class ShSurfTexClient : public TextureClient
{
public:
explicit ShSurfTexClient(TextureFlags aFlags, gl::SharedSurface* surf);
protected:
~ShSurfTexClient();
public:
// Boilerplate start
virtual bool IsAllocated() const MOZ_OVERRIDE { return true; }
virtual bool Lock(OpenMode) MOZ_OVERRIDE {
MOZ_ASSERT(!mIsLocked);
mIsLocked = true;
return true;
}
virtual void Unlock() MOZ_OVERRIDE {
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
}
virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE {
return gfx::SurfaceFormat::UNKNOWN;
}
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return gfx::IntSize(); }
// This TextureClient should not be used in a context where we use CreateSimilar
// (ex. component alpha) because the underlying texture data is always created by
// an external producer.
virtual TemporaryRef<TextureClient>
CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE {
return nullptr;
}
virtual bool AllocateForSurface(gfx::IntSize,
TextureAllocationFlags) MOZ_OVERRIDE {
MOZ_CRASH("Should never hit this.");
return false;
}
// Boilerplate end
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
protected:
bool mIsLocked;
gl::SharedSurface* const mSurf;
RefPtr<gl::GLContext> mGL; // Just for reference holding.
};
struct TextureClientAutoUnlock
{
TextureClient* mTexture;

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

@ -203,6 +203,9 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
case SurfaceDescriptor::TSurfaceStreamDescriptor:
return new StreamTextureHost(aFlags, aDesc.get_SurfaceStreamDescriptor());
case SurfaceDescriptor::TShSurfDescriptor:
return new ShSurfTexHost(aFlags, aDesc.get_ShSurfDescriptor());
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) {
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
@ -997,8 +1000,134 @@ StreamTextureHost::GetSize() const
MOZ_ASSERT(mTextureSource);
return mTextureSource->GetSize();
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
static RefPtr<NewTextureSource>
ShSurfToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor)
{
MOZ_ASSERT(abstractSurf);
MOZ_ASSERT(abstractSurf->mType != gl::SharedSurfaceType::Basic);
MOZ_ASSERT(abstractSurf->mType != gl::SharedSurfaceType::Gralloc);
if (!compositor) {
return nullptr;
}
gfx::SurfaceFormat format = abstractSurf->mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
: gfx::SurfaceFormat::R8G8B8X8;
RefPtr<NewTextureSource> texSource;
switch (abstractSurf->mType) {
#ifdef XP_WIN
case gl::SharedSurfaceType::EGLSurfaceANGLE: {
auto surf = gl::SharedSurface_ANGLEShareHandle::Cast(abstractSurf);
HANDLE shareHandle = surf->GetShareHandle();
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_D3D11);
CompositorD3D11* compositorD3D11 = static_cast<CompositorD3D11*>(compositor);
ID3D11Device* d3d = compositorD3D11->GetDevice();
nsRefPtr<ID3D11Texture2D> tex;
HRESULT hr = d3d->OpenSharedResource(shareHandle,
__uuidof(ID3D11Texture2D),
getter_AddRefs(tex));
if (FAILED(hr)) {
NS_WARNING("Failed to open shared resource.");
break;
}
texSource = new DataTextureSourceD3D11(format, compositorD3D11, tex);
break;
}
#endif
case gl::SharedSurfaceType::GLTextureShare: {
auto surf = gl::SharedSurface_GLTexture::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
gl::GLContext* gl = compositorOGL->gl();
GLenum target = surf->ConsTextureTarget();
GLuint tex = surf->ConsTexture(gl);
texSource = new GLTextureSource(compositorOGL, tex, format, target,
surf->mSize);
break;
}
case gl::SharedSurfaceType::EGLImageShare: {
auto surf = gl::SharedSurface_EGLImage::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
gl::GLContext* gl = compositorOGL->gl();
MOZ_ASSERT(gl->IsCurrent());
GLenum target = 0;
GLuint tex = 0;
surf->AcquireConsumerTexture(gl, &tex, &target);
texSource = new GLTextureSource(compositorOGL, tex, format, target,
surf->mSize);
break;
}
#ifdef XP_MACOSX
case gl::SharedSurfaceType::IOSurface: {
auto surf = gl::SharedSurface_IOSurface::Cast(abstractSurf);
MacIOSurface* ioSurf = surf->GetIOSurface();
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
texSource = new MacIOSurfaceTextureSourceOGL(compositorOGL, ioSurf);
break;
}
#endif
default:
break;
}
MOZ_ASSERT(texSource.get(), "TextureSource creation failed.");
return texSource;
}
////////////////////////////////////////////////////////////////////////////////
// ShSurfTexHost
ShSurfTexHost::ShSurfTexHost(TextureFlags aFlags, const ShSurfDescriptor& aDesc)
: TextureHost(aFlags)
, mIsLocked(false)
, mSurf((gl::SharedSurface*)aDesc.surf())
, mCompositor(nullptr)
{
MOZ_ASSERT(mSurf);
}
gfx::SurfaceFormat
ShSurfTexHost::GetFormat() const
{
MOZ_ASSERT(mTexSource);
return mTexSource->GetFormat();
}
gfx::IntSize
ShSurfTexHost::GetSize() const
{
MOZ_ASSERT(mTexSource);
return mTexSource->GetSize();
}
void
ShSurfTexHost::EnsureTexSource()
{
MOZ_ASSERT(mIsLocked);
if (mTexSource)
return;
mSurf->WaitSync();
mTexSource = ShSurfToTexSource(mSurf, mCompositor);
MOZ_ASSERT(mTexSource);
}
////////////////////////////////////////////////////////////////////////////////
} // namespace
} // namespace

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

@ -35,6 +35,7 @@ struct nsIntRect;
namespace mozilla {
namespace gl {
class SharedSurface;
class SurfaceStream;
}
namespace ipc {
@ -49,6 +50,7 @@ class CompositableBackendSpecificData;
class CompositableParentManager;
class SurfaceDescriptor;
class SurfaceStreamDescriptor;
class ShSurfDescriptor;
class ISurfaceAllocator;
class TextureHostOGL;
class TextureSourceOGL;
@ -615,6 +617,68 @@ protected:
RefPtr<DataTextureSource> mDataTextureSource;
};
/**
* A TextureHost for SharedSurfaces
*/
class ShSurfTexHost : public TextureHost
{
public:
ShSurfTexHost(TextureFlags aFlags, const ShSurfDescriptor& aDesc);
virtual ~ShSurfTexHost() {};
virtual void DeallocateDeviceData() MOZ_OVERRIDE {};
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE {
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE {
MOZ_ASSERT(!mIsLocked);
if (aCompositor == mCompositor)
return;
mTexSource = nullptr;
mCompositor = aCompositor;
}
public:
virtual bool Lock() MOZ_OVERRIDE {
MOZ_ASSERT(!mIsLocked);
mIsLocked = true;
EnsureTexSource();
return true;
}
virtual void Unlock() MOZ_OVERRIDE {
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
}
virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE {
MOZ_ASSERT(mIsLocked);
MOZ_ASSERT(mTexSource);
return mTexSource;
}
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() { return "ShSurfTexHost"; }
#endif
protected:
void EnsureTexSource();
bool mIsLocked;
gl::SharedSurface* const mSurf;
Compositor* mCompositor;
RefPtr<NewTextureSource> mTexSource;
};
class MOZ_STACK_CLASS AutoLockTextureHost
{
public:

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

@ -47,9 +47,6 @@ CanvasLayerD3D10::Initialize(const Data& aData)
mNeedsYFlip = true;
GLScreenBuffer* screen = mGLContext->Screen();
SurfaceStreamType streamType =
SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
screen->PreserveBuffer());
UniquePtr<SurfaceFactory> factory = nullptr;
if (!gfxPrefs::WebGLForceLayersReadback()) {
@ -60,7 +57,7 @@ CanvasLayerD3D10::Initialize(const Data& aData)
}
if (factory) {
screen->Morph(Move(factory), streamType);
screen->Morph(Move(factory));
}
} else if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;

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

@ -81,6 +81,10 @@ struct SurfaceStreamDescriptor {
bool yflip;
};
struct ShSurfDescriptor {
uintptr_t surf;
};
/**
* Used for shmem-backed YCbCr and (flavors of) RGBA textures
*/
@ -109,6 +113,7 @@ union SurfaceDescriptor {
SurfaceStreamDescriptor;
SurfaceDescriptorMacIOSurface;
NewSurfaceDescriptorGralloc;
ShSurfDescriptor;
null_t;
};