b=843599; use gralloc buffers for WebGL streaming on B2G; r=nical,jgilbert,jrmuizel

This commit is contained in:
Vladimir Vukicevic 2013-05-27 10:12:13 -04:00
parent 6abeb68348
commit 8969f99b17
27 changed files with 530 additions and 71 deletions

View File

@ -39,8 +39,8 @@ namespace layers {
VideoGraphicBuffer::VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
android::MediaBuffer *aBuffer,
SurfaceDescriptor *aDescriptor)
: GraphicBufferLocked(*aDescriptor),
SurfaceDescriptor& aDescriptor)
: GraphicBufferLocked(aDescriptor),
mMediaBuffer(aBuffer),
mOmxDecoder(aOmxDecoder)
{
@ -591,11 +591,11 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
// Change the descriptor's size to video's size. There are cases that
// GraphicBuffer's size and actual video size is different.
// See Bug 850566.
const mozilla::layers::SurfaceDescriptorGralloc& grallocDesc = descriptor->get_SurfaceDescriptorGralloc();
mozilla::layers::SurfaceDescriptor newDescriptor = mozilla::layers::SurfaceDescriptorGralloc(grallocDesc.bufferParent(),
grallocDesc.bufferChild(), nsIntSize(mVideoWidth, mVideoHeight), grallocDesc.external());
mozilla::layers::SurfaceDescriptorGralloc newDescriptor = descriptor->get_SurfaceDescriptorGralloc();
newDescriptor.size() = nsIntSize(mVideoWidth, mVideoHeight);
aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, &newDescriptor);
mozilla::layers::SurfaceDescriptor descWrapper(newDescriptor);
aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, descWrapper);
aFrame->mRotation = mVideoRotation;
aFrame->mTimeUs = timeUs;
aFrame->mKeyFrame = keyFrame;

View File

@ -27,7 +27,7 @@ class VideoGraphicBuffer : public GraphicBufferLocked {
public:
VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
android::MediaBuffer *aBuffer,
SurfaceDescriptor *aDescriptor);
SurfaceDescriptor& aDescriptor);
~VideoGraphicBuffer();
void Unlock();
};

View File

@ -10,6 +10,10 @@
#include "GLContext.h"
#include "SharedSurfaceGL.h"
#include "SurfaceStream.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#include "nsXULAppAPI.h"
#endif
using namespace mozilla::gfx;
@ -27,7 +31,20 @@ GLScreenBuffer::Create(GLContext* gl,
return nullptr;
}
SurfaceFactory_GL* factory = new SurfaceFactory_Basic(gl, caps);
SurfaceFactory_GL* factory = nullptr;
#ifdef MOZ_B2G
/* On B2G, we want a Gralloc factory, and we want one right at the start */
if (!factory &&
XRE_GetProcessType() != GeckoProcessType_Default)
{
factory = new SurfaceFactory_Gralloc(gl, caps);
}
#endif
if (!factory)
factory = new SurfaceFactory_Basic(gl, caps);
SurfaceStream* stream = SurfaceStream::CreateForType(
SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
caps.preserve),

View File

@ -37,6 +37,11 @@ CPPSRCS = \
SurfaceStream.cpp \
$(NULL)
ifdef MOZ_B2G
CPPSRCS += SharedSurfaceGralloc.cpp
EXPORTS += SharedSurfaceGralloc.h
endif
GL_PROVIDER = Null
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
@ -110,6 +115,8 @@ endif
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
DEFINES := $(filter-out -DUNICODE,$(DEFINES))
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)

View File

