From 78cb423d30e098ef7ae0f49eb62f213503fa70d2 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Thu, 13 Feb 2014 09:46:59 -0500 Subject: [PATCH] Bug 946720 - Enable new textures at ContentClient/ContentHost classes on gonk. r=nical --- gfx/layers/client/ClientImageLayer.cpp | 7 ++ gfx/layers/client/CompositableClient.cpp | 43 +++++++ gfx/layers/client/ContentClient.cpp | 2 +- gfx/layers/client/ImageClient.cpp | 22 +++- gfx/layers/client/ImageClient.h | 3 + gfx/layers/composite/ContentHost.cpp | 2 +- gfx/layers/opengl/GrallocTextureClient.cpp | 132 ++++++++++++++++++--- gfx/layers/opengl/GrallocTextureClient.h | 23 ++-- 8 files changed, 201 insertions(+), 33 deletions(-) diff --git a/gfx/layers/client/ClientImageLayer.cpp b/gfx/layers/client/ClientImageLayer.cpp index df8c63aeefe..a4363a82739 100644 --- a/gfx/layers/client/ClientImageLayer.cpp +++ b/gfx/layers/client/ClientImageLayer.cpp @@ -108,8 +108,15 @@ protected: RefPtr surface; AutoLockImage autoLock(mContainer, &surface); +#ifdef MOZ_WIDGET_GONK + // gralloc buffer needs BUFFER_IMAGE_BUFFERED to prevent + // the buffer's usage conflict. + mImageClientTypeContainer = autoLock.GetImage() ? + BUFFER_IMAGE_BUFFERED : BUFFER_UNKNOWN; +#else mImageClientTypeContainer = autoLock.GetImage() ? BUFFER_IMAGE_SINGLE : BUFFER_UNKNOWN; +#endif return mImageClientTypeContainer; } diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index 2a4a6ef7dff..546b67f144a 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -20,6 +20,10 @@ #ifdef MOZ_X11 #include "mozilla/layers/TextureClientX11.h" #endif +#ifdef MOZ_WIDGET_GONK +#include +#include "mozilla/layers/GrallocTextureClient.h" +#endif using namespace mozilla::gfx; @@ -192,6 +196,39 @@ CompositableClient::CreateBufferTextureClient(SurfaceFormat aFormat, return result.forget(); } +#ifdef MOZ_WIDGET_GONK +static bool +DisableGralloc(SurfaceFormat aFormat) +{ + if (aFormat == gfx::SurfaceFormat::A8) { + return true; + } +#if ANDROID_VERSION <= 15 + static bool checkedDevice = false; + static bool disableGralloc = false; + + if (!checkedDevice) { + char propValue[PROPERTY_VALUE_MAX]; + property_get("ro.product.device", propValue, "None"); + + if (strcmp("crespo",propValue) == 0) { + NS_WARNING("Nexus S has issues with gralloc, falling back to shmem"); + disableGralloc = true; + } + + checkedDevice = true; + } + + if (disableGralloc) { + return true; + } + return false; +#else + return false; +#endif +} +#endif + TemporaryRef CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat, TextureFlags aTextureFlags) @@ -225,6 +262,12 @@ CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat, } #endif +#ifdef MOZ_WIDGET_GONK + if (!DisableGralloc(aFormat)) { + result = new GrallocTextureClientOGL(this, aFormat, aTextureFlags); + } +#endif + // Can't do any better than a buffer texture client. if (!result) { result = CreateBufferTextureClient(aFormat, aTextureFlags); diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index ab0582d4db8..9b83f27c5ab 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -53,7 +53,7 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder) // XXX We need support for gralloc with non-deprecated textures content before // we can use them with FirefoxOS (bug 946720). We need the same locking for // Windows. -#if !defined(MOZ_WIDGET_GONK) && !defined(XP_WIN) +#if !defined(XP_WIN) useDeprecatedTextures = gfxPlatform::GetPlatform()->UseDeprecatedTextures(); #endif diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index eeb126d3f43..055338907b1 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -124,8 +124,17 @@ ImageClientBuffered::FlushAllImages(bool aExceptFront) bool ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags) +{ + bool isSwapped = false; + return UpdateImageInternal(aContainer, aContentFlags, &isSwapped); +} + +bool +ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer, + uint32_t aContentFlags, bool* aIsSwapped) { AutoLockImage autoLock(aContainer); + *aIsSwapped = false; Image *image = autoLock.GetImage(); if (!image) { @@ -270,6 +279,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, mLastPaintedImageSerial = image->GetSerial(); aContainer->NotifyPaintedImage(image); + *aIsSwapped = true; return true; } @@ -280,7 +290,17 @@ ImageClientBuffered::UpdateImage(ImageContainer* aContainer, RefPtr temp = mFrontBuffer; mFrontBuffer = mBackBuffer; mBackBuffer = temp; - return ImageClientSingle::UpdateImage(aContainer, aContentFlags); + + bool isSwapped = false; + bool ret = ImageClientSingle::UpdateImageInternal(aContainer, aContentFlags, &isSwapped); + + if (!isSwapped) { + // If buffer swap did not happen at Host side, swap back the buffers. + RefPtr temp = mFrontBuffer; + mFrontBuffer = mBackBuffer; + mBackBuffer = temp; + } + return ret; } bool diff --git a/gfx/layers/client/ImageClient.h b/gfx/layers/client/ImageClient.h index c511d48ffb3..81f700e33d2 100644 --- a/gfx/layers/client/ImageClient.h +++ b/gfx/layers/client/ImageClient.h @@ -100,6 +100,9 @@ public: virtual void FlushAllImages(bool aExceptFront) MOZ_OVERRIDE; +protected: + virtual bool UpdateImageInternal(ImageContainer* aContainer, uint32_t aContentFlags, bool* aIsSwapped); + protected: RefPtr mFrontBuffer; // Some layers may want to enforce some flags to all their textures diff --git a/gfx/layers/composite/ContentHost.cpp b/gfx/layers/composite/ContentHost.cpp index 856a080a155..1aa7fc5151b 100644 --- a/gfx/layers/composite/ContentHost.cpp +++ b/gfx/layers/composite/ContentHost.cpp @@ -220,9 +220,9 @@ ContentHostBase::Composite(EffectChain& aEffectChain, void ContentHostBase::UseTextureHost(TextureHost* aTexture) { + CompositableHost::UseTextureHost(aTexture); mTextureHost = aTexture; mTextureHostOnWhite = nullptr; - mTextureHost->SetCompositor(GetCompositor()); } void diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp index c1de147aa18..9fc35a133c7 100644 --- a/gfx/layers/opengl/GrallocTextureClient.cpp +++ b/gfx/layers/opengl/GrallocTextureClient.cpp @@ -5,13 +5,16 @@ #ifdef MOZ_WIDGET_GONK +#include "mozilla/gfx/2D.h" #include "mozilla/layers/GrallocTextureClient.h" #include "mozilla/layers/CompositableClient.h" #include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/ShadowLayerUtilsGralloc.h" -#include "GrallocImages.h" #include "gfx2DGlue.h" +#include "gfxASurface.h" +#include "gfxImageSurface.h" // for gfxImageSurface +#include "GrallocImages.h" namespace mozilla { namespace layers { @@ -93,7 +96,6 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor, TextureFlags aFlags) : BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aFlags) , mAllocator(nullptr) -, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN) , mMappedBuffer(nullptr) { InitWith(aActor, aSize); @@ -105,7 +107,6 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(CompositableClient* aCompositab TextureFlags aFlags) : BufferTextureClient(aCompositable, aFormat, aFlags) , mAllocator(nullptr) -, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN) , mMappedBuffer(nullptr) { MOZ_COUNT_CTOR(GrallocTextureClientOGL); @@ -116,7 +117,6 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator, TextureFlags aFlags) : BufferTextureClient(nullptr, aFormat, aFlags) , mAllocator(aAllocator) -, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN) , mMappedBuffer(nullptr) { MOZ_COUNT_CTOR(GrallocTextureClientOGL); @@ -170,6 +170,32 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) return true; } + bool +GrallocTextureClientOGL::UpdateSurface(gfxASurface* aSurface) +{ + MOZ_ASSERT(aSurface); + MOZ_ASSERT(!IsImmutable()); + MOZ_ASSERT(IsValid()); + if (!IsValid() || !IsAllocated()) { + return false; + } + + if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { + RefPtr dt = GetAsDrawTarget(); + RefPtr source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aSurface); + + dt->CopySurface(source, IntRect(IntPoint(), GetSize()), IntPoint()); + } else { + nsRefPtr surf = GetAsSurface(); + nsRefPtr tmpCtx = new gfxContext(surf.get()); + tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); + tmpCtx->DrawSurface(aSurface, gfxSize(GetSize().width, + GetSize().height)); + } + + return true; +} + bool GrallocTextureClientOGL::Lock(OpenMode aMode) { @@ -177,11 +203,20 @@ GrallocTextureClientOGL::Lock(OpenMode aMode) if (!IsValid() || !IsAllocated()) { return false; } - // XXX- it would be cleaner to take the openMode into account or to check - // that aMode is coherent with mGrallocFlags (which carries more information - // than OpenMode). - int32_t rv = mGraphicBuffer->lock(mGrallocFlags, reinterpret_cast(&mMappedBuffer)); + + if (mMappedBuffer) { + return true; + } + uint32_t usage = 0; + if (aMode & OPEN_READ) { + usage |= GRALLOC_USAGE_SW_READ_OFTEN; + } + if (aMode & OPEN_WRITE) { + usage |= GRALLOC_USAGE_SW_WRITE_OFTEN; + } + int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast(&mMappedBuffer)); if (rv) { + mMappedBuffer = nullptr; NS_WARNING("Couldn't lock graphic buffer"); return false; } @@ -192,8 +227,11 @@ void GrallocTextureClientOGL::Unlock() { BufferTextureClient::Unlock(); - mMappedBuffer = nullptr; - mGraphicBuffer->unlock(); + mDrawTarget = nullptr; + if (mMappedBuffer) { + mMappedBuffer = nullptr; + mGraphicBuffer->unlock(); + } } uint8_t* @@ -204,6 +242,61 @@ GrallocTextureClientOGL::GetBuffer() const return mMappedBuffer; } +static gfx::SurfaceFormat +SurfaceFormatForPixelFormat(android::PixelFormat aFormat) +{ + switch (aFormat) { + case PIXEL_FORMAT_RGBA_8888: + return gfx::SurfaceFormat::R8G8B8A8; + case PIXEL_FORMAT_BGRA_8888: + return gfx::SurfaceFormat::B8G8R8A8; + case PIXEL_FORMAT_RGBX_8888: + return gfx::SurfaceFormat::R8G8B8X8; + case PIXEL_FORMAT_RGB_565: + return gfx::SurfaceFormat::R5G6B5; + default: + MOZ_CRASH("Unknown gralloc pixel format"); + } + return gfx::SurfaceFormat::R8G8B8A8; +} + +TemporaryRef +GrallocTextureClientOGL::GetAsDrawTarget() +{ + MOZ_ASSERT(IsValid()); + MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsDrawTarget without locking :("); + + if (mDrawTarget) { + return mDrawTarget; + } + + gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat()); + long pixelStride = mGraphicBuffer->getStride(); + long byteStride = pixelStride * BytesPerPixel(format); + mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(), + mSize, + byteStride, + mFormat); + return mDrawTarget; +} + +already_AddRefed +GrallocTextureClientOGL::GetAsSurface() +{ + MOZ_ASSERT(IsValid()); + MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsSurface without locking :("); + + gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat()); + long pixelStride = mGraphicBuffer->getStride(); + long byteStride = pixelStride * BytesPerPixel(format); + nsRefPtr surface = + new gfxImageSurface(GetBuffer(), + gfxIntSize(mSize.width, mSize.height), + byteStride, + SurfaceFormatToImageFormat(mFormat)); + return surface.forget(); +} + bool GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags) @@ -211,24 +304,31 @@ GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize, MOZ_ASSERT(IsValid()); uint32_t format; - uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN; - bool swapRB = GetFlags() & TEXTURE_RB_SWAPPED; + uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN | + android::GraphicBuffer::USAGE_SW_WRITE_OFTEN | + android::GraphicBuffer::USAGE_HW_TEXTURE; switch (mFormat) { case gfx::SurfaceFormat::R8G8B8A8: - format = swapRB ? android::PIXEL_FORMAT_BGRA_8888 : android::PIXEL_FORMAT_RGBA_8888; + format = android::PIXEL_FORMAT_RGBA_8888; break; case gfx::SurfaceFormat::B8G8R8A8: - format = swapRB ? android::PIXEL_FORMAT_RGBA_8888 : android::PIXEL_FORMAT_BGRA_8888; + format = android::PIXEL_FORMAT_RGBA_8888; + mFlags |= TEXTURE_RB_SWAPPED; break; case gfx::SurfaceFormat::R8G8B8X8: - case gfx::SurfaceFormat::B8G8R8X8: - // there is no android BGRX format? format = android::PIXEL_FORMAT_RGBX_8888; break; + case gfx::SurfaceFormat::B8G8R8X8: + format = android::PIXEL_FORMAT_RGBX_8888; + mFlags |= TEXTURE_RB_SWAPPED; + break; case gfx::SurfaceFormat::R5G6B5: format = android::PIXEL_FORMAT_RGB_565; break; + case gfx::SurfaceFormat::A8: + NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8"); + return false; default: NS_WARNING("Unsupported surface format"); return false; diff --git a/gfx/layers/opengl/GrallocTextureClient.h b/gfx/layers/opengl/GrallocTextureClient.h index 9778fe11953..40638790446 100644 --- a/gfx/layers/opengl/GrallocTextureClient.h +++ b/gfx/layers/opengl/GrallocTextureClient.h @@ -55,6 +55,8 @@ public: virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE; + virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE; + virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; void InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize); @@ -73,18 +75,12 @@ public: return mGraphicBuffer->getPixelFormat(); } - /** - * These flags are important for performances because they'll let the driver - * optimize for the right usage. - * Be sure to specify them before calling Lock. - */ - void SetGrallocOpenFlags(uint32_t aFlags) - { - mGrallocFlags = aFlags; - } - virtual uint8_t* GetBuffer() const MOZ_OVERRIDE; + virtual TemporaryRef GetAsDrawTarget() MOZ_OVERRIDE; + + virtual already_AddRefed GetAsSurface() MOZ_OVERRIDE; + virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE; @@ -116,15 +112,14 @@ protected: RefPtr mAllocator; - /** - * Flags that are used when locking the gralloc buffer - */ - uint32_t mGrallocFlags; /** * Points to a mapped gralloc buffer between calls to lock and unlock. * Should be null outside of the lock-unlock pair. */ uint8_t* mMappedBuffer; + + RefPtr mDrawTarget; + /** * android::GraphicBuffer has a size information. But there are cases * that GraphicBuffer's size and actual video's size are different.