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
parent a784663871
commit e48648f8ea
22 changed files with 828 additions and 63 deletions

View File

@@ -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();
}
}
}