From 931b9370529f7a8e92e32d0db5ebc0aed5de3168 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 3 Jul 2013 16:35:51 -0400 Subject: [PATCH] Bug 865104 - Support YCbCr images with BasicCompositor instead of doing the conversion on the main thread. r=nrc,nical --- gfx/layers/basic/BasicCompositor.cpp | 77 ++++++++++++++++++++++++ gfx/layers/client/CompositableClient.cpp | 4 +- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 72cbc1d2793e..8acbfe1d6f0e 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -6,6 +6,7 @@ #include "BasicCompositor.h" #include "ipc/AutoOpenSurface.h" #include "mozilla/layers/Effects.h" +#include "mozilla/layers/YCbCrImageDataSerializer.h" #include "nsIWidget.h" #include "gfx2DGlue.h" #include "gfxUtils.h" @@ -48,8 +49,11 @@ protected: mSize = IntSize(mThebesImage->Width(), mThebesImage->Height()); } + virtual void EnsureSurface() { } + virtual bool Lock() MOZ_OVERRIDE { + EnsureSurface(); if (!mSurface) { mSurface = mCompositor->GetDrawTarget()->CreateSourceSurfaceFromData(mThebesImage->Data(), mSize, @@ -74,11 +78,84 @@ protected: IntSize mSize; }; +DeserializerToPlanarYCbCrImageData(YCbCrImageDataDeserializer& aDeserializer, PlanarYCbCrImage::Data& aData) +{ + aData.mYChannel = aDeserializer.GetYData(); + aData.mYStride = aDeserializer.GetYStride(); + aData.mYSize = aDeserializer.GetYSize(); + aData.mCbChannel = aDeserializer.GetCbData(); + aData.mCrChannel = aDeserializer.GetCrData(); + aData.mCbCrStride = aDeserializer.GetCbCrStride(); + aData.mCbCrSize = aDeserializer.GetCbCrSize(); + aData.mPicSize = aDeserializer.GetYSize(); +} + +class YCbCrTextureHostBasic : public TextureSourceBasic +{ +public: + virtual void UpdateImpl(const SurfaceDescriptor& aImage, + nsIntRegion *aRegion, + nsIntPoint*) MOZ_OVERRIDE + { + MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage); + mSurface = nullptr; + ConvertImageToRGB(aImage); + } + + virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage, + nsIntRegion* aRegion) MOZ_OVERRIDE + { + MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage); + mSurface = nullptr; + } + + virtual void EnsureSurface() MOZ_OVERRIDE + { + if (!mBuffer) { + return; + } + ConvertImageToRGB(*mBuffer); + } + + void ConvertImageToRGB(const SurfaceDescriptor& aImage) + { + YCbCrImageDataDeserializer deserializer(aImage.get_YCbCrImage().data().get()); + PlanarYCbCrImage::Data data; + DeserializerToPlanarYCbCrImageData(deserializer, data); + + gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatRGB24; + gfxIntSize size; + gfxUtils::GetYCbCrToRGBDestFormatAndSize(data, format, size); + if (size.width > PlanarYCbCrImage::MAX_DIMENSION || + size.height > PlanarYCbCrImage::MAX_DIMENSION) { + NS_ERROR("Illegal image dest width or height"); + return; + } + + mThebesSurface = mThebesImage = + new gfxImageSurface(size, format); + + gfxUtils::ConvertYCbCrToRGB(data, format, size, + mThebesImage->Data(), + mThebesImage->Stride()); + + mSize = IntSize(size.width, size.height); + mFormat = + (format == gfxASurface::CONTENT_COLOR_ALPHA) ? FORMAT_B8G8R8A8 : + FORMAT_B8G8R8X8; + } + +}; + TemporaryRef CreateBasicTextureHost(SurfaceDescriptorType aDescriptorType, uint32_t aTextureHostFlags, uint32_t aTextureFlags) { + if (aDescriptorType == SurfaceDescriptor::TYCbCrImage) { + return new YCbCrTextureHostBasic(); + } + MOZ_ASSERT(aDescriptorType == SurfaceDescriptor::TShmem || aDescriptorType == SurfaceDescriptor::TMemoryImage, "We can only support Shmem currently"); diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index 44d9ba1943de..1b6fda4e9290 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -100,7 +100,9 @@ CompositableClient::CreateTextureClient(TextureClientType aTextureClientType) } break; case TEXTURE_YCBCR: - if (parentBackend == LAYERS_OPENGL || parentBackend == LAYERS_D3D11) { + if (parentBackend == LAYERS_OPENGL || + parentBackend == LAYERS_D3D11 || + parentBackend == LAYERS_BASIC) { result = new TextureClientShmemYCbCr(GetForwarder(), GetTextureInfo()); } break;