/src/mozilla-central/gfx/gl/MozFramebuffer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ |
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/. */ |
5 | | |
6 | | #include "MozFramebuffer.h" |
7 | | |
8 | | #include "GLContext.h" |
9 | | #include "mozilla/gfx/Logging.h" |
10 | | #include "ScopedGLHelpers.h" |
11 | | |
12 | | namespace mozilla { |
13 | | namespace gl { |
14 | | |
15 | | static void |
16 | | DeleteByTarget(GLContext* const gl, const GLenum target, const GLuint name) |
17 | 0 | { |
18 | 0 | if (target == LOCAL_GL_RENDERBUFFER) { |
19 | 0 | gl->DeleteRenderbuffer(name); |
20 | 0 | } else { |
21 | 0 | gl->DeleteTexture(name); |
22 | 0 | } |
23 | 0 | } |
24 | | |
25 | | UniquePtr<MozFramebuffer> |
26 | | MozFramebuffer::Create(GLContext* const gl, const gfx::IntSize& size, |
27 | | const uint32_t samples, const bool depthStencil) |
28 | 0 | { |
29 | 0 | if (samples && !gl->IsSupported(GLFeature::framebuffer_multisample)) |
30 | 0 | return nullptr; |
31 | 0 | |
32 | 0 | if (uint32_t(size.width) > gl->MaxTexOrRbSize() || |
33 | 0 | uint32_t(size.height) > gl->MaxTexOrRbSize() || |
34 | 0 | samples > gl->MaxSamples()) |
35 | 0 | { |
36 | 0 | return nullptr; |
37 | 0 | } |
38 | 0 | |
39 | 0 | gl->MakeCurrent(); |
40 | 0 |
|
41 | 0 | GLContext::LocalErrorScope errorScope(*gl); |
42 | 0 |
|
43 | 0 | GLenum colorTarget; |
44 | 0 | GLuint colorName; |
45 | 0 | if (samples) { |
46 | 0 | colorTarget = LOCAL_GL_RENDERBUFFER; |
47 | 0 | colorName = gl->CreateRenderbuffer(); |
48 | 0 | const ScopedBindRenderbuffer bindRB(gl, colorName); |
49 | 0 | gl->fRenderbufferStorageMultisample(colorTarget, samples, LOCAL_GL_RGBA8, |
50 | 0 | size.width, size.height); |
51 | 0 | } else { |
52 | 0 | colorTarget = LOCAL_GL_TEXTURE_2D; |
53 | 0 | colorName = gl->CreateTexture(); |
54 | 0 | const ScopedBindTexture bindTex(gl, colorName); |
55 | 0 | gl->TexParams_SetClampNoMips(); |
56 | 0 | gl->fTexImage2D(colorTarget, 0, LOCAL_GL_RGBA, |
57 | 0 | size.width, size.height, 0, |
58 | 0 | LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr); |
59 | 0 | } |
60 | 0 |
|
61 | 0 | const auto err = errorScope.GetError(); |
62 | 0 | if (err) { |
63 | 0 | if (err != LOCAL_GL_OUT_OF_MEMORY) { |
64 | 0 | gfxCriticalNote << "Unexpected error: " << gfx::hexa(err) << ": " |
65 | 0 | << GLContext::GLErrorToString(err); |
66 | 0 | } |
67 | 0 | DeleteByTarget(gl, colorTarget, colorName); |
68 | 0 | return nullptr; |
69 | 0 | } |
70 | 0 |
|
71 | 0 | return CreateWith(gl, size, samples, depthStencil, colorTarget, colorName); |
72 | 0 | } |
73 | | |
74 | | UniquePtr<MozFramebuffer> |
75 | | MozFramebuffer::CreateWith(GLContext* const gl, const gfx::IntSize& size, |
76 | | const uint32_t samples, const bool depthStencil, |
77 | | const GLenum colorTarget, const GLuint colorName) |
78 | 0 | { |
79 | 0 | UniquePtr<MozFramebuffer> mozFB(new MozFramebuffer(gl, size, samples, depthStencil, |
80 | 0 | colorTarget, colorName)); |
81 | 0 |
|
82 | 0 | const ScopedBindFramebuffer bindFB(gl, mozFB->mFB); |
83 | 0 |
|
84 | 0 | if (colorTarget == LOCAL_GL_RENDERBUFFER) { |
85 | 0 | gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, |
86 | 0 | colorTarget, colorName); |
87 | 0 | } else { |
88 | 0 | gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, |
89 | 0 | colorTarget, colorName, 0); |
90 | 0 | } |
91 | 0 |
|
92 | 0 | const auto fnAllocRB = [&](GLuint rb, GLenum format) { |
93 | 0 | const ScopedBindRenderbuffer bindRB(gl, rb); |
94 | 0 | if (samples) { |
95 | 0 | gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples, format, |
96 | 0 | size.width, size.height); |
97 | 0 | } else { |
98 | 0 | gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, size.width, |
99 | 0 | size.height); |
100 | 0 | } |
101 | 0 | return rb; |
102 | 0 | }; |
103 | 0 |
|
104 | 0 | if (depthStencil) { |
105 | 0 | GLuint depthRB, stencilRB; |
106 | 0 |
|
107 | 0 | { |
108 | 0 | GLContext::LocalErrorScope errorScope(*gl); |
109 | 0 |
|
110 | 0 | if (gl->IsSupported(GLFeature::packed_depth_stencil)) { |
111 | 0 | depthRB = fnAllocRB(mozFB->mDepthRB, LOCAL_GL_DEPTH24_STENCIL8); |
112 | 0 | stencilRB = depthRB; // Ignore unused mStencilRB. |
113 | 0 | } else { |
114 | 0 | depthRB = fnAllocRB(mozFB->mDepthRB , LOCAL_GL_DEPTH_COMPONENT24); |
115 | 0 | stencilRB = fnAllocRB(mozFB->mStencilRB, LOCAL_GL_STENCIL_INDEX8); |
116 | 0 | } |
117 | 0 |
|
118 | 0 | const auto err = errorScope.GetError(); |
119 | 0 | if (err) { |
120 | 0 | MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY); |
121 | 0 | return nullptr; |
122 | 0 | } |
123 | 0 | } |
124 | 0 |
|
125 | 0 | gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, |
126 | 0 | LOCAL_GL_RENDERBUFFER, depthRB); |
127 | 0 | gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, |
128 | 0 | LOCAL_GL_RENDERBUFFER, stencilRB); |
129 | 0 | } |
130 | 0 |
|
131 | 0 | const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); |
132 | 0 | if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) { |
133 | 0 | MOZ_ASSERT(false); |
134 | 0 | return nullptr; |
135 | 0 | } |
136 | 0 |
|
137 | 0 | return mozFB; |
138 | 0 | } |
139 | | |
140 | | //////////////////// |
141 | | |
142 | | MozFramebuffer::MozFramebuffer(GLContext* const gl, const gfx::IntSize& size, |
143 | | const uint32_t samples, const bool depthStencil, |
144 | | const GLenum colorTarget, const GLuint colorName) |
145 | | : mWeakGL(gl) |
146 | | , mSize(size) |
147 | | , mSamples(samples) |
148 | | , mFB(gl->CreateFramebuffer()) |
149 | | , mColorTarget(colorTarget) |
150 | | , mColorName(colorName) |
151 | | , mDepthRB(depthStencil ? gl->CreateRenderbuffer() : 0) |
152 | | , mStencilRB(depthStencil ? gl->CreateRenderbuffer() : 0) |
153 | 0 | { |
154 | 0 | MOZ_ASSERT(mColorTarget); |
155 | 0 | MOZ_ASSERT(mColorName); |
156 | 0 | } |
157 | | |
158 | | MozFramebuffer::~MozFramebuffer() |
159 | 0 | { |
160 | 0 | GLContext* const gl = mWeakGL; |
161 | 0 | if (!gl || !gl->MakeCurrent()) |
162 | 0 | return; |
163 | 0 | |
164 | 0 | gl->DeleteFramebuffer(mFB); |
165 | 0 | gl->DeleteRenderbuffer(mDepthRB); |
166 | 0 | gl->DeleteRenderbuffer(mStencilRB); |
167 | 0 |
|
168 | 0 | DeleteByTarget(gl, mColorTarget, mColorName); |
169 | 0 | } |
170 | | |
171 | | } // namespace gl |
172 | | } // namespace mozilla |