summaryrefslogtreecommitdiffstats
path: root/gfx/gl/SharedSurfaceGL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl/SharedSurfaceGL.cpp')
-rw-r--r--gfx/gl/SharedSurfaceGL.cpp190
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 */