• Home
  • History
  • Annotate
  • 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