@ -0,0 +1,165 @@
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Preferences.h"
#include "SharedSurfaceGralloc.h"
#include "GLContext.h"
#include "SharedSurfaceGL.h"
#include "SurfaceFactory.h"
#include "GLLibraryEGL.h"
#include "mozilla/layers/ShadowLayers.h"
#include "ui/GraphicBuffer.h"
#include "../layers/ipc/ShadowLayers.h"
#define DEBUG_GRALLOC
#ifdef DEBUG_GRALLOC
#define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0)
#else
#define DEBUG_PRINT(...) do { } while (0)
#endif
using namespace mozilla;
using namespace mozilla::gfx;
using namespace gl;
using namespace layers;
using namespace android;
static bool sForceReadPixelsToFence = false;
SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
const SurfaceCaps& caps,
layers::ISurfaceAllocator* allocator)
: SurfaceFactory_GL(prodGL, SharedSurfaceType::Gralloc, caps)
{
if (!allocator) {
allocator = layers::ShadowLayerForwarder::GetActiveForwarder();
}
mAllocator = allocator;
}
SharedSurface_Gralloc*
SharedSurface_Gralloc::Create(GLContext* prodGL,
const GLFormats& formats,
const gfxIntSize& size,
bool hasAlpha,
ISurfaceAllocator* allocator)
{
static bool runOnce = true;
if (runOnce) {
sForceReadPixelsToFence = false;
mozilla::Preferences::AddBoolVarCache(&sForceReadPixelsToFence,
"gfx.gralloc.fence-with-readpixels");
runOnce = false;
}
GLLibraryEGL* egl = prodGL->GetLibraryEGL();
MOZ_ASSERT(egl);
DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
if (!HasExtensions(egl, prodGL))
return nullptr;
SurfaceDescriptor baseDesc;
SurfaceDescriptorGralloc desc;
gfxASurface::gfxContentType type = hasAlpha ? gfxASurface::CONTENT_COLOR_ALPHA
: gfxASurface::CONTENT_COLOR;
if (!allocator->AllocSurfaceDescriptorWithCaps(size, type, USING_GL_RENDERING_ONLY, &baseDesc))
return false;
if (baseDesc.type() != SurfaceDescriptor::TSurfaceDescriptorGralloc) {
allocator->DestroySharedSurface(&baseDesc);
return false;
}
desc = baseDesc.get_SurfaceDescriptorGralloc();
sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(desc);
EGLDisplay display = egl->Display();
EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
EGLint attrs[] = {
LOCAL_EGL_NONE, LOCAL_EGL_NONE
};
EGLImage image = egl->fCreateImage(display,
EGL_NO_CONTEXT,
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
clientBuffer, attrs);
if (!image) {
allocator->DestroySharedSurface(&baseDesc);
return nullptr;
}
prodGL->MakeCurrent();
GLuint prodTex = 0;
prodGL->fGenTextures(1, &prodTex);
ScopedBindTexture autoTex(prodGL, prodTex);
prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
egl->fDestroyImage(display, image);
SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, desc, prodTex);
DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get());
return surf;
}
bool
SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
{
return egl->HasKHRImageBase() &&
gl->IsExtensionSupported(GLContext::OES_EGL_image);
}
SharedSurface_Gralloc::~SharedSurface_Gralloc()
{
DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
mGL->MakeCurrent();
mGL->fDeleteTextures(1, (GLuint*)&mProdTex);
SurfaceDescriptor desc(mDesc);
mAllocator->DestroySharedSurface(&desc);
}
void
SharedSurface_Gralloc::Fence()
{
// We should be able to rely on genlock write locks/read locks.
// But they're broken on some configs, and even a glFinish doesn't
// work. glReadPixels seems to, though.
if (sForceReadPixelsToFence) {
mGL->MakeCurrent();
// read a 1x1 pixel
unsigned char pixels[4];
mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &pixels[0]);
}
}
bool
SharedSurface_Gralloc::WaitSync()
{
return true;
}
void
SharedSurface_Gralloc::LockProdImpl()
{
}
void
SharedSurface_Gralloc::UnlockProdImpl()
{
}

View File

