Bug 875211 - use one global gl texture per texture unit rather than one per GrallocTextureHostOGL. r=bjacob

This commit is contained in:
Nicolas Silva 2013-06-04 20:44:37 +02:00
parent bf470038f5
commit 11575bb513
4 changed files with 96 additions and 91 deletions

View File

@ -232,6 +232,7 @@ CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
, mSurfaceSize(aSurfaceWidth, aSurfaceHeight)
, mHasBGRA(0)
, mUseExternalSurfaceSize(aUseExternalSurfaceSize)
, mTextures({0, 0, 0})
, mFrameInProgress(false)
, mDestroyed(false)
{
@ -279,9 +280,29 @@ CompositorOGL::AddPrograms(ShaderProgramType aType)
}
}
GLuint
CompositorOGL::GetTemporaryTexture(GLenum aTextureUnit)
{
if (!mTextures[aTextureUnit - LOCAL_GL_TEXTURE0]) {
gl()->MakeCurrent();
gl()->fGenTextures(1, &mTextures[aTextureUnit - LOCAL_GL_TEXTURE0]);
}
return mTextures[aTextureUnit - LOCAL_GL_TEXTURE0];
}
void
CompositorOGL::Destroy()
{
if (gl()) {
gl()->MakeCurrent();
gl()->fDeleteTextures(3, mTextures);
mTextures[0] = 0;
mTextures[1] = 0;
mTextures[2] = 0;
} else {
MOZ_ASSERT(!mTextures[0] && !mTextures[1] && !mTextures[2]);
}
if (!mDestroyed) {
mDestroyed = true;
CleanupResources();

View File

@ -134,6 +134,13 @@ public:
gl::RGBARectLayerProgramType : gl::RGBALayerProgramType;
}
/**
* The compositor provides with temporary textures for use with direct
* textruing like gralloc texture.
* Doing so lets us use gralloc the way it has been designed to be used
* (see https://wiki.mozilla.org/Platform/GFX/Gralloc)
*/
GLuint GetTemporaryTexture(GLenum aUnit);
private:
/**
* Context target, nullptr when drawing directly to our swap chain.
@ -319,6 +326,9 @@ private:
bool mDestroyed;
nsAutoPtr<FPSState> mFPS;
// Textures used for direct texturing of buffers like gralloc.
// The index of the texture in this array must correspond to the texture unit.
GLuint mTextures[3];
static bool sDrawFPS;
static bool sFrameCounter;
};

View File

@ -700,28 +700,29 @@ TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
}
}
GrallocTextureHostOGL::GrallocTextureHostOGL()
: mCompositor(nullptr)
, mTextureTarget(0)
, mEGLImage(0)
{
}
void GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
{
CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
if (mGL && !glCompositor) {
if (mCompositor && !glCompositor) {
DeleteTextures();
}
mGL = glCompositor ? glCompositor->gl() : nullptr;
mCompositor = glCompositor;
}
void
GrallocTextureHostOGL::DeleteTextures()
{
if (mGLTexture || mEGLImage) {
mGL->MakeCurrent();
if (mGLTexture) {
mGL->fDeleteTextures(1, &mGLTexture);
mGLTexture = 0;
}
if (mEGLImage) {
mGL->DestroyEGLImage(mEGLImage);
mEGLImage = 0;
}
if (mEGLImage) {
gl()->MakeCurrent();
gl()->DestroyEGLImage(mEGLImage);
mEGLImage = 0;
}
}
@ -767,20 +768,43 @@ GrallocTextureHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage,
RegisterTextureHostAtGrallocBufferActor(this, aImage);
}
gl::GLContext*
GrallocTextureHostOGL::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
void GrallocTextureHostOGL::BindTexture(GLenum aTextureUnit)
{
MOZ_ASSERT(mGLTexture);
/*
* 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());
gl()->MakeCurrent();
mGL->MakeCurrent();
mGL->fActiveTexture(aTextureUnit);
mGL->fBindTexture(mTextureTarget, mGLTexture);
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
GLuint tex = mCompositor->GetTemporaryTexture(aTextureUnit);
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, tex);
if (!mEGLImage) {
mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
}
gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
}
bool
GrallocTextureHostOGL::IsValid() const
{
return !!mGL && !!mGraphicBuffer.get();
return !!gl() && !!mGraphicBuffer.get();
}
GrallocTextureHostOGL::~GrallocTextureHostOGL()
@ -798,65 +822,14 @@ GrallocTextureHostOGL::~GrallocTextureHostOGL()
bool
GrallocTextureHostOGL::Lock()
{
if (!IsValid()) {
return false;
}
/*
* 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(mGraphicBuffer.get());
mGL->MakeCurrent();
if (!mGLTexture) {
mGL->fGenTextures(1, &mGLTexture);
}
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
mGL->fBindTexture(mTextureTarget, mGLTexture);
if (!mEGLImage) {
mEGLImage = mGL->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
}
mGL->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
return true;
// Lock/Unlock is done internally when binding the gralloc buffer to a gl texture
return IsValid();
}
void
GrallocTextureHostOGL::Unlock()
{
/*
* The job of this function is to ensure that we release any read lock placed on
* our android::GraphicBuffer by any drawing code that sourced it via this TextureHost.
*
* Indeed, as soon as we draw with a texture that's tied to a android::GraphicBuffer,
* the GL may place read locks on it. We must ensure that we release them early enough,
* i.e. before the next time that we will try to acquire a write lock on the same buffer,
* because read and write locks on gralloc buffers are mutually exclusive.
*/
if (mGL->Renderer() == GLContext::RendererAdrenoTM205) {
/* XXX This is working around a driver bug exhibited on at least the
* Geeksphone Peak, where retargeting to a different EGL image is very
* slow. See Bug 869696.
*/
if (mGLTexture) {
mGL->MakeCurrent();
mGL->fDeleteTextures(1, &mGLTexture);
mGLTexture = 0;
}
return;
}
mGL->MakeCurrent();
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
mGL->fBindTexture(mTextureTarget, mGLTexture);
mGL->fEGLImageTargetTexture2D(mTextureTarget, mGL->GetNullEGLImage());
// Lock/Unlock is done internally when binding the gralloc buffer to a gl texture
}
gfx::SurfaceFormat
@ -877,7 +850,7 @@ GrallocTextureHostOGL::SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator*
RegisterTextureHostAtGrallocBufferActor(this, *mBuffer);
}
#endif
#endif // MOZ_WIDGET_GONK
already_AddRefed<gfxImageSurface>
TextureImageTextureHostOGL::GetAsSurface() {
@ -932,10 +905,20 @@ TiledTextureHostOGL::GetAsSurface() {
#ifdef MOZ_WIDGET_GONK
already_AddRefed<gfxImageSurface>
GrallocTextureHostOGL::GetAsSurface() {
nsRefPtr<gfxImageSurface> surf = IsValid() && mGLTexture ?
mGL->GetTexImage(mGLTexture,
false,
GetShaderProgram())
gl()->MakeCurrent();
GLuint tex = mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(mTextureTarget, tex);
if (!mEGLImage) {
mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
}
gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
nsRefPtr<gfxImageSurface> surf = IsValid() ?
gl()->GetTexImage(tex,
false,
GetShaderProgram())
: nullptr;
return surf.forget();
}

View File

@ -21,6 +21,7 @@ namespace mozilla {
namespace layers {
class TextureImageTextureHostOGL;
class CompositorOGL;
/*
* TextureHost implementations for the OpenGL backend.
@ -568,23 +569,12 @@ class GrallocTextureHostOGL
, public TextureSourceOGL
{
public:
GrallocTextureHostOGL()
: mGL(nullptr)
, mTextureTarget(0)
, mGLTexture(0)
, mEGLImage(0)
{
}
GrallocTextureHostOGL();
~GrallocTextureHostOGL();
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual GLuint GetTextureHandle()
{
return mGLTexture;
}
virtual void UpdateImpl(const SurfaceDescriptor& aImage,
nsIntRegion* aRegion = nullptr,
nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
@ -652,12 +642,13 @@ public:
}
private:
gl::GLContext* gl() const;
void DeleteTextures();
RefPtr<gl::GLContext> mGL;
RefPtr<CompositorOGL> mCompositor;
android::sp<android::GraphicBuffer> mGraphicBuffer;
GLenum mTextureTarget;
GLuint mGLTexture;
EGLImage mEGLImage;
};
#endif