From e454ee8ae8af63c6f9f3022570fc16530e7e4a2a Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Tue, 18 Mar 2014 17:18:07 +0100 Subject: [PATCH] Bug 984437 - Backout for build bustage on a CLOSED TREE --- gfx/layers/composite/TextureHost.cpp | 8 + gfx/layers/composite/TextureHost.h | 4 +- gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp | 20 ++ gfx/layers/ipc/ShadowLayerUtilsGralloc.h | 5 + gfx/layers/opengl/TextureHostOGL.cpp | 305 +++++++++++++++++++++ gfx/layers/opengl/TextureHostOGL.h | 93 +++++++ 6 files changed, 434 insertions(+), 1 deletion(-) diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index bba79d6e5d6..c9476ce93c4 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -357,6 +357,14 @@ DeprecatedTextureHost::SwapTextures(const SurfaceDescriptor& aImage, *aResult = *mBuffer; } *mBuffer = aImage; + // The following SetBuffer call was added in bug 912725 as a fix for the + // hacky fix introduced in gecko 23 for bug 862324. + // Note that it is a no-op in the generic case, but not for + // GrallocDeprecatedTextureHostOGL which overrides SetBuffer to make it + // register the TextureHost with the GrallocBufferActor. + // The reason why this SetBuffer calls is needed here is that just above we + // overwrote *mBuffer in place, so we need to tell the new mBuffer about this + // TextureHost. SetBuffer(mBuffer, mDeAllocator); } diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 029b2ff619f..590bb9b7afe 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -761,7 +761,9 @@ public: * retain a SurfaceDescriptor. * Ownership of the SurfaceDescriptor passes to this. */ - void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator); + // only made virtual to allow overriding in GrallocDeprecatedTextureHostOGL, for hacky fix in gecko 23 for bug 862324. + // see bug 865908 about fixing this. + virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator); // used only for hacky fix in gecko 23 for bug 862324 // see bug 865908 about fixing this. diff --git a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp index e45e7da169b..ed027862538 100644 --- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp +++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp @@ -317,6 +317,11 @@ GrallocBufferActor::Create(const gfx::IntSize& aSize, void GrallocBufferActor::ActorDestroy(ActorDestroyReason) { + // used only for hacky fix for bug 862324 + for (size_t i = 0; i < mDeprecatedTextureHosts.Length(); i++) { + mDeprecatedTextureHosts[i]->ForgetBuffer(); + } + // Used only for hacky fix for bug 966446. if (mTextureHost) { mTextureHost->ForgetBufferActor(); @@ -324,6 +329,21 @@ void GrallocBufferActor::ActorDestroy(ActorDestroyReason) } } +// used only for hacky fix for bug 862324 +void GrallocBufferActor::AddDeprecatedTextureHost(DeprecatedTextureHost* aDeprecatedTextureHost) +{ + mDeprecatedTextureHosts.AppendElement(aDeprecatedTextureHost); +} + +// used only for hacky fix for bug 862324 +void GrallocBufferActor::RemoveDeprecatedTextureHost(DeprecatedTextureHost* aDeprecatedTextureHost) +{ + mDeprecatedTextureHosts.RemoveElement(aDeprecatedTextureHost); + // that should be the only occurence, otherwise we'd leak this TextureHost... + // assert that that's not happening. + MOZ_ASSERT(!mDeprecatedTextureHosts.Contains(aDeprecatedTextureHost)); +} + void GrallocBufferActor::AddTextureHost(TextureHost* aTextureHost) { mTextureHost = aTextureHost; diff --git a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h index 3d3514d4290..e6b77a1dc80 100644 --- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h +++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h @@ -85,6 +85,11 @@ public: // see bug 865908 about fixing this. void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; + // used only for hacky fix in gecko 23 for bug 862324 + // see bug 865908 about fixing this. + void AddDeprecatedTextureHost(DeprecatedTextureHost* aDeprecatedTextureHost); + void RemoveDeprecatedTextureHost(DeprecatedTextureHost* aDeprecatedTextureHost); + void AddTextureHost(TextureHost* aTextureHost); void RemoveTextureHost(); diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index 11bacf93490..58dc6d371fc 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -65,6 +65,10 @@ CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType, if (aDeprecatedTextureHostFlags & TEXTURE_HOST_TILED) { result = new TiledDeprecatedTextureHostOGL(); +#ifdef MOZ_WIDGET_GONK + } else if (aDescriptorType == SurfaceDescriptor::TSurfaceDescriptorGralloc) { + result = new GrallocDeprecatedTextureHostOGL(); +#endif } else { result = new TextureImageDeprecatedTextureHostOGL(); } @@ -922,6 +926,286 @@ TiledDeprecatedTextureHostOGL::Lock() return true; } +#ifdef MOZ_WIDGET_GONK +static gfx::SurfaceFormat +Deprecated_SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat, + bool swapRB = false) +{ + switch (aFormat) { + case android::PIXEL_FORMAT_BGRA_8888: + return swapRB ? SurfaceFormat::R8G8B8A8 : SurfaceFormat::B8G8R8A8; + case android::PIXEL_FORMAT_RGBA_8888: + return swapRB ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::R8G8B8A8; + case android::PIXEL_FORMAT_RGBX_8888: + return swapRB ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::R8G8B8X8; + case android::PIXEL_FORMAT_RGB_565: + return SurfaceFormat::R5G6B5; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + case HAL_PIXEL_FORMAT_YV12: + return SurfaceFormat::B8G8R8A8; // yup, use SurfaceFormat::B8G8R8A8 even though it's a YUV texture. This is an external texture. + default: + if (aFormat >= 0x100 && aFormat <= 0x1FF) { + // Reserved range for HAL specific formats. + return SurfaceFormat::B8G8R8A8; + } else { + // This is not super-unreachable, there's a bunch of hypothetical pixel + // formats we don't deal with. + // We only want to abort in debug builds here, since if we crash here + // we'll take down the compositor process and thus the phone. This seems + // like undesirable behaviour. We'd rather have a subtle artifact. + MOZ_ASSERT(false, "Unknown Android pixel format."); + return SurfaceFormat::UNKNOWN; + } + } +} + +static GLenum +Deprecated_TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat) +{ + switch (aFormat) { + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + case HAL_PIXEL_FORMAT_YV12: + return LOCAL_GL_TEXTURE_EXTERNAL; + case android::PIXEL_FORMAT_RGBA_8888: + case android::PIXEL_FORMAT_RGBX_8888: + case android::PIXEL_FORMAT_RGB_565: + return LOCAL_GL_TEXTURE_2D; + default: + if (aFormat >= 0x100 && aFormat <= 0x1FF) { + // Reserved range for HAL specific formats. + return LOCAL_GL_TEXTURE_EXTERNAL; + } else { + // This is not super-unreachable, there's a bunch of hypothetical pixel + // formats we don't deal with. + // We only want to abort in debug builds here, since if we crash here + // we'll take down the compositor process and thus the phone. This seems + // like undesirable behaviour. We'd rather have a subtle artifact. + MOZ_ASSERT(false, "Unknown Android pixel format."); + return LOCAL_GL_TEXTURE_EXTERNAL; + } + } +} + +GrallocDeprecatedTextureHostOGL::GrallocDeprecatedTextureHostOGL() +: mCompositor(nullptr) +, mTextureTarget(0) +, mEGLImage(0) +, mIsRBSwapped(false) +{ +} + +void GrallocDeprecatedTextureHostOGL::SetCompositor(Compositor* aCompositor) +{ + CompositorOGL* glCompositor = static_cast(aCompositor); + if (mCompositor && !glCompositor) { + DeleteTextures(); + } + mCompositor = glCompositor; +} + +gfx::SurfaceFormat +GrallocDeprecatedTextureHostOGL::GetFormat() const +{ + switch (mTextureTarget) { + case LOCAL_GL_TEXTURE_EXTERNAL: return gfx::SurfaceFormat::R8G8B8A8; + case LOCAL_GL_TEXTURE_2D: return mFormat; + default: return gfx::SurfaceFormat::UNKNOWN; + } +} + +void +GrallocDeprecatedTextureHostOGL::DeleteTextures() +{ + if (mEGLImage) { + if (gl()->MakeCurrent()) { + EGLImageDestroy(gl(), mEGLImage); + } + mEGLImage = EGL_NO_IMAGE; + } +} + +// only used for hacky fix in gecko 23 for bug 862324 +static void +AddDeprecatedTextureHostToGrallocBufferActor(DeprecatedTextureHost* aDeprecatedTextureHost, const SurfaceDescriptor* aSurfaceDescriptor) +{ + if (aSurfaceDescriptor && IsSurfaceDescriptorValid(*aSurfaceDescriptor)) { + GrallocBufferActor* actor = static_cast(aSurfaceDescriptor->get_SurfaceDescriptorGralloc().bufferParent()); + actor->AddDeprecatedTextureHost(aDeprecatedTextureHost); + } +} + +static void +RemoveDeprecatedTextureHostFromGrallocBufferActor(DeprecatedTextureHost* aDeprecatedTextureHost, const SurfaceDescriptor* aSurfaceDescriptor) +{ + if (aSurfaceDescriptor && IsSurfaceDescriptorValid(*aSurfaceDescriptor)) { + GrallocBufferActor* actor = static_cast(aSurfaceDescriptor->get_SurfaceDescriptorGralloc().bufferParent()); + actor->RemoveDeprecatedTextureHost(aDeprecatedTextureHost); + } +} + +void +GrallocDeprecatedTextureHostOGL::UpdateImpl(const SurfaceDescriptor& aImage, + nsIntRegion* aRegion, + nsIntPoint* aOffset) +{ + SwapTexturesImpl(aImage, aRegion); +} + +void +GrallocDeprecatedTextureHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage, + nsIntRegion*) +{ + MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorGralloc); + + const SurfaceDescriptorGralloc& desc = aImage.get_SurfaceDescriptorGralloc(); + mGraphicBuffer = GrallocBufferActor::GetFrom(desc); + mIsRBSwapped = desc.isRBSwapped(); + mFormat = Deprecated_SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat(), + mIsRBSwapped); + + mTextureTarget = Deprecated_TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat()); + GLuint tex = GetGLTexture(); + // delete old EGLImage + DeleteTextures(); + + if (!gl()->MakeCurrent()) { + return; + } + gl()->fActiveTexture(LOCAL_GL_TEXTURE0); + gl()->fBindTexture(mTextureTarget, tex); + // create new EGLImage + // create EGLImage during buffer swap could reduce the graphic driver's task + // during rendering. + mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer()); + gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage); + +} + +gl::GLContext* +GrallocDeprecatedTextureHostOGL::gl() const +{ + return mCompositor ? mCompositor->gl() : nullptr; +} + +void GrallocDeprecatedTextureHostOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) +{ + PROFILER_LABEL("Gralloc", "BindTexture"); + /* + * The job of this function is to ensure that the texture is tied to the + * android::GraphicBuffer, so that texturing will source the GraphicBuffer. + * + * To this effect we create an EGLImage wrapping this GraphicBuffer, + * using CreateEGLImageForNativeBuffer, and then we tie this EGLImage to our + * texture using fEGLImageTargetTexture2D. + * + * We try to avoid re-creating the EGLImage everytime, by keeping it around + * as the mEGLImage member of this class. + */ + MOZ_ASSERT(gl()); + if (!gl()->MakeCurrent()) { + return; + } + + GLuint tex = GetGLTexture(); + + gl()->fActiveTexture(aTextureUnit); + gl()->fBindTexture(mTextureTarget, tex); + ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget); +} + +bool +GrallocDeprecatedTextureHostOGL::IsValid() const +{ + return !!gl() && !!mGraphicBuffer.get(); +} + +GrallocDeprecatedTextureHostOGL::~GrallocDeprecatedTextureHostOGL() +{ + DeleteTextures(); + + // only done for hacky fix in gecko 23 for bug 862324. + // make sure that if the GrallocBufferActor survives us, it doesn't keep a dangling + // pointer to us. + RemoveDeprecatedTextureHostFromGrallocBufferActor(this, mBuffer); +} + +bool +GrallocDeprecatedTextureHostOGL::Lock() +{ + // Lock/Unlock is done internally when binding the gralloc buffer to a gl texture + return IsValid(); +} + +void +GrallocDeprecatedTextureHostOGL::Unlock() +{ + // Lock/Unlock is done internally when binding the gralloc buffer to a gl texture +} + +void +GrallocDeprecatedTextureHostOGL::SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator) +{ + MOZ_ASSERT(!mBuffer, "Will leak the old mBuffer"); + + if (aBuffer != mBuffer) { + // only done for hacky fix in gecko 23 for bug 862324. + // Doing this in SwapTextures is not enough, as the crash could occur right after SetBuffer. + RemoveDeprecatedTextureHostFromGrallocBufferActor(this, mBuffer); + AddDeprecatedTextureHostToGrallocBufferActor(this, aBuffer); + } + + mBuffer = aBuffer; + mDeAllocator = aAllocator; +} + +LayerRenderState +GrallocDeprecatedTextureHostOGL::GetRenderState() +{ + if (mGraphicBuffer.get()) { + + uint32_t flags = mFlags & TEXTURE_NEEDS_Y_FLIP ? LAYER_RENDER_STATE_Y_FLIPPED : 0; + + /* + * The 32 bit format of gralloc buffer is created as RGBA8888 or RGBX888 by default. + * For software rendering (non-GL rendering), the content is drawn with BGRA + * or BGRX. Therefore, we need to pass the RBSwapped flag for HW composer to swap format. + * + * For GL rendering content, the content format is RGBA or RGBX which is the same as + * the pixel format of gralloc buffer and no need for the RBSwapped flag. + */ + + if (mIsRBSwapped) { + flags |= LAYER_RENDER_STATE_FORMAT_RB_SWAP; + } + + nsIntSize bufferSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight()); + + return LayerRenderState(mGraphicBuffer.get(), + bufferSize, + flags, + nullptr); + } + + return LayerRenderState(); +} + +GLuint +GrallocDeprecatedTextureHostOGL::GetGLTexture() +{ + mCompositableBackendData->SetCompositor(mCompositor); + return static_cast(mCompositableBackendData.get())->GetTexture(); +} + +#endif // MOZ_WIDGET_GONK + TemporaryRef TextureImageDeprecatedTextureHostOGL::GetAsSurface() { RefPtr surf = @@ -939,5 +1223,26 @@ TiledDeprecatedTextureHostOGL::GetAsSurface() { return surf.forget(); } +#ifdef MOZ_WIDGET_GONK +TemporaryRef +GrallocDeprecatedTextureHostOGL::GetAsSurface() { + if (!gl()->MakeCurrent()) { + return nullptr; + } + GLuint tex = GetGLTexture(); + gl()->fActiveTexture(LOCAL_GL_TEXTURE0); + gl()->fBindTexture(mTextureTarget, tex); + if (!mEGLImage) { + mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer()); + } + gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage); + + RefPtr surf = + IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat()) + : nullptr; + return surf.forget(); +} +#endif // MOZ_WIDGET_GONK + } // namespace } // namespace diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 792c26cee42..330ad29be1e 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -654,6 +654,99 @@ private: nsRefPtr mGL; }; +#ifdef MOZ_WIDGET_GONK + +// For direct texturing with gralloc buffers. The corresponding DeprecatedTextureClient is DeprecatedTextureClientShmem, +// which automatically gets gralloc when it can, in which case the compositor sees that the +// SurfaceDescriptor is gralloc, and decides to use a GrallocDeprecatedTextureHostOGL to do direct texturing, +// saving the cost of a texture upload. +class GrallocDeprecatedTextureHostOGL + : public DeprecatedTextureHost + , public TextureSourceOGL +{ +public: + GrallocDeprecatedTextureHostOGL(); + + ~GrallocDeprecatedTextureHostOGL(); + + virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; + + virtual void UpdateImpl(const SurfaceDescriptor& aImage, + nsIntRegion* aRegion = nullptr, + nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE; + virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage, + nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE; + virtual bool Lock() MOZ_OVERRIDE; + virtual void Unlock() MOZ_OVERRIDE; + + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE + { + return mGraphicBuffer.get() ? gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight()) : gfx::IntSize(0, 0); + } + + virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE; + + GLenum GetWrapMode() const MOZ_OVERRIDE + { + return LOCAL_GL_CLAMP_TO_EDGE; + } + + virtual GLenum GetTextureTarget() const MOZ_OVERRIDE + { + return mTextureTarget; + } + + bool IsValid() const MOZ_OVERRIDE; + + virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE; + + virtual const char* Name() { return "GrallocDeprecatedTextureHostOGL"; } + + void BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) MOZ_OVERRIDE; + + virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE + { + return this; + } + + // only overridden for hacky fix in gecko 23 for bug 862324 + // see bug 865908 about fixing this. + virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator) MOZ_OVERRIDE; + + // used only for hacky fix in gecko 23 for bug 862324 + virtual void ForgetBuffer() + { + if (mBuffer) { + // Intentionally don't destroy the actor held by mBuffer here. + // The point is that this is only called from GrallocBufferActor::ActorDestroy + // where we know that the actor is already being deleted. + // See bug 862324 comment 39. + delete mBuffer; + mBuffer = nullptr; + } + + mGraphicBuffer = nullptr; + DeleteTextures(); + } + + virtual LayerRenderState GetRenderState() MOZ_OVERRIDE; + + GLuint GetGLTexture(); + +private: + gl::GLContext* gl() const; + + void DeleteTextures(); + + RefPtr mCompositor; + android::sp mGraphicBuffer; + GLenum mTextureTarget; + EGLImage mEGLImage; + //Set when the composer needs to swap RB pixels of gralloc buffer + bool mIsRBSwapped; +}; +#endif + } // namespace } // namespace