@ -0,0 +1,111 @@
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef SHARED_SURFACE_GRALLOC_H_
#define SHARED_SURFACE_GRALLOC_H_
#include "SharedSurfaceGL.h"
#include "mozilla/layers/LayersSurfaces.h"
namespace mozilla {
namespace layers {
class ISurfaceAllocator;
class SurfaceDescriptorGralloc;
}
namespace gl {
class GLContext;
class GLLibraryEGL;
class SharedSurface_Gralloc
: public SharedSurface_GL
{
public:
static SharedSurface_Gralloc* Create(GLContext* prodGL,
const GLFormats& formats,
const gfxIntSize& size,
bool hasAlpha,
layers::ISurfaceAllocator* allocator);
static SharedSurface_Gralloc* Cast(SharedSurface* surf) {
MOZ_ASSERT(surf->Type() == SharedSurfaceType::Gralloc);
return (SharedSurface_Gralloc*)surf;
}
protected:
GLLibraryEGL* const mEGL;
layers::ISurfaceAllocator* const mAllocator;
// We keep the SurfaceDescriptor around, because we'll end up
// using it often and it's handy to do so. The actual
// GraphicBuffer is kept alive by the sp<GraphicBuffer> in
// GrallocBufferActor; the actor will stay alive until we
// explicitly destroy this descriptor (and thus deallocate the
// actor) it in the destructor of this class. This is okay to do
// on the client, but is very bad to do on the server (because on
// the client, the actor has no chance of going away unless the
// whole app died).
layers::SurfaceDescriptorGralloc mDesc;
const GLuint mProdTex;
SharedSurface_Gralloc(GLContext* prodGL,
const gfxIntSize& size,
bool hasAlpha,
GLLibraryEGL* egl,
layers::ISurfaceAllocator* allocator,
layers::SurfaceDescriptorGralloc& desc,
GLuint prodTex)
: SharedSurface_GL(SharedSurfaceType::Gralloc,
AttachmentType::GLTexture,
prodGL,
size,
hasAlpha)
, mEGL(egl)
, mAllocator(allocator)
, mDesc(desc)
, mProdTex(prodTex)
{}
static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
public:
virtual ~SharedSurface_Gralloc();
virtual void Fence();
virtual bool WaitSync();
virtual void LockProdImpl();
virtual void UnlockProdImpl();
virtual GLuint Texture() const {
return mProdTex;
}
layers::SurfaceDescriptorGralloc& GetDescriptor() {
return mDesc;
}
};
class SurfaceFactory_Gralloc
: public SurfaceFactory_GL
{
protected:
layers::ISurfaceAllocator* mAllocator;
public:
SurfaceFactory_Gralloc(GLContext* prodGL,
const SurfaceCaps& caps,
layers::ISurfaceAllocator* allocator = nullptr);
virtual SharedSurface* CreateShared(const gfxIntSize& size) {
bool hasAlpha = mReadCaps.alpha;
return SharedSurface_Gralloc::Create(mGL, mFormats, size, hasAlpha, mAllocator);
}
};
} /* namespace gl */
} /* namespace mozilla */
#endif /* SHARED_SURFACE_GRALLOC_H_ */

View File

