• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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