Home | History | Annotate | Download | only in opengl
      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