@ -36,6 +36,9 @@ const TextureFlags NewTile = 0x10;
const TextureFlags HostRelease = 0x20;
// The texture is part of a component-alpha pair
const TextureFlags ComponentAlpha = 0x40;
// The shared resources are owned by client
const TextureFlags OwnByClient = 0x80;
/**
* The kind of memory held by the texture client/host pair. This will

View File

@ -14,6 +14,9 @@
#include "SurfaceStream.h"
#include "SharedSurfaceGL.h"
#include "SharedSurfaceEGL.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#endif
#include "GeckoProfiler.h"
#include "nsXULAppAPI.h"

View File

@ -11,6 +11,10 @@
#include "nsXULAppAPI.h"
#include "GLContext.h"
#include "SurfaceStream.h"
#include "SharedSurface.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#endif
using namespace mozilla::gl;
@ -95,9 +99,33 @@ CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
mTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR);
GLScreenBuffer* screen = aLayer->mGLContext->Screen();
SurfaceStreamHandle handle = screen->Stream()->GetShareHandle();
SurfaceStream* stream = screen->Stream();
mTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
if (isCrossProcess) {
// swap staging -> consumer so we can send it to the compositor
SharedSurface* surf = stream->SwapConsumer();
if (!surf) {
printf_stderr("surf is null post-SwapConsumer!\n");
return;
}
#ifdef MOZ_B2G
if (surf->Type() != SharedSurfaceType::Gralloc) {
printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
return;
}
SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
mTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
#else
printf_stderr("isCrossProcess, but not MOZ_B2G! Someone needs to write some code!");
MOZ_ASSERT(false);
#endif
} else {
SurfaceStreamHandle handle = stream->GetShareHandle();
mTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
}
aLayer->Painted();
}

View File

@ -8,6 +8,9 @@
#include "SurfaceStream.h"
#include "SharedSurfaceGL.h"
#include "SharedSurfaceEGL.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#endif
using namespace mozilla::gl;
@ -37,7 +40,12 @@ ClientCanvasLayer::Initialize(const Data& aData)
factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
} else {
// [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
// Fall back to readback.
#ifdef MOZ_B2G
factory = new SurfaceFactory_Gralloc(mGLContext, screen->Caps(), ClientManager());
#else
// we could do readback here maybe
NS_NOTREACHED("isCrossProcess but not on B2G!");
#endif
}
} else {
// [Basic Layers, OMTC] WebGL layer init.
@ -70,6 +78,15 @@ ClientCanvasLayer::RenderLayer()
if (mNeedsYFlip) {
flags |= NeedsYFlip;
}
bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
//Append OwnByClient flag for streaming buffer under OOPC case
if (isCrossProcess && mGLContext) {
GLScreenBuffer* screen = mGLContext->Screen();
if (screen && screen->Stream()) {
flags |= OwnByClient;
}
}
mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
ClientManager(), flags);
if (!mCanvasClient) {

View File

@ -73,7 +73,7 @@ protected:
CompositableType GetCompositableClientType()
{
if (mGLContext && XRE_GetProcessType() == GeckoProcessType_Default) {
if (mGLContext) {
return BUFFER_IMAGE_BUFFERED;
}
return BUFFER_IMAGE_SINGLE;

View File

@ -77,10 +77,12 @@ TextureHost::TextureHost()
TextureHost::~TextureHost()
{
if (mBuffer) {
if (mDeAllocator) {
mDeAllocator->DestroySharedSurface(mBuffer);
} else {
MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
if (!(mFlags & OwnByClient)) {
if (mDeAllocator) {
mDeAllocator->DestroySharedSurface(mBuffer);
} else {
MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
}
}
delete mBuffer;
}

View File

@ -44,7 +44,11 @@ enum BufferCapabilities {
* The allocated buffer must be efficiently mappable as a
* gfxImageSurface.
*/
MAP_AS_IMAGE_SURFACE = 1 << 0
MAP_AS_IMAGE_SURFACE = 1 << 0,
/**
* The allocated buffer will be used for GL rendering only
*/
USING_GL_RENDERING_ONLY = 1 << 1
};
class SurfaceDescriptor;
@ -114,8 +118,11 @@ protected:
gfxASurface::gfxContentType aContent,
uint32_t aCaps,
SurfaceDescriptor* aBuffer);
// method that does the actual allocation work
virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent,
uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle)
{
return nullptr;

View File

@ -577,7 +577,7 @@ ImageBridgeChild::AllocSurfaceDescriptorGrallocNow(const gfxIntSize& aSize,
GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
*aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false);
*aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false, /* swapRB */ false);
return true;
#else
NS_RUNTIMEABORT("No gralloc buffers for you");
@ -744,13 +744,14 @@ ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
PGrallocBufferChild*
ImageBridgeChild::AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent,
uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle)
{
#ifdef MOZ_WIDGET_GONK
return SendPGrallocBufferConstructor(aSize,
aContent,
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
aFormat,
aUsage,
aHandle);
#else
NS_RUNTIMEABORT("not implemented");

View File

@ -199,7 +199,7 @@ public:
*/
bool
AllocSurfaceDescriptorGrallocNow(const gfxIntSize& aSize,
const uint32_t& aContent,
const uint32_t& aFormat,
const uint32_t& aUsage,
SurfaceDescriptor* aBuffer);
@ -337,8 +337,9 @@ protected:
CompositableTransaction* mTxn;
// ISurfaceAllocator
virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent,
uint32_t aFormat, uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
};

View File

