gecko-dev/gfx/gl/SharedSurface.h

311 строки
8.1 KiB
C++

/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
/* 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 bool 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;
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();
// This surface has been moved to the front buffer and will not be locked
// again until it is recycled. Do any finalization steps here.
virtual void Commit() {}
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() {}
// Returns true if the buffer is available.
// You can call WaitForBufferOwnership to wait for availability.
virtual bool IsBufferAvailable() const { return true; }
// 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 final {
GLContext* const mGL;
ScopedBindFramebuffer mAutoFB;
GLuint mTempFB = 0;
GLuint mTempTex = 0;
SharedSurface* mSurfToUnlock = nullptr;
SharedSurface* mSurfToLock = nullptr;
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_