diff options
Diffstat (limited to 'gfx/gl/SharedSurface.h')
-rw-r--r-- | gfx/gl/SharedSurface.h | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/gfx/gl/SharedSurface.h b/gfx/gl/SharedSurface.h new file mode 100644 index 000000000..0cd21d1b7 --- /dev/null +++ b/gfx/gl/SharedSurface.h @@ -0,0 +1,333 @@ +/* -*- 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/. */ + +/* SharedSurface abstracts an actual surface (can be a GL texture, but + * not necessarily) that handles sharing. + * Its specializations are: + * SharedSurface_Basic (client-side bitmap, does readback) + * SharedSurface_GLTexture + * SharedSurface_EGLImage + * SharedSurface_ANGLEShareHandle + */ + +#ifndef SHARED_SURFACE_H_ +#define SHARED_SURFACE_H_ + +#include <queue> +#include <set> +#include <stdint.h> + +#include "GLContextTypes.h" +#include "GLDefs.h" +#include "mozilla/Attributes.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/Mutex.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/WeakPtr.h" +#include "ScopedGLHelpers.h" +#include "SurfaceTypes.h" + +class nsIThread; + +namespace mozilla { +namespace gfx { +class DataSourceSurface; +class DrawTarget; +} // namespace gfx + +namespace layers { +class LayersIPCChannel; +class SharedSurfaceTextureClient; +enum class TextureFlags : uint32_t; +class SurfaceDescriptor; +class TextureClient; +} // namespace layers + +namespace gl { + +class GLContext; +class SurfaceFactory; +class ShSurfHandle; + +class SharedSurface +{ +public: + static void ProdCopy(SharedSurface* src, SharedSurface* dest, + SurfaceFactory* factory); + + const SharedSurfaceType mType; + const AttachmentType mAttachType; + const WeakPtr<GLContext> mGL; + const gfx::IntSize mSize; + const bool mHasAlpha; + const bool mCanRecycle; +protected: + bool mIsLocked; + bool mIsProducerAcquired; +#ifdef DEBUG + nsIThread* const mOwningThread; +#endif + + SharedSurface(SharedSurfaceType type, + AttachmentType attachType, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + bool canRecycle); + +public: + virtual ~SharedSurface() { + } + + // Specifies to the TextureClient any flags which + // are required by the SharedSurface backend. + virtual layers::TextureFlags GetTextureFlags() const; + + bool IsLocked() const { return mIsLocked; } + bool IsProducerAcquired() const { return mIsProducerAcquired; } + + // This locks the SharedSurface as the production buffer for the context. + // This is needed by backends which use PBuffers and/or EGLSurfaces. + void LockProd(); + + // Unlocking is harmless if we're already unlocked. + void UnlockProd(); + +protected: + virtual void LockProdImpl() = 0; + virtual void UnlockProdImpl() = 0; + + virtual void ProducerAcquireImpl() = 0; + virtual void ProducerReleaseImpl() = 0; + virtual void ProducerReadAcquireImpl() { ProducerAcquireImpl(); } + virtual void ProducerReadReleaseImpl() { ProducerReleaseImpl(); } + +public: + void ProducerAcquire() { + MOZ_ASSERT(!mIsProducerAcquired); + ProducerAcquireImpl(); + mIsProducerAcquired = true; + } + void ProducerRelease() { + MOZ_ASSERT(mIsProducerAcquired); + ProducerReleaseImpl(); + mIsProducerAcquired = false; + } + void ProducerReadAcquire() { + MOZ_ASSERT(!mIsProducerAcquired); + ProducerReadAcquireImpl(); + mIsProducerAcquired = true; + } + void ProducerReadRelease() { + MOZ_ASSERT(mIsProducerAcquired); + ProducerReadReleaseImpl(); + mIsProducerAcquired = false; + } + + // This function waits until the buffer is no longer being used. + // To optimize the performance, some implementaions recycle SharedSurfaces + // even when its buffer is still being used. + virtual void WaitForBufferOwnership() {} + + // For use when AttachType is correct. + virtual GLenum ProdTextureTarget() const { + MOZ_ASSERT(mAttachType == AttachmentType::GLTexture); + return LOCAL_GL_TEXTURE_2D; + } + + virtual GLuint ProdTexture() { + MOZ_ASSERT(mAttachType == AttachmentType::GLTexture); + MOZ_CRASH("GFX: Did you forget to override this function?"); + } + + virtual GLuint ProdRenderbuffer() { + MOZ_ASSERT(mAttachType == AttachmentType::GLRenderbuffer); + MOZ_CRASH("GFX: Did you forget to override this function?"); + } + + virtual bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, + GLint y, GLsizei width, GLsizei height, GLint border) + { + return false; + } + + virtual bool ReadPixels(GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid* pixels) + { + return false; + } + + virtual bool NeedsIndirectReads() const { + return false; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) = 0; + + virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) { + return false; + } +}; + +template<typename T> +class RefSet +{ + std::set<T*> mSet; + +public: + ~RefSet() { + clear(); + } + + auto begin() -> decltype(mSet.begin()) { + return mSet.begin(); + } + + void clear() { + for (auto itr = mSet.begin(); itr != mSet.end(); ++itr) { + (*itr)->Release(); + } + mSet.clear(); + } + + bool empty() const { + return mSet.empty(); + } + + bool insert(T* x) { + if (mSet.insert(x).second) { + x->AddRef(); + return true; + } + + return false; + } + + bool erase(T* x) { + if (mSet.erase(x)) { + x->Release(); + return true; + } + + return false; + } +}; + +template<typename T> +class RefQueue +{ + std::queue<T*> mQueue; + +public: + ~RefQueue() { + clear(); + } + + void clear() { + while (!empty()) { + pop(); + } + } + + bool empty() const { + return mQueue.empty(); + } + + size_t size() const { + return mQueue.size(); + } + + void push(T* x) { + mQueue.push(x); + x->AddRef(); + } + + T* front() const { + return mQueue.front(); + } + + void pop() { + T* x = mQueue.front(); + x->Release(); + mQueue.pop(); + } +}; + +class SurfaceFactory : public SupportsWeakPtr<SurfaceFactory> +{ +public: + // Should use the VIRTUAL version, but it's currently incompatible + // with SupportsWeakPtr. (bug 1049278) + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(SurfaceFactory) + + const SharedSurfaceType mType; + GLContext* const mGL; + const SurfaceCaps mCaps; + const RefPtr<layers::LayersIPCChannel> mAllocator; + const layers::TextureFlags mFlags; + const GLFormats mFormats; + Mutex mMutex; +protected: + SurfaceCaps mDrawCaps; + SurfaceCaps mReadCaps; + RefQueue<layers::SharedSurfaceTextureClient> mRecycleFreePool; + RefSet<layers::SharedSurfaceTextureClient> mRecycleTotalPool; + + SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags); + +public: + virtual ~SurfaceFactory(); + + const SurfaceCaps& DrawCaps() const { + return mDrawCaps; + } + + const SurfaceCaps& ReadCaps() const { + return mReadCaps; + } + +protected: + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) = 0; + + void StartRecycling(layers::SharedSurfaceTextureClient* tc); + void SetRecycleCallback(layers::SharedSurfaceTextureClient* tc); + void StopRecycling(layers::SharedSurfaceTextureClient* tc); + +public: + UniquePtr<SharedSurface> NewSharedSurface(const gfx::IntSize& size); + //already_AddRefed<ShSurfHandle> NewShSurfHandle(const gfx::IntSize& size); + already_AddRefed<layers::SharedSurfaceTextureClient> NewTexClient(const gfx::IntSize& size); + + static void RecycleCallback(layers::TextureClient* tc, void* /*closure*/); + + // Auto-deletes surfs of the wrong type. + bool Recycle(layers::SharedSurfaceTextureClient* texClient); +}; + +class ScopedReadbackFB +{ + GLContext* const mGL; + ScopedBindFramebuffer mAutoFB; + GLuint mTempFB; + GLuint mTempTex; + SharedSurface* mSurfToUnlock; + SharedSurface* mSurfToLock; + +public: + explicit ScopedReadbackFB(SharedSurface* src); + ~ScopedReadbackFB(); +}; + +bool ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst); +uint32_t ReadPixel(SharedSurface* src); + +} // namespace gl +} // namespace mozilla + +#endif // SHARED_SURFACE_H_ |