@ -24,8 +24,9 @@ LayerTransactionChild::Destroy()
PGrallocBufferChild*
LayerTransactionChild::AllocPGrallocBuffer(const gfxIntSize&,
const gfxContentType&,
MaybeMagicGrallocBufferHandle*)
const uint32_t&,
const uint32_t&,
MaybeMagicGrallocBufferHandle*)
{
#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
return GrallocBufferActor::Create();

View File

@ -30,7 +30,8 @@ public:
protected:
virtual PGrallocBufferChild*
AllocPGrallocBuffer(const gfxIntSize&, const gfxContentType&,
AllocPGrallocBuffer(const gfxIntSize&,
const uint32_t&, const uint32_t&,
MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
virtual bool
DeallocPGrallocBuffer(PGrallocBufferChild* actor) MOZ_OVERRIDE;

View File

@ -464,11 +464,12 @@ LayerTransactionParent::RecvClearCachedResources()
PGrallocBufferParent*
LayerTransactionParent::AllocPGrallocBuffer(const gfxIntSize& aSize,
const gfxContentType& aContent,
const uint32_t& aFormat,
const uint32_t& aUsage,
MaybeMagicGrallocBufferHandle* aOutHandle)
{
#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
return GrallocBufferActor::Create(aSize, aContent, aOutHandle);
return GrallocBufferActor::Create(aSize, aFormat, aUsage, aOutHandle);
#else
NS_RUNTIMEABORT("No gralloc buffers for you");
return nullptr;

View File

@ -78,7 +78,8 @@ protected:
virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
virtual PGrallocBufferParent*
AllocPGrallocBuffer(const gfxIntSize& aSize, const gfxContentType& aContent,
AllocPGrallocBuffer(const gfxIntSize& aSize,
const uint32_t& aFormat, const uint32_t& aUsage,
MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
virtual bool
DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;

View File

@ -62,6 +62,17 @@ struct SurfaceDescriptorGralloc {
* prevent its consumer from mistakenly freeing the buffer.
*/
bool external;
/**
* This gralloc buffer will be treated as if the RB bytes are swapped.
* This is useful for rendering using Cairo/Thebes, because there is no
* BGRX Android pixel format, and so we have to do byte swapping.
*
* For example, if the GraphicBuffer has an Android pixel format of
* PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
* (for example, with GL), a BGRA shader should be used.
*/
bool isRBSwapped;
};
struct SurfaceStreamDescriptor {

View File

@ -43,8 +43,30 @@ parent:
* Only the parent side has privileges to allocate the buffer.
* Allocation may fail (pmem is a scarce resource), and if so null_t
* is returned.
*
* |format| is an Android PixelFormat (see PixelFormat.h)
*
* commonly used PixelFormats are:
* PIXEL_FORMAT_RGBA_8888
* PIXEL_FORMAT_RGBX_8888
* PIXEL_FORMAT_BGRA_8888
*
* Note that SurfaceDescriptorGralloc has a "isRBSwapped" boolean
* that can treat the R/B bytes as swapped when they are rendered
* to the screen, to help with matching the native pixel format
* of other rendering engines.
*
* |usage| is a USAGE_* mask (see GraphicBuffer.h)
*
* commonly used USAGE flags are:
* USAGE_SW_READ_OFTEN | USAGE_SW_WRITE_OFTEN | USAGE_HW_TEXTURE
* - used for software rendering to a buffer which the compositor
* treats as a texture
* USAGE_HW_RENDER | USAGE_HW_TEXTURE
* - used for GL rendering to a buffer which the compositor
* treats as a texture
*/
sync PGrallocBuffer(gfxIntSize size, gfxContentType content)
sync PGrallocBuffer(gfxIntSize size, uint32_t format, uint32_t usage)
returns (MaybeMagicGrallocBufferHandle handle);
async PLayer();
async PCompositable(TextureInfo aTextureInfo);

View File

@ -146,6 +146,31 @@ PixelFormatForImageFormat(gfxASurface::gfxImageFormat aFormat)
return gfxASurface::ImageFormatARGB32;
}
static size_t
BytesPerPixelForPixelFormat(android::PixelFormat aFormat)
{
switch (aFormat) {
case PIXEL_FORMAT_RGBA_8888:
case PIXEL_FORMAT_RGBX_8888:
case PIXEL_FORMAT_BGRA_8888:
return 4;
case PIXEL_FORMAT_RGB_888:
return 3;
case PIXEL_FORMAT_RGB_565:
case PIXEL_FORMAT_RGBA_5551:
case PIXEL_FORMAT_RGBA_4444:
case PIXEL_FORMAT_LA_88:
return 2;
case PIXEL_FORMAT_L_8:
case PIXEL_FORMAT_A_8:
case PIXEL_FORMAT_RGB_332:
return 1;
default:
MOZ_NOT_REACHED("Unknown gralloc pixel format");
}
return gfxASurface::ImageFormatARGB32;
}
static android::PixelFormat
PixelFormatForContentType(gfxASurface::gfxContentType aContentType)
{
@ -197,28 +222,32 @@ GrallocBufferActor::~GrallocBufferActor()
/*static*/ PGrallocBufferParent*
GrallocBufferActor::Create(const gfxIntSize& aSize,
const gfxContentType& aContent,
const uint32_t& aFormat,
const uint32_t& aUsage,
MaybeMagicGrallocBufferHandle* aOutHandle)
{
PROFILER_LABEL("GrallocBufferActor", "Create");
GrallocBufferActor* actor = new GrallocBufferActor();
*aOutHandle = null_t();
android::PixelFormat format = PixelFormatForContentType(aContent);
sp<GraphicBuffer> buffer(
new GraphicBuffer(aSize.width, aSize.height, format,
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE));
uint32_t format = aFormat;
uint32_t usage = aUsage;
if (format == 0 || usage == 0) {
printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero");
return actor;
}
sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage));
if (buffer->initCheck() != OK)
return actor;
size_t bpp = gfxASurface::BytePerPixelFromFormat(
gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent));
size_t bpp = BytesPerPixelForPixelFormat(format);
actor->mAllocBytes = aSize.width * aSize.height * bpp;
sCurrentAlloc += actor->mAllocBytes;
actor->mGraphicBuffer = buffer;
*aOutHandle = MagicGrallocBufferHandle(buffer);
return actor;
}
@ -261,24 +290,6 @@ LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
// Nothing to be done for gralloc.
}
/*static*/ PGrallocBufferParent*
GrallocBufferActor::Create(const gfxIntSize& aSize,
const uint32_t& aFormat,
const uint32_t& aUsage,
MaybeMagicGrallocBufferHandle* aOutHandle)
{
GrallocBufferActor* actor = new GrallocBufferActor();
*aOutHandle = null_t();
sp<GraphicBuffer> buffer(
new GraphicBuffer(aSize.width, aSize.height, aFormat, aUsage));
if (buffer->initCheck() != OK)
return actor;
actor->mGraphicBuffer = buffer;
*aOutHandle = MagicGrallocBufferHandle(buffer);
return actor;
}
bool
ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
{
@ -322,10 +333,11 @@ GrallocBufferActor::InitFromHandle(const MagicGrallocBufferHandle& aHandle)
PGrallocBufferChild*
ShadowLayerForwarder::AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent,
uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle)
{
return mShadowManager->SendPGrallocBufferConstructor(aSize, aContent, aHandle);
return mShadowManager->SendPGrallocBufferConstructor(aSize, aFormat, aUsage, aHandle);
}
bool
@ -345,7 +357,31 @@ ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
// Gralloc buffers are efficiently mappable as gfxImageSurface, so
// no need to check |aCaps & MAP_AS_IMAGE_SURFACE|.
MaybeMagicGrallocBufferHandle handle;
PGrallocBufferChild* gc = AllocGrallocBuffer(aSize, aContent, &handle);
PGrallocBufferChild* gc;
bool defaultRBSwap;
if (aCaps & USING_GL_RENDERING_ONLY) {
gc = AllocGrallocBuffer(aSize,
PixelFormatForContentType(aContent),
GraphicBuffer::USAGE_HW_RENDER |
GraphicBuffer::USAGE_HW_TEXTURE,
&handle);
// If you're allocating for USING_GL_RENDERING_ONLY, then we don't flag
// this for RB swap.
defaultRBSwap = false;
} else {
gc = AllocGrallocBuffer(aSize,
PixelFormatForContentType(aContent),
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE,
&handle);
// But if you're allocating for non-GL-only rendering, we flag for
// RB swap to preserve old behaviour and proper interaction with
// cairo.
defaultRBSwap = true;
}
if (!gc) {
NS_ERROR("GrallocBufferConstructor failed by returned null");
return false;
@ -358,7 +394,9 @@ ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
*aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false);
*aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize,
/* external */ false,
defaultRBSwap);
return true;
}

View File

@ -71,10 +71,6 @@ class GrallocBufferActor : public PGrallocBufferChild
public:
virtual ~GrallocBufferActor();
static PGrallocBufferParent*
Create(const gfxIntSize& aSize, const gfxContentType& aContent,
MaybeMagicGrallocBufferHandle* aOutHandle);
static PGrallocBufferParent*
Create(const gfxIntSize& aSize, const uint32_t& aFormat, const uint32_t& aUsage,
MaybeMagicGrallocBufferHandle* aOutHandle);

View File

@ -36,6 +36,9 @@ using namespace mozilla::dom;
namespace mozilla {
namespace layers {
// static
ShadowLayerForwarder* ShadowLayerForwarder::sActiveForwarder = nullptr;
typedef nsTArray<SurfaceDescriptor> BufferArray;
typedef std::vector<Edit> EditVector;
typedef std::set<ShadowableLayer*> ShadowableLayerSet;
@ -170,12 +173,18 @@ ShadowLayerForwarder::ShadowLayerForwarder()
, mDrawColoredBorders(false)
{
mTxn = new Transaction();
MOZ_ASSERT(!sActiveForwarder);
sActiveForwarder = this;
}
ShadowLayerForwarder::~ShadowLayerForwarder()
{
NS_ABORT_IF_FALSE(mTxn->Finished(), "unfinished transaction?");
delete mTxn;
MOZ_ASSERT(this == sActiveForwarder);
sActiveForwarder = nullptr;
}
void

View File

@ -138,6 +138,14 @@ class ShadowLayerForwarder : public CompositableForwarder
friend class TextureClientShmem;
friend class ContentClientIncremental;
private:
static ShadowLayerForwarder* sActiveForwarder;
public:
static ShadowLayerForwarder* GetActiveForwarder() {
return sActiveForwarder;
}
public:
virtual ~ShadowLayerForwarder();
@ -388,8 +396,10 @@ protected:
PLayerTransactionChild* mShadowManager;
#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
// from ISurfaceAllocator
virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent,
uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
#endif

View File

@ -639,13 +639,16 @@ TiledTextureHostOGL::Lock()
#ifdef MOZ_WIDGET_GONK
static gfx::SurfaceFormat
SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat)
SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
bool swapRB = false)
{
switch (aFormat) {
case android::PIXEL_FORMAT_BGRA_8888:
return swapRB ? FORMAT_R8G8B8A8 : FORMAT_B8G8R8A8;
case android::PIXEL_FORMAT_RGBA_8888:
return FORMAT_B8G8R8A8;
return swapRB ? FORMAT_B8G8R8A8 : FORMAT_R8G8B8A8;
case android::PIXEL_FORMAT_RGBX_8888:
return FORMAT_B8G8R8X8;
return swapRB ? FORMAT_B8G8R8X8 : FORMAT_R8G8B8X8;
case android::PIXEL_FORMAT_RGB_565:
return FORMAT_R5G6B5;
case android::PIXEL_FORMAT_A_8:
@ -757,7 +760,8 @@ GrallocTextureHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage,
const SurfaceDescriptorGralloc& desc = aImage.get_SurfaceDescriptorGralloc();
mGraphicBuffer = GrallocBufferActor::GetFrom(desc);
mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat(),
desc.isRBSwapped());
mTextureTarget = TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
DeleteTextures();

View File

@ -3957,6 +3957,9 @@ pref("webgl.default-no-alpha", false);
pref("webgl.force-layers-readback", false);
pref("webgl.lose-context-on-heap-minimize", false);
pref("webgl.can-lose-context-in-foreground", true);
#ifdef MOZ_B2G
pref("gfx.gralloc.fence-with-readpixels", false);
#endif
// Stagefright prefs
pref("stagefright.force-enabled", false);