diff options
Diffstat (limited to 'gfx/gl/SharedSurfaceGL.cpp')
-rw-r--r-- | gfx/gl/SharedSurfaceGL.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp new file mode 100644 index 000000000..6fba1b4eb --- /dev/null +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -0,0 +1,190 @@ +/* -*- 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/. */ + +#include "SharedSurfaceGL.h" + +#include "GLBlitHelper.h" +#include "GLContext.h" +#include "GLReadTexImageHelper.h" +#include "mozilla/gfx/2D.h" +#include "ScopedGLHelpers.h" + +namespace mozilla { +namespace gl { + +using gfx::IntSize; +using gfx::SurfaceFormat; + +/*static*/ UniquePtr<SharedSurface_Basic> +SharedSurface_Basic::Create(GLContext* gl, + const GLFormats& formats, + const IntSize& size, + bool hasAlpha) +{ + UniquePtr<SharedSurface_Basic> ret; + gl->MakeCurrent(); + + GLContext::LocalErrorScope localError(*gl); + GLuint tex = CreateTextureForOffscreen(gl, formats, size); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) { + gl->fDeleteTextures(1, &tex); + return Move(ret); + } + + bool ownsTex = true; + ret.reset( new SharedSurface_Basic(gl, size, hasAlpha, tex, ownsTex) ); + return Move(ret); +} + + +/*static*/ UniquePtr<SharedSurface_Basic> +SharedSurface_Basic::Wrap(GLContext* gl, + const IntSize& size, + bool hasAlpha, + GLuint tex) +{ + bool ownsTex = false; + UniquePtr<SharedSurface_Basic> ret( new SharedSurface_Basic(gl, size, hasAlpha, tex, + ownsTex) ); + return Move(ret); +} + +SharedSurface_Basic::SharedSurface_Basic(GLContext* gl, + const IntSize& size, + bool hasAlpha, + GLuint tex, + bool ownsTex) + : SharedSurface(SharedSurfaceType::Basic, + AttachmentType::GLTexture, + gl, + size, + hasAlpha, + true) + , mTex(tex) + , mOwnsTex(ownsTex) + , mFB(0) +{ + mGL->MakeCurrent(); + mGL->fGenFramebuffers(1, &mFB); + + ScopedBindFramebuffer autoFB(mGL, mFB); + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_TEXTURE_2D, + mTex, + 0); + + DebugOnly<GLenum> status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); + MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE); +} + +SharedSurface_Basic::~SharedSurface_Basic() +{ + if (!mGL || !mGL->MakeCurrent()) + return; + + if (mFB) + mGL->fDeleteFramebuffers(1, &mFB); + + if (mOwnsTex) + mGL->fDeleteTextures(1, &mTex); +} + + +//////////////////////////////////////////////////////////////////////// + +SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps, + const layers::TextureFlags& flags) + : SurfaceFactory(SharedSurfaceType::Basic, gl, caps, nullptr, flags) +{ } + + +//////////////////////////////////////////////////////////////////////// +// SharedSurface_GLTexture + +/*static*/ UniquePtr<SharedSurface_GLTexture> +SharedSurface_GLTexture::Create(GLContext* prodGL, + const GLFormats& formats, + const IntSize& size, + bool hasAlpha) +{ + MOZ_ASSERT(prodGL); + + prodGL->MakeCurrent(); + + UniquePtr<SharedSurface_GLTexture> ret; + GLContext::LocalErrorScope localError(*prodGL); + + GLuint tex = CreateTextureForOffscreen(prodGL, formats, size); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) { + prodGL->fDeleteTextures(1, &tex); + return Move(ret); + } + + ret.reset(new SharedSurface_GLTexture(prodGL, size, + hasAlpha, tex)); + return Move(ret); +} + +SharedSurface_GLTexture::~SharedSurface_GLTexture() +{ + if (!mGL->MakeCurrent()) + return; + + if (mTex) { + mGL->fDeleteTextures(1, &mTex); + } + + if (mSync) { + mGL->fDeleteSync(mSync); + } +} + +void +SharedSurface_GLTexture::ProducerReleaseImpl() +{ + mGL->MakeCurrent(); + + if (mGL->IsSupported(GLFeature::sync)) { + if (mSync) { + mGL->fDeleteSync(mSync); + mSync = 0; + } + + mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + if (mSync) { + mGL->fFlush(); + return; + } + } + MOZ_ASSERT(!mSync); + + mGL->fFinish(); +} + +bool +SharedSurface_GLTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + *out_descriptor = layers::SurfaceDescriptorSharedGLTexture(ProdTexture(), + ProdTextureTarget(), + (uintptr_t)mSync, + mSize, + mHasAlpha); + + // Transfer ownership of the fence to the host + mSync = nullptr; + return true; +} + + +} // namespace gl + +} /* namespace mozilla */ |