michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_GFX_TEXTUREOGL_H michael@0: #define MOZILLA_GFX_TEXTUREOGL_H michael@0: michael@0: #include // for size_t michael@0: #include // for uint64_t michael@0: #include "CompositableHost.h" michael@0: #include "GLContextTypes.h" // for GLContext michael@0: #include "GLDefs.h" // for GLenum, LOCAL_GL_CLAMP_TO_EDGE, etc michael@0: #include "GLTextureImage.h" // for TextureImage michael@0: #include "gfxTypes.h" michael@0: #include "mozilla/GfxMessageUtils.h" // for gfxContentType michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/Attributes.h" // for MOZ_OVERRIDE michael@0: #include "mozilla/RefPtr.h" // for RefPtr michael@0: #include "mozilla/gfx/Matrix.h" // for Matrix4x4 michael@0: #include "mozilla/gfx/Point.h" // for IntSize, IntPoint michael@0: #include "mozilla/gfx/Types.h" // for SurfaceFormat, etc michael@0: #include "mozilla/layers/CompositorTypes.h" // for TextureFlags michael@0: #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor michael@0: #include "mozilla/layers/TextureHost.h" // for TextureHost, etc michael@0: #include "mozilla/mozalloc.h" // for operator delete, etc michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsCOMPtr.h" // for already_AddRefed michael@0: #include "nsDebug.h" // for NS_WARNING michael@0: #include "nsISupportsImpl.h" // for TextureImage::Release, etc michael@0: #include "OGLShaderProgram.h" // for ShaderProgramType, etc michael@0: #ifdef MOZ_WIDGET_GONK michael@0: #include michael@0: #if ANDROID_VERSION >= 17 michael@0: #include michael@0: #endif michael@0: #endif michael@0: michael@0: class gfxReusableSurfaceWrapper; michael@0: class nsIntRegion; michael@0: struct nsIntPoint; michael@0: struct nsIntRect; michael@0: struct nsIntSize; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: class DataSourceSurface; michael@0: class SurfaceStream; michael@0: } michael@0: michael@0: namespace layers { michael@0: michael@0: class Compositor; michael@0: class CompositorOGL; michael@0: class TextureImageTextureSourceOGL; michael@0: michael@0: /** michael@0: * CompositableBackendSpecificData implementation for the Gonk OpenGL backend. michael@0: * Share a same texture between TextureHosts in the same CompositableHost. michael@0: * By shareing the texture among the TextureHosts, number of texture allocations michael@0: * can be reduced than texture allocation in every TextureHosts. michael@0: * From Bug 912134, use only one texture among all TextureHosts degrade michael@0: * the rendering performance. michael@0: * CompositableDataGonkOGL chooses in a middile of them. michael@0: */ michael@0: class CompositableDataGonkOGL : public CompositableBackendSpecificData michael@0: { michael@0: public: michael@0: CompositableDataGonkOGL(); michael@0: virtual ~CompositableDataGonkOGL(); michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: virtual void ClearData() MOZ_OVERRIDE; michael@0: GLuint GetTexture(); michael@0: void DeleteTextureIfPresent(); michael@0: gl::GLContext* gl() const; michael@0: protected: michael@0: RefPtr mCompositor; michael@0: GLuint mTexture; michael@0: }; michael@0: michael@0: inline void ApplyFilterToBoundTexture(gl::GLContext* aGL, michael@0: gfx::Filter aFilter, michael@0: GLuint aTarget = LOCAL_GL_TEXTURE_2D) michael@0: { michael@0: GLenum filter = michael@0: (aFilter == gfx::Filter::POINT ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR); michael@0: michael@0: aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter); michael@0: aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter); michael@0: } michael@0: michael@0: /* michael@0: * TextureHost implementations for the OpenGL backend. michael@0: * michael@0: * Note that it is important to be careful about the ownership model with michael@0: * the OpenGL backend, due to some widget limitation on Linux: before michael@0: * the nsBaseWidget associated with our OpenGL context has been completely michael@0: * deleted, every resource belonging to the OpenGL context MUST have been michael@0: * released. At the moment the teardown sequence happens in the middle of michael@0: * the nsBaseWidget's destructor, meaning that at a given moment we must be michael@0: * able to easily find and release all the GL resources. michael@0: * The point is: be careful about the ownership model and limit the number michael@0: * of objects sharing references to GL resources to make the tear down michael@0: * sequence as simple as possible. michael@0: */ michael@0: michael@0: /** michael@0: * TextureSourceOGL provides the necessary API for CompositorOGL to composite michael@0: * a TextureSource. michael@0: */ michael@0: class TextureSourceOGL michael@0: { michael@0: public: michael@0: TextureSourceOGL() michael@0: : mHasCachedFilter(false) michael@0: {} michael@0: michael@0: virtual bool IsValid() const = 0; michael@0: michael@0: virtual void BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) = 0; michael@0: michael@0: virtual gfx::IntSize GetSize() const = 0; michael@0: michael@0: virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_2D; } michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const = 0; michael@0: michael@0: virtual GLenum GetWrapMode() const = 0; michael@0: michael@0: virtual gfx::Matrix4x4 GetTextureTransform() { return gfx::Matrix4x4(); } michael@0: michael@0: virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() { return nullptr; } michael@0: michael@0: void SetFilter(gl::GLContext* aGL, gfx::Filter aFilter) michael@0: { michael@0: if (mHasCachedFilter && michael@0: mCachedFilter == aFilter) { michael@0: return; michael@0: } michael@0: mHasCachedFilter = true; michael@0: mCachedFilter = aFilter; michael@0: ApplyFilterToBoundTexture(aGL, aFilter, GetTextureTarget()); michael@0: } michael@0: michael@0: void ClearCachedFilter() { mHasCachedFilter = false; } michael@0: michael@0: private: michael@0: gfx::Filter mCachedFilter; michael@0: bool mHasCachedFilter; michael@0: }; michael@0: michael@0: /** michael@0: * TextureHostOGL provides the necessary API for platform specific composition. michael@0: */ michael@0: class TextureHostOGL michael@0: { michael@0: public: michael@0: #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 michael@0: michael@0: /** michael@0: * Store a fence that will signal when the current buffer is no longer being read. michael@0: * Similar to android's GLConsumer::setReleaseFence() michael@0: */ michael@0: virtual bool SetReleaseFence(const android::sp& aReleaseFence); michael@0: michael@0: /** michael@0: * Return a releaseFence's Fence and clear a reference to the Fence. michael@0: */ michael@0: virtual android::sp GetAndResetReleaseFence(); michael@0: michael@0: protected: michael@0: android::sp mReleaseFence; michael@0: michael@0: /** michael@0: * Hold previous ReleaseFence to prevent Fence delivery failure via gecko IPC. michael@0: * Fence is a kernel object and its lifetime is managed by a reference count. michael@0: * Until the Fence is delivered to client side, need to hold Fence on host side. michael@0: */ michael@0: android::sp mPrevReleaseFence; michael@0: #endif michael@0: }; michael@0: michael@0: /** michael@0: * A TextureSource backed by a TextureImage. michael@0: * michael@0: * Depending on the underlying TextureImage, may support texture tiling, so michael@0: * make sure to check AsTileIterator() and use the texture accordingly. michael@0: * michael@0: * This TextureSource can be used without a TextureHost and manage it's own michael@0: * GL texture(s). michael@0: */ michael@0: class TextureImageTextureSourceOGL : public DataTextureSource michael@0: , public TextureSourceOGL michael@0: , public TileIterator michael@0: { michael@0: public: michael@0: TextureImageTextureSourceOGL(gl::GLContext* aGL, michael@0: TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) michael@0: : mGL(aGL) michael@0: , mFlags(aFlags) michael@0: , mIterating(false) michael@0: {} michael@0: michael@0: // DataTextureSource michael@0: michael@0: virtual bool Update(gfx::DataSourceSurface* aSurface, michael@0: nsIntRegion* aDestRegion = nullptr, michael@0: gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE; michael@0: michael@0: void EnsureBuffer(const nsIntSize& aSize, michael@0: gfxContentType aContentType); michael@0: michael@0: void CopyTo(const nsIntRect& aSourceRect, michael@0: DataTextureSource* aDest, michael@0: const nsIntRect& aDestRect); michael@0: michael@0: virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() { return this; } michael@0: michael@0: // TextureSource michael@0: michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE michael@0: { michael@0: mTexImage = nullptr; michael@0: SetUpdateSerial(0); michael@0: } michael@0: michael@0: virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; } michael@0: michael@0: virtual void BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsValid() const MOZ_OVERRIDE { return !!mTexImage; } michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: virtual GLenum GetWrapMode() const MOZ_OVERRIDE michael@0: { michael@0: return mTexImage->GetWrapMode(); michael@0: } michael@0: michael@0: // TileIterator michael@0: michael@0: virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return this; } michael@0: michael@0: virtual void BeginTileIteration() MOZ_OVERRIDE michael@0: { michael@0: mTexImage->BeginTileIteration(); michael@0: mIterating = true; michael@0: } michael@0: michael@0: virtual void EndTileIteration() MOZ_OVERRIDE michael@0: { michael@0: mIterating = false; michael@0: } michael@0: michael@0: virtual nsIntRect GetTileRect() MOZ_OVERRIDE; michael@0: michael@0: virtual size_t GetTileCount() MOZ_OVERRIDE michael@0: { michael@0: return mTexImage->GetTileCount(); michael@0: } michael@0: michael@0: virtual bool NextTile() MOZ_OVERRIDE michael@0: { michael@0: return mTexImage->NextTile(); michael@0: } michael@0: michael@0: protected: michael@0: nsRefPtr mTexImage; michael@0: gl::GLContext* mGL; michael@0: TextureFlags mFlags; michael@0: bool mIterating; michael@0: }; michael@0: michael@0: /** michael@0: * A texture source meant for use with SharedTextureHostOGL. michael@0: * michael@0: * It does not own any GL texture, and attaches its shared handle to one of michael@0: * the compositor's temporary textures when binding. michael@0: * michael@0: * The shared texture handle is owned by the TextureHost. michael@0: */ michael@0: class SharedTextureSourceOGL : public NewTextureSource michael@0: , public TextureSourceOGL michael@0: { michael@0: public: michael@0: typedef gl::SharedTextureShareType SharedTextureShareType; michael@0: michael@0: SharedTextureSourceOGL(CompositorOGL* aCompositor, michael@0: gl::SharedTextureHandle aHandle, michael@0: gfx::SurfaceFormat aFormat, michael@0: GLenum aTarget, michael@0: GLenum aWrapMode, michael@0: SharedTextureShareType aShareType, michael@0: gfx::IntSize aSize); michael@0: michael@0: virtual TextureSourceOGL* AsSourceOGL() { return this; } michael@0: michael@0: virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsValid() const MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } michael@0: michael@0: virtual gfx::Matrix4x4 GetTextureTransform() MOZ_OVERRIDE; michael@0: michael@0: virtual GLenum GetTextureTarget() const { return mTextureTarget; } michael@0: michael@0: virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; } michael@0: michael@0: // SharedTextureSource doesn't own any gl texture michael@0: virtual void DeallocateDeviceData() {} michael@0: michael@0: void DetachSharedHandle(); michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: gl::GLContext* gl() const; michael@0: michael@0: protected: michael@0: gfx::IntSize mSize; michael@0: CompositorOGL* mCompositor; michael@0: gl::SharedTextureHandle mSharedHandle; michael@0: gfx::SurfaceFormat mFormat; michael@0: SharedTextureShareType mShareType; michael@0: GLenum mTextureTarget; michael@0: GLenum mWrapMode; michael@0: }; michael@0: michael@0: /** michael@0: * A TextureHost for shared GL Textures michael@0: * michael@0: * Most of the logic actually happens in SharedTextureSourceOGL. michael@0: */ michael@0: class SharedTextureHostOGL : public TextureHost michael@0: { michael@0: public: michael@0: SharedTextureHostOGL(TextureFlags aFlags, michael@0: gl::SharedTextureShareType aShareType, michael@0: gl::SharedTextureHandle aSharedhandle, michael@0: gfx::IntSize aSize, michael@0: bool inverted); michael@0: michael@0: virtual ~SharedTextureHostOGL(); michael@0: michael@0: // SharedTextureHostOGL doesn't own any GL texture michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE {} michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: virtual bool Lock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE; michael@0: michael@0: virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE michael@0: { michael@0: return mTextureSource; michael@0: } michael@0: michael@0: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE michael@0: { michael@0: return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) michael@0: } michael@0: michael@0: gl::GLContext* gl() const; michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual const char* Name() { return "SharedTextureHostOGL"; } michael@0: michael@0: protected: michael@0: gfx::IntSize mSize; michael@0: CompositorOGL* mCompositor; michael@0: gl::SharedTextureHandle mSharedHandle; michael@0: gl::SharedTextureShareType mShareType; michael@0: michael@0: RefPtr mTextureSource; michael@0: }; michael@0: michael@0: /** michael@0: * A texture source meant for use with StreamTextureHostOGL. michael@0: * michael@0: * It does not own any texture, we get texture from SurfaceStream. michael@0: */ michael@0: class StreamTextureSourceOGL : public NewTextureSource michael@0: , public TextureSourceOGL michael@0: { michael@0: public: michael@0: StreamTextureSourceOGL(CompositorOGL* aCompositor, michael@0: gfx::SurfaceStream* aStream) michael@0: : mCompositor(aCompositor) michael@0: , mStream(aStream) michael@0: , mTextureHandle(0) michael@0: , mTextureTarget(LOCAL_GL_TEXTURE_2D) michael@0: , mUploadTexture(0) michael@0: , mFormat(gfx::SurfaceFormat::UNKNOWN) michael@0: { michael@0: MOZ_COUNT_CTOR(StreamTextureSourceOGL); michael@0: } michael@0: michael@0: ~StreamTextureSourceOGL() michael@0: { michael@0: MOZ_COUNT_DTOR(StreamTextureSourceOGL); michael@0: } michael@0: michael@0: virtual TextureSourceOGL* AsSourceOGL() { return this; } michael@0: michael@0: virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsValid() const MOZ_OVERRIDE { return !!gl(); } michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } michael@0: michael@0: virtual GLenum GetTextureTarget() const { return mTextureTarget; } michael@0: michael@0: virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return LOCAL_GL_CLAMP_TO_EDGE; } michael@0: michael@0: virtual void DeallocateDeviceData(); michael@0: michael@0: bool RetrieveTextureFromStream(); michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: protected: michael@0: gl::GLContext* gl() const; michael@0: michael@0: CompositorOGL* mCompositor; michael@0: gfx::SurfaceStream* mStream; michael@0: GLuint mTextureHandle; michael@0: GLenum mTextureTarget; michael@0: GLuint mUploadTexture; michael@0: gfx::IntSize mSize; michael@0: gfx::SurfaceFormat mFormat; michael@0: }; michael@0: michael@0: /** michael@0: * A TextureHost for shared SurfaceStream michael@0: */ michael@0: class StreamTextureHostOGL : public TextureHost michael@0: { michael@0: public: michael@0: StreamTextureHostOGL(TextureFlags aFlags, michael@0: const SurfaceStreamDescriptor& aDesc); michael@0: michael@0: virtual ~StreamTextureHostOGL(); michael@0: michael@0: // SharedTextureHostOGL doesn't own any GL texture michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE {} michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: virtual bool Lock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE; michael@0: michael@0: virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE michael@0: { michael@0: return mTextureSource; michael@0: } michael@0: michael@0: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE michael@0: { michael@0: return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) michael@0: } michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE; michael@0: michael@0: #ifdef MOZ_LAYERS_HAVE_LOG michael@0: virtual const char* Name() { return "StreamTextureHostOGL"; } michael@0: #endif michael@0: michael@0: protected: michael@0: CompositorOGL* mCompositor; michael@0: gfx::SurfaceStream* mStream; michael@0: RefPtr mTextureSource; michael@0: }; michael@0: michael@0: } // namespace michael@0: } // namespace michael@0: michael@0: #endif /* MOZILLA_GFX_TEXTUREOGL_H */