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 38 static tcu::PixelFormat getPixelFormat (deUint32 colorFormat) 39 { 40 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(colorFormat)); 41 return tcu::PixelFormat(bits[0], bits[1], bits[2], bits[3]); 42 } 43 44 static void getDepthStencilBits (deUint32 depthStencilFormat, int* depthBits, int* stencilBits) 45 { 46 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(depthStencilFormat)); 47 *depthBits = bits[0]; 48 *stencilBits = bits[3]; 49 } 50 51 deUint32 chooseColorFormat (const glu::RenderConfig& config) 52 { 53 static const deUint32 s_formats[] = 54 { 55 GL_RGBA8, 56 GL_RGB8, 57 GL_RG8, 58 GL_R8, 59 GL_RGBA4, 60 GL_RGB5_A1, 61 GL_RGB565, 62 GL_RGB5 63 }; 64 65 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++) 66 { 67 const deUint32 format = s_formats[fmtNdx]; 68 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(format)); 69 70 if (config.redBits != glu::RenderConfig::DONT_CARE && 71 config.redBits != bits[0]) 72 continue; 73 74 if (config.greenBits != glu::RenderConfig::DONT_CARE && 75 config.greenBits != bits[1]) 76 continue; 77 78 if (config.blueBits != glu::RenderConfig::DONT_CARE && 79 config.blueBits != bits[2]) 80 continue; 81 82 if (config.alphaBits != glu::RenderConfig::DONT_CARE && 83 config.alphaBits != bits[3]) 84 continue; 85 86 return format; 87 } 88 89 return 0; 90 } 91 92 deUint32 chooseDepthStencilFormat (const glu::RenderConfig& config) 93 { 94 static const deUint32 s_formats[] = 95 { 96 GL_DEPTH32F_STENCIL8, 97 GL_DEPTH24_STENCIL8, 98 GL_DEPTH_COMPONENT32F, 99 GL_DEPTH_COMPONENT24, 100 GL_DEPTH_COMPONENT16, 101 GL_STENCIL_INDEX8 102 }; 103 104 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++) 105 { 106 const deUint32 format = s_formats[fmtNdx]; 107 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(format)); 108 109 if (config.depthBits != glu::RenderConfig::DONT_CARE && 110 config.depthBits != bits[0]) 111 continue; 112 113 if (config.stencilBits != glu::RenderConfig::DONT_CARE && 114 config.stencilBits != bits[3]) 115 continue; 116 117 return format; 118 } 119 120 return 0; 121 } 122 123 FboRenderContext::FboRenderContext (RenderContext* context, const RenderConfig& config) 124 : m_context (context) 125 , m_framebuffer (0) 126 , m_colorBuffer (0) 127 , m_depthStencilBuffer (0) 128 , m_renderTarget () 129 { 130 try 131 { 132 createFramebuffer(config); 133 } 134 catch (...) 135 { 136 destroyFramebuffer(); 137 throw; 138 } 139 } 140 141 FboRenderContext::FboRenderContext (const ContextFactory& factory, const RenderConfig& config, const tcu::CommandLine& cmdLine) 142 : m_context (DE_NULL) 143 , m_framebuffer (0) 144 , m_colorBuffer (0) 145 , m_depthStencilBuffer (0) 146 , m_renderTarget () 147 { 148 try 149 { 150 RenderConfig nativeRenderConfig; 151 nativeRenderConfig.type = config.type; 152 nativeRenderConfig.windowVisibility = config.windowVisibility; 153 // \note All other properties are defaults, mostly DONT_CARE 154 m_context = factory.createContext(nativeRenderConfig, cmdLine); 155 createFramebuffer(config); 156 } 157 catch (...) 158 { 159 delete m_context; 160 throw; 161 } 162 } 163 164 FboRenderContext::~FboRenderContext (void) 165 { 166 // \todo [2013-04-08 pyry] Do we want to destry FBO before destroying context? 167 delete m_context; 168 } 169 170 void FboRenderContext::postIterate (void) 171 { 172 // \todo [2012-11-27 pyry] Blit to default framebuffer in ES3? 173 m_context->getFunctions().finish(); 174 } 175 176 void FboRenderContext::createFramebuffer (const RenderConfig& config) 177 { 178 DE_ASSERT(m_framebuffer == 0 && m_colorBuffer == 0 && m_depthStencilBuffer == 0); 179 180 const glw::Functions& gl = m_context->getFunctions(); 181 const deUint32 colorFormat = chooseColorFormat(config); 182 const deUint32 depthStencilFormat = chooseDepthStencilFormat(config); 183 int width = config.width; 184 int height = config.height; 185 tcu::PixelFormat pixelFormat; 186 int depthBits = 0; 187 int stencilBits = 0; 188 189 if (config.numSamples > 0 && !gl.renderbufferStorageMultisample) 190 throw tcu::NotSupportedError("Multisample FBO is not supported"); 191 192 if (colorFormat == 0) 193 throw tcu::NotSupportedError("Unsupported color attachment format"); 194 195 if (width == glu::RenderConfig::DONT_CARE || height == glu::RenderConfig::DONT_CARE) 196 { 197 int maxSize = 0; 198 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize); 199 200 width = (width == glu::RenderConfig::DONT_CARE) ? maxSize : width; 201 height = (height == glu::RenderConfig::DONT_CARE) ? maxSize : height; 202 } 203 204 { 205 pixelFormat = getPixelFormat(colorFormat); 206 207 gl.genRenderbuffers(1, &m_colorBuffer); 208 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer); 209 210 if (config.numSamples > 0) 211 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, colorFormat, width, height); 212 else 213 gl.renderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height); 214 215 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 216 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer"); 217 } 218 219 if (depthStencilFormat != GL_NONE) 220 { 221 getDepthStencilBits(depthStencilFormat, &depthBits, &stencilBits); 222 223 gl.genRenderbuffers(1, &m_depthStencilBuffer); 224 gl.bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); 225 226 if (config.numSamples > 0) 227 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, depthStencilFormat, width, height); 228 else 229 gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height); 230 231 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 232 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer"); 233 } 234 235 gl.genFramebuffers(1, &m_framebuffer); 236 gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 237 238 if (m_colorBuffer) 239 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer); 240 241 if (m_depthStencilBuffer) 242 { 243 if (depthBits > 0) 244 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 245 246 if (stencilBits > 0) 247 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 248 } 249 250 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer"); 251 252 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 253 throw tcu::NotSupportedError("Framebuffer is not complete"); 254 255 // Set up correct viewport for first test case. 256 gl.viewport(0, 0, width, height); 257 258 m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, config.numSamples); 259 } 260 261 void FboRenderContext::destroyFramebuffer (void) 262 { 263 const glw::Functions& gl = m_context->getFunctions(); 264 265 if (m_framebuffer) 266 { 267 gl.deleteFramebuffers(1, &m_framebuffer); 268 m_framebuffer = 0; 269 } 270 271 if (m_depthStencilBuffer) 272 { 273 gl.deleteRenderbuffers(1, &m_depthStencilBuffer); 274 m_depthStencilBuffer = 0; 275 } 276 277 if (m_colorBuffer) 278 { 279 gl.deleteRenderbuffers(1, &m_colorBuffer); 280 m_colorBuffer = 0; 281 } 282 } 283 284 } // glu 285