1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief OpenGL ES context wrapper that uses FBO as default framebuffer.
22 *//*--------------------------------------------------------------------*/
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"
38 static int getNumDepthBits (const tcu::TextureFormat& format)
40 if (format.order == tcu::TextureFormat::DS)
42 const tcu::TextureFormat depthOnlyFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_DEPTH);
43 return tcu::getTextureFormatBitDepth(depthOnlyFormat).x();
45 else if (format.order == tcu::TextureFormat::D)
46 return tcu::getTextureFormatBitDepth(format).x();
51 static int getNumStencilBits (const tcu::TextureFormat& format)
53 if (format.order == tcu::TextureFormat::DS)
55 const tcu::TextureFormat stencilOnlyFormat = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_STENCIL);
56 return tcu::getTextureFormatBitDepth(stencilOnlyFormat).x();
58 else if (format.order == tcu::TextureFormat::S)
59 return tcu::getTextureFormatBitDepth(format).x();
64 static tcu::PixelFormat getPixelFormat (deUint32 colorFormat)
66 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(colorFormat));
67 return tcu::PixelFormat(bits[0], bits[1], bits[2], bits[3]);
70 static void getDepthStencilBits (deUint32 depthStencilFormat, int* depthBits, int* stencilBits)
72 const tcu::TextureFormat combinedFormat = glu::mapGLInternalFormat(depthStencilFormat);
74 *depthBits = getNumDepthBits(combinedFormat);
75 *stencilBits = getNumStencilBits(combinedFormat);
78 deUint32 chooseColorFormat (const glu::RenderConfig& config)
80 static const deUint32 s_formats[] =
92 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++)
94 const deUint32 format = s_formats[fmtNdx];
95 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(format));
97 if (config.redBits != glu::RenderConfig::DONT_CARE &&
98 config.redBits != bits[0])
101 if (config.greenBits != glu::RenderConfig::DONT_CARE &&
102 config.greenBits != bits[1])
105 if (config.blueBits != glu::RenderConfig::DONT_CARE &&
106 config.blueBits != bits[2])
109 if (config.alphaBits != glu::RenderConfig::DONT_CARE &&
110 config.alphaBits != bits[3])
119 deUint32 chooseDepthStencilFormat (const glu::RenderConfig& config)
121 static const deUint32 s_formats[] =
123 GL_DEPTH32F_STENCIL8,
125 GL_DEPTH_COMPONENT32F,
126 GL_DEPTH_COMPONENT24,
127 GL_DEPTH_COMPONENT16,
131 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++)
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);
138 if (config.depthBits != glu::RenderConfig::DONT_CARE &&
139 config.depthBits != depthBits)
142 if (config.stencilBits != glu::RenderConfig::DONT_CARE &&
143 config.stencilBits != stencilBits)
152 FboRenderContext::FboRenderContext (RenderContext* context, const RenderConfig& config)
153 : m_context (context)
156 , m_depthStencilBuffer (0)
161 createFramebuffer(config);
165 destroyFramebuffer();
170 FboRenderContext::FboRenderContext (const ContextFactory& factory, const RenderConfig& config, const tcu::CommandLine& cmdLine)
171 : m_context (DE_NULL)
174 , m_depthStencilBuffer (0)
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);
193 FboRenderContext::~FboRenderContext (void)
195 // \todo [2013-04-08 pyry] Do we want to destry FBO before destroying context?
199 void FboRenderContext::postIterate (void)
201 // \todo [2012-11-27 pyry] Blit to default framebuffer in ES3?
202 m_context->getFunctions().finish();
205 void FboRenderContext::createFramebuffer (const RenderConfig& config)
207 DE_ASSERT(m_framebuffer == 0 && m_colorBuffer == 0 && m_depthStencilBuffer == 0);
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;
218 if (config.numSamples > 0 && !gl.renderbufferStorageMultisample)
219 throw tcu::NotSupportedError("Multisample FBO is not supported");
221 if (colorFormat == 0)
222 throw tcu::NotSupportedError("Unsupported color attachment format");
224 if (width == glu::RenderConfig::DONT_CARE || height == glu::RenderConfig::DONT_CARE)
227 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
229 width = (width == glu::RenderConfig::DONT_CARE) ? maxSize : width;
230 height = (height == glu::RenderConfig::DONT_CARE) ? maxSize : height;
234 pixelFormat = getPixelFormat(colorFormat);
236 gl.genRenderbuffers(1, &m_colorBuffer);
237 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);
239 if (config.numSamples > 0)
240 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, colorFormat, width, height);
242 gl.renderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
244 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
245 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer");
248 if (depthStencilFormat != GL_NONE)
250 getDepthStencilBits(depthStencilFormat, &depthBits, &stencilBits);
252 gl.genRenderbuffers(1, &m_depthStencilBuffer);
253 gl.bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
255 if (config.numSamples > 0)
256 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, depthStencilFormat, width, height);
258 gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
260 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
261 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer");
264 gl.genFramebuffers(1, &m_framebuffer);
265 gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
268 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
270 if (m_depthStencilBuffer)
273 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
276 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
279 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer");
281 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
282 throw tcu::NotSupportedError("Framebuffer is not complete");
284 // Set up correct viewport for first test case.
285 gl.viewport(0, 0, width, height);
287 m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, config.numSamples);
290 void FboRenderContext::destroyFramebuffer (void)
292 const glw::Functions& gl = m_context->getFunctions();
296 gl.deleteFramebuffers(1, &m_framebuffer);
300 if (m_depthStencilBuffer)
302 gl.deleteRenderbuffers(1, &m_depthStencilBuffer);
303 m_depthStencilBuffer = 0;
308 gl.deleteRenderbuffers(1, &m_colorBuffer);