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