Backed out 3 changesets (bug 1764201) for causing multiple failures, including build...
[gecko.git] / gfx / gl / MozFramebuffer.cpp
blob10995a7ee11cc4c809b476bff12706d5862ca950
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 CreateImpl(
69 gl, size, samples,
70 depthStencil ? DepthAndStencilBuffer::Create(gl, size, samples) : nullptr,
71 colorTarget, colorName);
74 UniquePtr<MozFramebuffer> MozFramebuffer::CreateForBacking(
75 GLContext* const gl, const gfx::IntSize& size, const uint32_t samples,
76 bool depthStencil, const GLenum colorTarget, const GLuint colorName) {
77 return CreateImpl(
78 gl, size, samples,
79 depthStencil ? DepthAndStencilBuffer::Create(gl, size, samples) : nullptr,
80 colorTarget, colorName);
83 /* static */ UniquePtr<MozFramebuffer>
84 MozFramebuffer::CreateForBackingWithSharedDepthAndStencil(
85 const gfx::IntSize& size, const uint32_t samples, GLenum colorTarget,
86 GLuint colorName,
87 const RefPtr<DepthAndStencilBuffer>& depthAndStencilBuffer) {
88 auto gl = depthAndStencilBuffer->gl();
89 if (!gl || !gl->MakeCurrent()) {
90 return nullptr;
92 return CreateImpl(gl, size, samples, depthAndStencilBuffer, colorTarget,
93 colorName);
96 /* static */ UniquePtr<MozFramebuffer> MozFramebuffer::CreateImpl(
97 GLContext* const gl, const gfx::IntSize& size, const uint32_t samples,
98 const RefPtr<DepthAndStencilBuffer>& depthAndStencilBuffer,
99 const GLenum colorTarget, const GLuint colorName) {
100 GLuint fb = gl->CreateFramebuffer();
101 const ScopedBindFramebuffer bindFB(gl, fb);
103 if (colorTarget == LOCAL_GL_RENDERBUFFER) {
104 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
105 LOCAL_GL_COLOR_ATTACHMENT0, colorTarget,
106 colorName);
107 } else {
108 gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
109 colorTarget, colorName, 0);
112 if (depthAndStencilBuffer) {
113 gl->fFramebufferRenderbuffer(
114 LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER,
115 depthAndStencilBuffer->mDepthRB);
116 gl->fFramebufferRenderbuffer(
117 LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
118 LOCAL_GL_RENDERBUFFER, depthAndStencilBuffer->mStencilRB);
121 const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
122 if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
123 gfxCriticalNote << "MozFramebuffer::CreateImpl(size:" << size
124 << ", samples:" << samples
125 << ", depthAndStencil:" << bool(depthAndStencilBuffer)
126 << ", colorTarget:" << gfx::hexa(colorTarget)
127 << ", colorName:" << colorName << "): Incomplete: 0x"
128 << gfx::hexa(status);
129 return nullptr;
132 return UniquePtr<MozFramebuffer>(new MozFramebuffer(
133 gl, size, fb, samples, depthAndStencilBuffer, colorTarget, colorName));
136 /* static */ RefPtr<DepthAndStencilBuffer> DepthAndStencilBuffer::Create(
137 GLContext* const gl, const gfx::IntSize& size, const uint32_t samples) {
138 const auto fnAllocRB = [&](GLenum format) {
139 GLuint rb = gl->CreateRenderbuffer();
140 const ScopedBindRenderbuffer bindRB(gl, rb);
141 if (samples) {
142 gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
143 format, size.width, size.height);
144 } else {
145 gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, size.width,
146 size.height);
148 return rb;
151 GLuint depthRB, stencilRB;
153 GLContext::LocalErrorScope errorScope(*gl);
155 if (gl->IsSupported(GLFeature::packed_depth_stencil)) {
156 depthRB = fnAllocRB(LOCAL_GL_DEPTH24_STENCIL8);
157 stencilRB = depthRB; // Ignore unused mStencilRB.
158 } else {
159 depthRB = fnAllocRB(LOCAL_GL_DEPTH_COMPONENT24);
160 stencilRB = fnAllocRB(LOCAL_GL_STENCIL_INDEX8);
163 const auto err = errorScope.GetError();
164 if (err) {
165 MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY);
166 return nullptr;
170 return new DepthAndStencilBuffer(gl, size, depthRB, stencilRB);
173 ////////////////////
175 MozFramebuffer::MozFramebuffer(
176 GLContext* const gl, const gfx::IntSize& size, GLuint fb,
177 const uint32_t samples, RefPtr<DepthAndStencilBuffer> depthAndStencilBuffer,
178 const GLenum colorTarget, const GLuint colorName)
179 : mWeakGL(gl),
180 mSize(size),
181 mSamples(samples),
182 mFB(fb),
183 mColorTarget(colorTarget),
184 mDepthAndStencilBuffer(std::move(depthAndStencilBuffer)),
185 mColorName(colorName) {
186 MOZ_ASSERT(mColorTarget);
187 MOZ_ASSERT(mColorName);
190 MozFramebuffer::~MozFramebuffer() {
191 GLContext* const gl = mWeakGL;
192 if (!gl || !gl->MakeCurrent()) {
193 return;
196 gl->DeleteFramebuffer(mFB);
198 DeleteByTarget(gl, mColorTarget, mColorName);
201 bool MozFramebuffer::HasDepth() const {
202 return mDepthAndStencilBuffer && mDepthAndStencilBuffer->mDepthRB;
205 bool MozFramebuffer::HasStencil() const {
206 return mDepthAndStencilBuffer && mDepthAndStencilBuffer->mStencilRB;
209 DepthAndStencilBuffer::DepthAndStencilBuffer(GLContext* gl,
210 const gfx::IntSize& size,
211 GLuint depthRB, GLuint stencilRB)
212 : mWeakGL(gl), mSize(size), mDepthRB(depthRB), mStencilRB(stencilRB) {}
214 DepthAndStencilBuffer::~DepthAndStencilBuffer() {
215 GLContext* const gl = mWeakGL;
216 if (!gl || !gl->MakeCurrent()) {
217 return;
220 gl->DeleteRenderbuffer(mDepthRB);
221 gl->DeleteRenderbuffer(mStencilRB);
224 } // namespace gl
225 } // namespace mozilla