1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief OpenGL ES context wrapper that uses FBO as default framebuffer.
22 *//*--------------------------------------------------------------------*/
23
24 #include "gluFboRenderContext.hpp"
25 #include "gluContextFactory.hpp"
26 #include "gluRenderConfig.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuCommandLine.hpp"
30 #include "gluTextureUtil.hpp"
31 #include "tcuTextureUtil.hpp"
32
33 #include <sstream>
34
35 namespace glu
36 {
37
getNumDepthBits(const tcu::TextureFormat & format)38 static int getNumDepthBits (const tcu::TextureFormat& format)
39 {
40 if (format.order == tcu::TextureFormat::DS)
41 {
42 const tcu::TextureFormat depthOnlyFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_DEPTH);
43 return tcu::getTextureFormatBitDepth(depthOnlyFormat).x();
44 }
45 else if (format.order == tcu::TextureFormat::D)
46 return tcu::getTextureFormatBitDepth(format).x();
47 else
48 return 0;
49 }
50
getNumStencilBits(const tcu::TextureFormat & format)51 static int getNumStencilBits (const tcu::TextureFormat& format)
52 {
53 if (format.order == tcu::TextureFormat::DS)
54 {
55 const tcu::TextureFormat stencilOnlyFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_STENCIL);
56 return tcu::getTextureFormatBitDepth(stencilOnlyFormat).x();
57 }
58 else if (format.order == tcu::TextureFormat::S)
59 return tcu::getTextureFormatBitDepth(format).x();
60 else
61 return 0;
62 }
63
getPixelFormat(deUint32 colorFormat)64 static tcu::PixelFormat getPixelFormat (deUint32 colorFormat)
65 {
66 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(colorFormat));
67 return tcu::PixelFormat(bits[0], bits[1], bits[2], bits[3]);
68 }
69
getDepthStencilBits(deUint32 depthStencilFormat,int * depthBits,int * stencilBits)70 static void getDepthStencilBits (deUint32 depthStencilFormat, int* depthBits, int* stencilBits)
71 {
72 const tcu::TextureFormat combinedFormat = glu::mapGLInternalFormat(depthStencilFormat);
73
74 *depthBits = getNumDepthBits(combinedFormat);
75 *stencilBits = getNumStencilBits(combinedFormat);
76 }
77
chooseColorFormat(const glu::RenderConfig & config)78 deUint32 chooseColorFormat (const glu::RenderConfig& config)
79 {
80 static const deUint32 s_formats[] =
81 {
82 GL_RGBA8,
83 GL_RGB8,
84 GL_RG8,
85 GL_R8,
86 GL_RGBA4,
87 GL_RGB5_A1,
88 GL_RGB565,
89 GL_RGB5
90 };
91
92 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++)
93 {
94 const deUint32 format = s_formats[fmtNdx];
95 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(format));
96
97 if (config.redBits != glu::RenderConfig::DONT_CARE &&
98 config.redBits != bits[0])
99 continue;
100
101 if (config.greenBits != glu::RenderConfig::DONT_CARE &&
102 config.greenBits != bits[1])
103 continue;
104
105 if (config.blueBits != glu::RenderConfig::DONT_CARE &&
106 config.blueBits != bits[2])
107 continue;
108
109 if (config.alphaBits != glu::RenderConfig::DONT_CARE &&
110 config.alphaBits != bits[3])
111 continue;
112
113 return format;
114 }
115
116 return 0;
117 }
118
chooseDepthStencilFormat(const glu::RenderConfig & config)119 deUint32 chooseDepthStencilFormat (const glu::RenderConfig& config)
120 {
121 static const deUint32 s_formats[] =
122 {
123 GL_DEPTH32F_STENCIL8,
124 GL_DEPTH24_STENCIL8,
125 GL_DEPTH_COMPONENT32F,
126 GL_DEPTH_COMPONENT24,
127 GL_DEPTH_COMPONENT16,
128 GL_STENCIL_INDEX8
129 };
130
131 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++)
132 {
133 const deUint32 format = s_formats[fmtNdx];
134 const tcu::TextureFormat combinedFormat = glu::mapGLInternalFormat(format);
135 const int depthBits = getNumDepthBits(combinedFormat);
136 const int stencilBits = getNumStencilBits(combinedFormat);
137
138 if (config.depthBits != glu::RenderConfig::DONT_CARE &&
139 config.depthBits != depthBits)
140 continue;
141
142 if (config.stencilBits != glu::RenderConfig::DONT_CARE &&
143 config.stencilBits != stencilBits)
144 continue;
145
146 return format;
147 }
148
149 return 0;
150 }
151
FboRenderContext(RenderContext * context,const RenderConfig & config)152 FboRenderContext::FboRenderContext (RenderContext* context, const RenderConfig& config)
153 : m_context (context)
154 , m_framebuffer (0)
155 , m_colorBuffer (0)
156 , m_depthStencilBuffer (0)
157 , m_renderTarget ()
158 {
159 try
160 {
161 createFramebuffer(config);
162 }
163 catch (...)
164 {
165 destroyFramebuffer();
166 throw;
167 }
168 }
169
FboRenderContext(const ContextFactory & factory,const RenderConfig & config,const tcu::CommandLine & cmdLine)170 FboRenderContext::FboRenderContext (const ContextFactory& factory, const RenderConfig& config, const tcu::CommandLine& cmdLine)
171 : m_context (DE_NULL)
172 , m_framebuffer (0)
173 , m_colorBuffer (0)
174 , m_depthStencilBuffer (0)
175 , m_renderTarget ()
176 {
177 try
178 {
179 RenderConfig nativeRenderConfig;
180 nativeRenderConfig.type = config.type;
181 nativeRenderConfig.windowVisibility = config.windowVisibility;
182 // \note All other properties are defaults, mostly DONT_CARE
183 m_context = factory.createContext(nativeRenderConfig, cmdLine);
184 createFramebuffer(config);
185 }
186 catch (...)
187 {
188 delete m_context;
189 throw;
190 }
191 }
192
~FboRenderContext(void)193 FboRenderContext::~FboRenderContext (void)
194 {
195 // \todo [2013-04-08 pyry] Do we want to destry FBO before destroying context?
196 delete m_context;
197 }
198
postIterate(void)199 void FboRenderContext::postIterate (void)
200 {
201 // \todo [2012-11-27 pyry] Blit to default framebuffer in ES3?
202 m_context->getFunctions().finish();
203 }
204
createFramebuffer(const RenderConfig & config)205 void FboRenderContext::createFramebuffer (const RenderConfig& config)
206 {
207 DE_ASSERT(m_framebuffer == 0 && m_colorBuffer == 0 && m_depthStencilBuffer == 0);
208
209 const glw::Functions& gl = m_context->getFunctions();
210 const deUint32 colorFormat = chooseColorFormat(config);
211 const deUint32 depthStencilFormat = chooseDepthStencilFormat(config);
212 int width = config.width;
213 int height = config.height;
214 tcu::PixelFormat pixelFormat;
215 int depthBits = 0;
216 int stencilBits = 0;
217
218 if (config.numSamples > 0 && !gl.renderbufferStorageMultisample)
219 throw tcu::NotSupportedError("Multisample FBO is not supported");
220
221 if (colorFormat == 0)
222 throw tcu::NotSupportedError("Unsupported color attachment format");
223
224 if (width == glu::RenderConfig::DONT_CARE || height == glu::RenderConfig::DONT_CARE)
225 {
226 int maxSize = 0;
227 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
228
229 width = (width == glu::RenderConfig::DONT_CARE) ? maxSize : width;
230 height = (height == glu::RenderConfig::DONT_CARE) ? maxSize : height;
231 }
232
233 {
234 pixelFormat = getPixelFormat(colorFormat);
235
236 gl.genRenderbuffers(1, &m_colorBuffer);
237 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);
238
239 if (config.numSamples > 0)
240 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, colorFormat, width, height);
241 else
242 gl.renderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
243
244 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
245 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer");
246 }
247
248 if (depthStencilFormat != GL_NONE)
249 {
250 getDepthStencilBits(depthStencilFormat, &depthBits, &stencilBits);
251
252 gl.genRenderbuffers(1, &m_depthStencilBuffer);
253 gl.bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
254
255 if (config.numSamples > 0)
256 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, depthStencilFormat, width, height);
257 else
258 gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
259
260 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
261 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer");
262 }
263
264 gl.genFramebuffers(1, &m_framebuffer);
265 gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
266
267 if (m_colorBuffer)
268 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
269
270 if (m_depthStencilBuffer)
271 {
272 if (depthBits > 0)
273 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
274
275 if (stencilBits > 0)
276 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
277 }
278
279 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer");
280
281 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
282 throw tcu::NotSupportedError("Framebuffer is not complete");
283
284 // Set up correct viewport for first test case.
285 gl.viewport(0, 0, width, height);
286
287 m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, config.numSamples);
288 }
289
destroyFramebuffer(void)290 void FboRenderContext::destroyFramebuffer (void)
291 {
292 const glw::Functions& gl = m_context->getFunctions();
293
294 if (m_framebuffer)
295 {
296 gl.deleteFramebuffers(1, &m_framebuffer);
297 m_framebuffer = 0;
298 }
299
300 if (m_depthStencilBuffer)
301 {
302 gl.deleteRenderbuffers(1, &m_depthStencilBuffer);
303 m_depthStencilBuffer = 0;
304 }
305
306 if (m_colorBuffer)
307 {
308 gl.deleteRenderbuffers(1, &m_colorBuffer);
309 m_colorBuffer = 0;
310 }
311 }
312
313 } // glu
314