1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
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 Framebuffer completeness tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es2fFboCompletenessTests.hpp"
25
26#include "glsFboCompletenessTests.hpp"
27#include "gluObjectWrapper.hpp"
28
29using namespace glw;
30using deqp::gls::Range;
31using namespace deqp::gls::FboUtil;
32using namespace deqp::gls::FboUtil::config;
33namespace fboc = deqp::gls::fboc;
34typedef tcu::TestCase::IterateResult IterateResult;
35
36namespace deqp
37{
38namespace gles2
39{
40namespace Functional
41{
42
43static const FormatKey s_es2ColorRenderables[] =
44{
45	GL_RGBA4, GL_RGB5_A1, GL_RGB565,
46};
47
48// GLES2 does not strictly allow these, but this seems to be a bug in the
49// specification. For now, let's assume the unsized formats corresponding to
50// the color-renderable sized formats are allowed.
51// See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7333
52
53static const FormatKey s_es2UnsizedColorRenderables[] =
54{
55	GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),
56	GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1),
57	GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_SHORT_5_6_5)
58};
59
60static const FormatKey s_es2DepthRenderables[] =
61{
62	GL_DEPTH_COMPONENT16,
63};
64
65static const FormatKey s_es2StencilRenderables[] =
66{
67	GL_STENCIL_INDEX8,
68};
69
70static const FormatEntry s_es2Formats[] =
71{
72	{ COLOR_RENDERABLE | TEXTURE_VALID,
73	  GLS_ARRAY_RANGE(s_es2UnsizedColorRenderables) },
74	{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID,
75	  GLS_ARRAY_RANGE(s_es2ColorRenderables) },
76	{ REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID,
77	  GLS_ARRAY_RANGE(s_es2DepthRenderables) },
78	{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID,
79	  GLS_ARRAY_RANGE(s_es2StencilRenderables) },
80};
81
82// We have here only the extensions that are redundant in vanilla GLES3. Those
83// that are applicable both to GLES2 and GLES3 are in glsFboCompletenessTests.cpp.
84
85// GL_OES_texture_float
86static const FormatKey s_oesTextureFloatFormats[] =
87{
88	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_FLOAT),
89	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_FLOAT),
90};
91
92// GL_OES_texture_half_float
93static const FormatKey s_oesTextureHalfFloatFormats[] =
94{
95	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_HALF_FLOAT_OES),
96	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_HALF_FLOAT_OES),
97};
98
99// GL_EXT_sRGB_write_control
100static const FormatKey s_extSrgbWriteControlFormats[] =
101{
102	GL_SRGB8_ALPHA8
103};
104
105// DEQP_gles3_core_no_extension_features
106static const FormatKey s_es3NoExtRboFormats[] =
107{
108	GL_RGB10_A2,
109};
110static const FormatKey s_es3NoExtTextureFormats[] =
111{
112	GL_R16F,
113	GL_RG16F,
114	GL_RGB16F,
115	GL_RGBA16F,
116	GL_R11F_G11F_B10F,
117};
118static const FormatKey s_es3NoExtTextureColorRenderableFormats[] =
119{
120	GL_R8,
121	GL_RG8,
122};
123
124// with ES3 core and GL_EXT_color_buffer_float
125static const FormatKey s_es3NoExtExtColorBufferFloatFormats[] =
126{
127	// \note Only the GLES2+exts subset of formats
128	GL_R11F_G11F_B10F, GL_RGBA16F, GL_RG16F, GL_R16F,
129};
130
131// with ES3 core with OES_texture_stencil8
132static const FormatKey s_es3NoExtOesTextureStencil8Formats[] =
133{
134	GL_STENCIL_INDEX8,
135};
136
137static const FormatExtEntry s_es2ExtFormats[] =
138{
139	// The extension does not specify these to be color-renderable.
140	{
141		"GL_OES_texture_float",
142		TEXTURE_VALID,
143		GLS_ARRAY_RANGE(s_oesTextureFloatFormats)
144	},
145	{
146		"GL_OES_texture_half_float",
147		TEXTURE_VALID,
148		GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)
149	},
150
151	// GL_EXT_sRGB_write_control makes SRGB8_ALPHA8 color-renderable
152	{
153		"GL_EXT_sRGB_write_control",
154		REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID,
155		GLS_ARRAY_RANGE(s_extSrgbWriteControlFormats)
156	},
157
158	// Since GLES3 is "backwards compatible" to GLES2, we might actually be running on a GLES3
159	// context. Since GLES3 added some features to core with no corresponding GLES2 extension,
160	// some tests might produce wrong results (since they are using rules of GLES2 & extensions)
161	//
162	// To avoid this, require new features of GLES3 that have no matching GLES2 extension if
163	// context is GLES3. This can be done with a DEQP_* extensions.
164	//
165	// \note Not all feature changes are listed here but only those that alter GLES2 subset of
166	//       the formats
167	{
168		"DEQP_gles3_core_compatible",
169		REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID,
170		GLS_ARRAY_RANGE(s_es3NoExtRboFormats)
171	},
172	{
173		"DEQP_gles3_core_compatible",
174		TEXTURE_VALID,
175		GLS_ARRAY_RANGE(s_es3NoExtTextureFormats)
176	},
177	{
178		"DEQP_gles3_core_compatible",
179		REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE,
180		GLS_ARRAY_RANGE(s_es3NoExtTextureColorRenderableFormats)
181	},
182	{
183		"DEQP_gles3_core_compatible GL_EXT_color_buffer_float",
184		REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID,
185		GLS_ARRAY_RANGE(s_es3NoExtExtColorBufferFloatFormats)
186	},
187	{
188		"DEQP_gles3_core_compatible GL_OES_texture_stencil8",
189		REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID,
190		GLS_ARRAY_RANGE(s_es3NoExtOesTextureStencil8Formats)
191	},
192};
193
194class ES2Checker : public Checker
195{
196public:
197			ES2Checker				(const glu::RenderContext& ctx);
198	void	check					(GLenum attPoint, const Attachment& att,
199									 const Image* image);
200private:
201	GLsizei	m_width;	//< The common width of images
202	GLsizei	m_height;	//< The common height of images
203};
204
205ES2Checker::ES2Checker (const glu::RenderContext& ctx)\
206	: Checker		(ctx)
207	, m_width		(-1)
208	, m_height		(-1)
209{
210}
211
212void ES2Checker::check (GLenum attPoint, const Attachment& att, const Image* image)
213{
214	DE_UNREF(attPoint);
215	DE_UNREF(att);
216	// GLES2: "All attached images have the same width and height."
217	if (m_width == -1)
218	{
219		m_width = image->width;
220		m_height = image->height;
221	}
222	else if (image->width != m_width || image->height != m_height)
223	{
224		// Since GLES3 is "backwards compatible" to GLES2, we might actually be running
225		// on a GLES3 context. On GLES3, FRAMEBUFFER_INCOMPLETE_DIMENSIONS is not generated
226		// if attachments have different sizes.
227		if (!gls::FboUtil::checkExtensionSupport(m_renderCtx, "DEQP_gles3_core_compatible"))
228		{
229			// running on GLES2
230			addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "Sizes of attachments differ");
231		}
232	}
233	// GLES2, 4.4.5: "some implementations may not support rendering to
234	// particular combinations of internal formats. If the combination of
235	// formats of the images attached to a framebuffer object are not
236	// supported by the implementation, then the framebuffer is not complete
237	// under the clause labeled FRAMEBUFFER_UNSUPPORTED."
238	//
239	// Hence it is _always_ allowed to report FRAMEBUFFER_UNSUPPORTED.
240	addPotentialFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Particular format combinations need not to be supported");
241}
242
243struct FormatCombination
244{
245	GLenum			colorKind;
246	ImageFormat		colorFmt;
247	GLenum			depthKind;
248	ImageFormat		depthFmt;
249	GLenum			stencilKind;
250	ImageFormat		stencilFmt;
251};
252
253class SupportedCombinationTest : public fboc::TestBase
254{
255public:
256					SupportedCombinationTest	(fboc::Context& ctx,
257												 const char* name, const char* desc)
258						: TestBase		(ctx, name, desc) {}
259
260	IterateResult	iterate						(void);
261	bool			tryCombination				(const FormatCombination& comb);
262	GLenum			formatKind					(ImageFormat fmt);
263};
264
265bool SupportedCombinationTest::tryCombination (const FormatCombination& comb)
266{
267	glu::Framebuffer fbo(m_ctx.getRenderContext());
268	FboBuilder builder(*fbo, GL_FRAMEBUFFER, fboc::gl(*this));
269
270	attachTargetToNew(GL_COLOR_ATTACHMENT0,		comb.colorKind,		comb.colorFmt,
271					  64, 						64,					builder);
272	attachTargetToNew(GL_DEPTH_ATTACHMENT,		comb.depthKind,		comb.depthFmt,
273					  64,						64,					builder);
274	attachTargetToNew(GL_STENCIL_ATTACHMENT,	comb.stencilKind,	comb.stencilFmt,
275					  64,						64,					builder);
276
277	const GLenum glStatus = fboc::gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER);
278
279	return (glStatus == GL_FRAMEBUFFER_COMPLETE);
280}
281
282GLenum SupportedCombinationTest::formatKind (ImageFormat fmt)
283{
284	if (fmt.format == GL_NONE)
285		return GL_NONE;
286
287	const FormatFlags flags = m_ctx.getCoreFormats().getFormatInfo(fmt);
288	const bool rbo = (flags & RENDERBUFFER_VALID) != 0;
289	// exactly one of renderbuffer and texture is supported by vanilla GLES2 formats
290	DE_ASSERT(rbo != ((flags & TEXTURE_VALID) != 0));
291
292	return rbo ? GL_RENDERBUFFER : GL_TEXTURE;
293}
294
295IterateResult SupportedCombinationTest::iterate (void)
296{
297	const FormatDB& db		= m_ctx.getCoreFormats();
298	const ImageFormat none	= ImageFormat::none();
299	Formats colorFmts		= db.getFormats(COLOR_RENDERABLE);
300	Formats depthFmts		= db.getFormats(DEPTH_RENDERABLE);
301	Formats stencilFmts		= db.getFormats(STENCIL_RENDERABLE);
302	FormatCombination comb;
303	bool succ = false;
304
305	colorFmts.insert(none);
306	depthFmts.insert(none);
307	stencilFmts.insert(none);
308
309	for (Formats::const_iterator col = colorFmts.begin(); col != colorFmts.end(); col++)
310	{
311		comb.colorFmt = *col;
312		comb.colorKind = formatKind(*col);
313		for (Formats::const_iterator dep = depthFmts.begin(); dep != depthFmts.end(); dep++)
314		{
315			comb.depthFmt = *dep;
316			comb.depthKind = formatKind(*dep);
317			for (Formats::const_iterator stc = stencilFmts.begin();
318				 stc != stencilFmts.end(); stc++)
319			{
320				comb.stencilFmt = *stc;
321				comb.stencilKind = formatKind(*stc);
322				succ = tryCombination(comb);
323				if (succ)
324					break;
325			}
326		}
327	}
328
329	if (succ)
330		pass();
331	else
332		fail("No supported format combination found");
333
334	return STOP;
335}
336
337class ES2CheckerFactory : public CheckerFactory
338{
339public:
340	Checker*			createChecker	(const glu::RenderContext& ctx) { return new ES2Checker(ctx); }
341};
342
343class TestGroup : public TestCaseGroup
344{
345public:
346						TestGroup		(Context& ctx);
347	void				init			(void);
348private:
349	ES2CheckerFactory	m_checkerFactory;
350	fboc::Context		m_fboc;
351};
352
353TestGroup::TestGroup (Context& ctx)
354	: TestCaseGroup		(ctx, "completeness", "Completeness tests")
355	, m_checkerFactory	()
356	, m_fboc			(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
357{
358	const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es2Formats);
359	const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es2ExtFormats);
360
361	m_fboc.addFormats(stdRange);
362	m_fboc.addExtFormats(extRange);
363	m_fboc.setHaveMulticolorAtts(
364		ctx.getContextInfo().isExtensionSupported("GL_NV_fbo_color_attachments"));
365}
366
367void TestGroup::init (void)
368{
369	tcu::TestCaseGroup* attCombTests = m_fboc.createAttachmentTests();
370	addChild(m_fboc.createRenderableTests());
371	attCombTests->addChild(new SupportedCombinationTest(
372							   m_fboc,
373							   "exists_supported",
374							   "Test for existence of a supported combination of formats"));
375	addChild(attCombTests);
376	addChild(m_fboc.createSizeTests());
377}
378
379tcu::TestCaseGroup* createFboCompletenessTests (Context& context)
380{
381	return new TestGroup(context);
382}
383
384} // Functional
385} // gles2
386} // deqp
387