Bug 1508381 - remove now-unnecessary TASKCLUSTER_* variables r=tomprince
[gecko.git] / gfx / gl / MozFramebuffer.cpp
blob8f38e0ce8b3f15e31695c2557d676e8ccf3f69b9
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "MozFramebuffer.h"
8 #include "GLContext.h"
9 #include "mozilla/gfx/Logging.h"
10 #include "ScopedGLHelpers.h"
12 namespace mozilla {
13 namespace gl {
15 static void DeleteByTarget(GLContext* const gl, const GLenum target,
16 const GLuint name) {
17 if (target == LOCAL_GL_RENDERBUFFER) {
18 gl->DeleteRenderbuffer(name);
19 } else {
20 gl->DeleteTexture(name);
24 UniquePtr<MozFramebuffer> MozFramebuffer::Create(GLContext* const gl,
25 const gfx::IntSize& size,
26 const uint32_t samples,
27 const bool depthStencil) {
28 if (samples && !gl->IsSupported(GLFeature::framebuffer_multisample))
29 return nullptr;
31 if (uint32_t(size.width) > gl->MaxTexOrRbSize() ||
32 uint32_t(size.height) > gl->MaxTexOrRbSize() ||
33 samples > gl->MaxSamples()) {
34 return nullptr;
37 gl->MakeCurrent();
39 GLContext::LocalErrorScope errorScope(*gl);
41 GLenum colorTarget;
42 GLuint colorName;
43 if (samples) {
44 colorTarget = LOCAL_GL_RENDERBUFFER;
45 colorName = gl->CreateRenderbuffer();
46 const ScopedBindRenderbuffer bindRB(gl, colorName);
47 gl->fRenderbufferStorageMultisample(colorTarget, samples, LOCAL_GL_RGBA8,
48 size.width, size.height);
49 } else {
50 colorTarget = LOCAL_GL_TEXTURE_2D;
51 colorName = gl->CreateTexture();
52 const ScopedBindTexture bindTex(gl, colorName);
53 gl->TexParams_SetClampNoMips();
54 gl->fTexImage2D(colorTarget, 0, LOCAL_GL_RGBA, size.width, size.height, 0,
55 LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
58 const auto err = errorScope.GetError();
59 if (err) {
60 if (err != LOCAL_GL_OUT_OF_MEMORY) {
61 gfxCriticalNote << "Unexpected error: " << gfx::hexa(err) << ": "
62 << GLContext::GLErrorToString(err);
64 DeleteByTarget(gl, colorTarget, colorName);
65 return nullptr;
68 return CreateWith(gl, size, samples, depthStencil, colorTarget, colorName);
71 UniquePtr<MozFramebuffer> MozFramebuffer::CreateWith(
72 GLContext* const gl, const gfx::IntSize& size, const uint32_t samples,
73 const bool depthStencil, const GLenum colorTarget, const GLuint colorName) {
74 UniquePtr<MozFramebuffer> mozFB(new MozFramebuffer(
75 gl, size, samples, depthStencil, colorTarget, colorName));
77 const ScopedBindFramebuffer bindFB(gl, mozFB->mFB);
79 if (colorTarget == LOCAL_GL_RENDERBUFFER) {
80 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
81 LOCAL_GL_COLOR_ATTACHMENT0, colorTarget,
82 colorName);
83 } else {
84 gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
85 colorTarget, colorName, 0);
88 const auto fnAllocRB = [&](GLuint rb, GLenum format) {
89 const ScopedBindRenderbuffer bindRB(gl, rb);
90 if (samples) {
91 gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
92 format, size.width, size.height);
93 } else {
94 gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, size.width,
95 size.height);
97 return rb;
100 if (depthStencil) {
101 GLuint depthRB, stencilRB;
104 GLContext::LocalErrorScope errorScope(*gl);
106 if (gl->IsSupported(GLFeature::packed_depth_stencil)) {
107 depthRB = fnAllocRB(mozFB->mDepthRB, LOCAL_GL_DEPTH24_STENCIL8);
108 stencilRB = depthRB; // Ignore unused mStencilRB.
109 } else {
110 depthRB = fnAllocRB(mozFB->mDepthRB, LOCAL_GL_DEPTH_COMPONENT24);
111 stencilRB = fnAllocRB(mozFB->mStencilRB, LOCAL_GL_STENCIL_INDEX8);
114 const auto err = errorScope.GetError();
115 if (err) {
116 MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY);
117 return nullptr;
121 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
122 LOCAL_GL_DEPTH_ATTACHMENT,
123 LOCAL_GL_RENDERBUFFER, depthRB);
124 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
125 LOCAL_GL_STENCIL_ATTACHMENT,
126 LOCAL_GL_RENDERBUFFER, stencilRB);
129 const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
130 if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
131 MOZ_ASSERT(false);
132 return nullptr;
135 return mozFB;
138 ////////////////////
140 MozFramebuffer::MozFramebuffer(GLContext* const gl, const gfx::IntSize& size,
141 const uint32_t samples, const bool depthStencil,
142 const GLenum colorTarget, const GLuint colorName)
143 : mWeakGL(gl),
144 mSize(size),
145 mSamples(samples),
146 mFB(gl->CreateFramebuffer()),
147 mColorTarget(colorTarget),
148 mColorName(colorName),
149 mDepthRB(depthStencil ? gl->CreateRenderbuffer() : 0),
150 mStencilRB(depthStencil ? gl->CreateRenderbuffer() : 0) {
151 MOZ_ASSERT(mColorTarget);
152 MOZ_ASSERT(mColorName);
155 MozFramebuffer::~MozFramebuffer() {
156 GLContext* const gl = mWeakGL;
157 if (!gl || !gl->MakeCurrent()) return;
159 gl->DeleteFramebuffer(mFB);
160 gl->DeleteRenderbuffer(mDepthRB);
161 gl->DeleteRenderbuffer(mStencilRB);
163 DeleteByTarget(gl, mColorTarget, mColorName);
166 } // namespace gl
167 } // namespace mozilla