Bug 1427668 - Add MozFramebuffer. - r=daoshengmu
MozReview-Commit-ID: CX0wxs7Gqvp
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -3688,24 +3688,52 @@ protected:
bool mHeavyGLCallsSinceLastFlush;
public:
void FlushIfHeavyGLCallsSinceLastFlush();
static bool ShouldSpew();
static bool ShouldDumpExts();
bool Readback(SharedSurface* src, gfx::DataSourceSurface* dest);
- ////
+ // --
void TexParams_SetClampNoMips(GLenum target = LOCAL_GL_TEXTURE_2D) {
fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
}
+
+ // --
+
+ GLuint CreateFramebuffer() {
+ GLuint x = 0;
+ fGenFramebuffers(1, &x);
+ return x;
+ }
+ GLuint CreateRenderbuffer() {
+ GLuint x = 0;
+ fGenRenderbuffers(1, &x);
+ return x;
+ }
+ GLuint CreateTexture() {
+ GLuint x = 0;
+ fGenTextures(1, &x);
+ return x;
+ }
+
+ void DeleteFramebuffer(const GLuint x) {
+ fDeleteFramebuffers(1, &x);
+ }
+ void DeleteRenderbuffer(const GLuint x) {
+ fDeleteRenderbuffers(1, &x);
+ }
+ void DeleteTexture(const GLuint x) {
+ fDeleteTextures(1, &x);
+ }
};
bool DoesStringMatch(const char* aString, const char* aWantedString);
void SplitByChar(const nsACString& str, const char delim,
std::vector<nsCString>* const out);
template<size_t N>
new file mode 100644
--- /dev/null
+++ b/gfx/gl/MozFramebuffer.cpp
@@ -0,0 +1,163 @@
+/* -*- 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 "MozFramebuffer.h"
+
+#include "GLContext.h"
+#include "ScopedGLHelpers.h"
+
+namespace mozilla {
+namespace gl {
+
+static void
+DeleteByTarget(GLContext* const gl, const GLenum target, const GLuint name)
+{
+ if (target == LOCAL_GL_RENDERBUFFER) {
+ gl->DeleteRenderbuffer(name);
+ } else {
+ gl->DeleteTexture(name);
+ }
+}
+
+UniquePtr<MozFramebuffer>
+MozFramebuffer::Create(GLContext* const gl, const gfx::IntSize& size,
+ const uint32_t samples, const bool depthStencil)
+{
+ if (samples && !gl->IsSupported(GLFeature::framebuffer_multisample))
+ return nullptr;
+
+ gl->MakeCurrent();
+
+ GLContext::LocalErrorScope errorScope(*gl);
+
+ GLenum colorTarget;
+ GLuint colorName;
+ if (samples) {
+ colorTarget = LOCAL_GL_RENDERBUFFER;
+ colorName = gl->CreateRenderbuffer();
+ const ScopedBindRenderbuffer bindRB(gl, colorName);
+ gl->fRenderbufferStorageMultisample(colorTarget, samples, LOCAL_GL_RGBA8,
+ size.width, size.height);
+ } else {
+ colorTarget = LOCAL_GL_TEXTURE_2D;
+ colorName = gl->CreateTexture();
+ const ScopedBindTexture bindTex(gl, colorName);
+ gl->TexParams_SetClampNoMips();
+ const ScopedBindPBO bindPBO(gl, LOCAL_GL_PIXEL_UNPACK_BUFFER);
+ gl->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
+ gl->fTexImage2D(colorTarget, 0, LOCAL_GL_RGBA,
+ size.width, size.height, 0,
+ LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
+ }
+
+ const auto err = errorScope.GetError();
+ if (err) {
+ MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY);
+ DeleteByTarget(gl, colorTarget, colorName);
+ return nullptr;
+ }
+
+ return CreateWith(gl, size, samples, depthStencil, colorTarget, colorName);
+}
+
+UniquePtr<MozFramebuffer>
+MozFramebuffer::CreateWith(GLContext* const gl, const gfx::IntSize& size,
+ const uint32_t samples, const bool depthStencil,
+ const GLenum colorTarget, const GLuint colorName)
+{
+ UniquePtr<MozFramebuffer> mozFB(new MozFramebuffer(gl, size, samples, depthStencil,
+ colorTarget, colorName));
+
+ const ScopedBindFramebuffer bindFB(gl, mozFB->mFB);
+
+ if (colorTarget == LOCAL_GL_RENDERBUFFER) {
+ gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ colorTarget, colorName);
+ } else {
+ gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ colorTarget, colorName, 0);
+ }
+
+ const auto fnAllocRB = [&](GLuint rb, GLenum format) {
+ const ScopedBindRenderbuffer bindRB(gl, rb);
+ if (samples) {
+ gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples, format,
+ size.width, size.height);
+ } else {
+ gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, size.width,
+ size.height);
+ }
+ return rb;
+ };
+
+ if (depthStencil) {
+ GLuint depthRB, stencilRB;
+
+ {
+ GLContext::LocalErrorScope errorScope(*gl);
+
+ if (gl->IsSupported(GLFeature::packed_depth_stencil)) {
+ depthRB = fnAllocRB(mozFB->mDepthRB, LOCAL_GL_DEPTH24_STENCIL8);
+ stencilRB = depthRB; // Ignore unused mStencilRB.
+ } else {
+ depthRB = fnAllocRB(mozFB->mDepthRB , LOCAL_GL_DEPTH_COMPONENT24);
+ stencilRB = fnAllocRB(mozFB->mStencilRB, LOCAL_GL_STENCIL_INDEX8);
+ }
+
+ const auto err = errorScope.GetError();
+ if (err) {
+ MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ }
+
+ gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, depthRB);
+ gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, stencilRB);
+ }
+
+ const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+ if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
+ MOZ_ASSERT(false);
+ return nullptr;
+ }
+
+ return Move(mozFB);
+}
+
+////////////////////
+
+MozFramebuffer::MozFramebuffer(GLContext* const gl, const gfx::IntSize& size,
+ const uint32_t samples, const bool depthStencil,
+ const GLenum colorTarget, const GLuint colorName)
+ : mWeakGL(gl)
+ , mSize(size)
+ , mSamples(samples)
+ , mFB(gl->CreateFramebuffer())
+ , mColorTarget(colorTarget)
+ , mColorName(colorName)
+ , mDepthRB(depthStencil ? gl->CreateRenderbuffer() : 0)
+ , mStencilRB(depthStencil ? gl->CreateRenderbuffer() : 0)
+{
+ MOZ_ASSERT(mColorTarget);
+ MOZ_ASSERT(mColorName);
+}
+
+MozFramebuffer::~MozFramebuffer()
+{
+ GLContext* const gl = mWeakGL;
+ if (!gl || !gl->MakeCurrent())
+ return;
+
+ gl->DeleteFramebuffer(mFB);
+ gl->DeleteRenderbuffer(mDepthRB);
+ gl->DeleteRenderbuffer(mStencilRB);
+
+ DeleteByTarget(gl, mColorTarget, mColorName);
+}
+
+} // namespace gl
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/gl/MozFramebuffer.h
@@ -0,0 +1,54 @@
+/* -*- 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/. */
+
+#ifndef MOZ_FRAMEBUFFER_H_
+#define MOZ_FRAMEBUFFER_H_
+
+#include "gfx2DGlue.h"
+#include "GLConsts.h"
+#include "GLContextTypes.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h"
+
+namespace mozilla {
+namespace gl {
+
+class MozFramebuffer final
+{
+ const WeakPtr<GLContext> mWeakGL;
+public:
+ const gfx::IntSize mSize;
+ const uint32_t mSamples;
+ const GLuint mFB;
+ const GLenum mColorTarget;
+private:
+ const GLuint mColorName;
+ const GLuint mDepthRB;
+ const GLuint mStencilRB;
+
+public:
+ static UniquePtr<MozFramebuffer> Create(GLContext* gl, const gfx::IntSize& size,
+ uint32_t samples, bool depthStencil);
+
+ static UniquePtr<MozFramebuffer> CreateWith(GLContext* gl, const gfx::IntSize& size,
+ uint32_t samples, bool depthStencil,
+ GLenum colorTarget, GLuint colorName);
+private:
+ MozFramebuffer(GLContext* gl, const gfx::IntSize& size, uint32_t samples,
+ bool depthStencil, GLenum colorTarget, GLuint colorName);
+public:
+ ~MozFramebuffer();
+
+ GLuint ColorTex() const {
+ if (mColorTarget == LOCAL_GL_RENDERBUFFER)
+ return 0;
+ return mColorName;
+ }
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // MOZ_FRAMEBUFFER_H_
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -131,16 +131,17 @@ UNIFIED_SOURCES += [
'GLContextTypes.cpp',
'GLDebugUtils.cpp',
'GLLibraryEGL.cpp',
'GLLibraryLoader.cpp',
'GLReadTexImageHelper.cpp',
'GLScreenBuffer.cpp',
'GLTextureImage.cpp',
'GLUploadHelpers.cpp',
+ 'MozFramebuffer.cpp',
'ScopedGLHelpers.cpp',
'SharedSurface.cpp',
'SharedSurfaceEGL.cpp',
'SharedSurfaceGL.cpp',
'SurfaceTypes.cpp',
'TextureImageEGL.cpp',
]