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
Родитель 6abeb68348
Коммит 8969f99b17
27 изменённых файлов: 530 добавлений и 71 удалений

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

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

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

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

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

@ -10,6 +10,10 @@
#include "GLContext.h" #include "GLContext.h"
#include "SharedSurfaceGL.h" #include "SharedSurfaceGL.h"
#include "SurfaceStream.h" #include "SurfaceStream.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#include "nsXULAppAPI.h"
#endif
using namespace mozilla::gfx; using namespace mozilla::gfx;
@ -27,7 +31,20 @@ GLScreenBuffer::Create(GLContext* gl,
return nullptr; 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* stream = SurfaceStream::CreateForType(
SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
caps.preserve), caps.preserve),

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

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

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

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

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

@ -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_ */

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

@ -36,6 +36,9 @@ const TextureFlags NewTile = 0x10;
const TextureFlags HostRelease = 0x20; const TextureFlags HostRelease = 0x20;
// The texture is part of a component-alpha pair // The texture is part of a component-alpha pair
const TextureFlags ComponentAlpha = 0x40; 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 * The kind of memory held by the texture client/host pair. This will

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

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

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

@ -11,6 +11,10 @@
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "GLContext.h" #include "GLContext.h"
#include "SurfaceStream.h" #include "SurfaceStream.h"
#include "SharedSurface.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#endif
using namespace mozilla::gl; using namespace mozilla::gl;
@ -95,9 +99,33 @@ CanvasClientWebGL::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
mTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR); mTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR);
GLScreenBuffer* screen = aLayer->mGLContext->Screen(); 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(); aLayer->Painted();
} }

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

