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"
9 #include "mozilla/gfx/Logging.h"
10 #include "ScopedGLHelpers.h"
15 static void DeleteByTarget(GLContext
* const gl
, const GLenum target
,
17 if (target
== LOCAL_GL_RENDERBUFFER
) {
18 gl
->DeleteRenderbuffer(name
);
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
))
31 if (uint32_t(size
.width
) > gl
->MaxTexOrRbSize() ||
32 uint32_t(size
.height
) > gl
->MaxTexOrRbSize() ||
33 samples
> gl
->MaxSamples()) {
39 GLContext::LocalErrorScope
errorScope(*gl
);
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
);
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();
60 if (err
!= LOCAL_GL_OUT_OF_MEMORY
) {
61 gfxCriticalNote
<< "Unexpected error: " << gfx::hexa(err
) << ": "
62 << GLContext::GLErrorToString(err
);
64 DeleteByTarget(gl
, colorTarget
, colorName
);
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
,
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
);
91 gl
->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER
, samples
,
92 format
, size
.width
, size
.height
);
94 gl
->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER
, format
, size
.width
,
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.
110 depthRB
= fnAllocRB(mozFB
->mDepthRB
, LOCAL_GL_DEPTH_COMPONENT24
);
111 stencilRB
= fnAllocRB(mozFB
->mStencilRB
, LOCAL_GL_STENCIL_INDEX8
);
114 const auto err
= errorScope
.GetError();
116 MOZ_ASSERT(err
== LOCAL_GL_OUT_OF_MEMORY
);
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
) {
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
)
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
);
167 } // namespace mozilla