@ -8,6 +8,9 @@
#include "SurfaceStream.h" #include "SurfaceStream.h"
#include "SharedSurfaceGL.h" #include "SharedSurfaceGL.h"
#include "SharedSurfaceEGL.h" #include "SharedSurfaceEGL.h"
#ifdef MOZ_B2G
#include "SharedSurfaceGralloc.h"
#endif
using namespace mozilla::gl; using namespace mozilla::gl;
@ -37,7 +40,12 @@ ClientCanvasLayer::Initialize(const Data& aData)
factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps()); factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
} else { } else {
// [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing) // [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 { } else {
// [Basic Layers, OMTC] WebGL layer init. // [Basic Layers, OMTC] WebGL layer init.
@ -70,6 +78,15 @@ ClientCanvasLayer::RenderLayer()
if (mNeedsYFlip) { if (mNeedsYFlip) {
flags |= NeedsYFlip; 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(), mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
ClientManager(), flags); ClientManager(), flags);
if (!mCanvasClient) { if (!mCanvasClient) {

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

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

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

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

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

@ -44,7 +44,11 @@ enum BufferCapabilities {
* The allocated buffer must be efficiently mappable as a * The allocated buffer must be efficiently mappable as a
* gfxImageSurface. * 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; class SurfaceDescriptor;
@ -114,8 +118,11 @@ protected:
gfxASurface::gfxContentType aContent, gfxASurface::gfxContentType aContent,
uint32_t aCaps, uint32_t aCaps,
SurfaceDescriptor* aBuffer); SurfaceDescriptor* aBuffer);
// method that does the actual allocation work
virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize, virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent, uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle) MaybeMagicGrallocBufferHandle* aHandle)
{ {
return nullptr; return nullptr;

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

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

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

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

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

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

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

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

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

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

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

@ -78,7 +78,8 @@ protected:
virtual bool RecvClearCachedResources() MOZ_OVERRIDE; virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
virtual PGrallocBufferParent* 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; MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
virtual bool virtual bool
DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE; DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;

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

@ -62,6 +62,17 @@ struct SurfaceDescriptorGralloc {
* prevent its consumer from mistakenly freeing the buffer. * prevent its consumer from mistakenly freeing the buffer.
*/ */
bool external; 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 { struct SurfaceStreamDescriptor {

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

@ -43,8 +43,30 @@ parent:
* Only the parent side has privileges to allocate the buffer. * Only the parent side has privileges to allocate the buffer.
* Allocation may fail (pmem is a scarce resource), and if so null_t * Allocation may fail (pmem is a scarce resource), and if so null_t
* is returned. * 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); returns (MaybeMagicGrallocBufferHandle handle);
async PLayer(); async PLayer();
async PCompositable(TextureInfo aTextureInfo); async PCompositable(TextureInfo aTextureInfo);

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

@ -146,6 +146,31 @@ PixelFormatForImageFormat(gfxASurface::gfxImageFormat aFormat)
return gfxASurface::ImageFormatARGB32; 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 static android::PixelFormat
PixelFormatForContentType(gfxASurface::gfxContentType aContentType) PixelFormatForContentType(gfxASurface::gfxContentType aContentType)
{ {
@ -197,28 +222,32 @@ GrallocBufferActor::~GrallocBufferActor()
/*static*/ PGrallocBufferParent* /*static*/ PGrallocBufferParent*
GrallocBufferActor::Create(const gfxIntSize& aSize, GrallocBufferActor::Create(const gfxIntSize& aSize,
const gfxContentType& aContent, const uint32_t& aFormat,
const uint32_t& aUsage,
MaybeMagicGrallocBufferHandle* aOutHandle) MaybeMagicGrallocBufferHandle* aOutHandle)
{ {
PROFILER_LABEL("GrallocBufferActor", "Create"); PROFILER_LABEL("GrallocBufferActor", "Create");
GrallocBufferActor* actor = new GrallocBufferActor(); GrallocBufferActor* actor = new GrallocBufferActor();
*aOutHandle = null_t(); *aOutHandle = null_t();
android::PixelFormat format = PixelFormatForContentType(aContent); uint32_t format = aFormat;
sp<GraphicBuffer> buffer( uint32_t usage = aUsage;
new GraphicBuffer(aSize.width, aSize.height, format,
GraphicBuffer::USAGE_SW_READ_OFTEN | if (format == 0 || usage == 0) {
GraphicBuffer::USAGE_SW_WRITE_OFTEN | printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero");
GraphicBuffer::USAGE_HW_TEXTURE)); return actor;
}
sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage));
if (buffer->initCheck() != OK) if (buffer->initCheck() != OK)
return actor; return actor;
size_t bpp = gfxASurface::BytePerPixelFromFormat( size_t bpp = BytesPerPixelForPixelFormat(format);
gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent));
actor->mAllocBytes = aSize.width * aSize.height * bpp; actor->mAllocBytes = aSize.width * aSize.height * bpp;
sCurrentAlloc += actor->mAllocBytes; sCurrentAlloc += actor->mAllocBytes;
actor->mGraphicBuffer = buffer; actor->mGraphicBuffer = buffer;
*aOutHandle = MagicGrallocBufferHandle(buffer); *aOutHandle = MagicGrallocBufferHandle(buffer);
return actor; return actor;
} }
@ -261,24 +290,6 @@ LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
// Nothing to be done for gralloc. // 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 bool
ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface) ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
{ {
@ -322,10 +333,11 @@ GrallocBufferActor::InitFromHandle(const MagicGrallocBufferHandle& aHandle)
PGrallocBufferChild* PGrallocBufferChild*
ShadowLayerForwarder::AllocGrallocBuffer(const gfxIntSize& aSize, ShadowLayerForwarder::AllocGrallocBuffer(const gfxIntSize& aSize,
gfxASurface::gfxContentType aContent, uint32_t aFormat,
uint32_t aUsage,
MaybeMagicGrallocBufferHandle* aHandle) MaybeMagicGrallocBufferHandle* aHandle)
{ {
return mShadowManager->SendPGrallocBufferConstructor(aSize, aContent, aHandle); return mShadowManager->SendPGrallocBufferConstructor(aSize, aFormat, aUsage, aHandle);
} }
bool bool
@ -345,7 +357,31 @@ ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
// Gralloc buffers are efficiently mappable as gfxImageSurface, so // Gralloc buffers are efficiently mappable as gfxImageSurface, so
// no need to check |aCaps & MAP_AS_IMAGE_SURFACE|. // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|.
MaybeMagicGrallocBufferHandle handle; 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) { if (!gc) {
NS_ERROR("GrallocBufferConstructor failed by returned null"); NS_ERROR("GrallocBufferConstructor failed by returned null");
return false; return false;
@ -358,7 +394,9 @@ ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc); GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
gba->InitFromHandle(handle.get_MagicGrallocBufferHandle()); gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
*aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false); *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize,
/* external */ false,
defaultRBSwap);
return true; return true;
} }

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

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

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

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

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

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

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

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

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

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