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
105static const FormatExtEntry s_es2ExtFormats[] =
106{
107	// The extension does not specify these to be color-renderable.
108	{
109		"GL_OES_texture_float",
110		TEXTURE_VALID,
111		GLS_ARRAY_RANGE(s_oesTextureFloatFormats)
112	},
113	{
114		"GL_OES_texture_half_float",
115		TEXTURE_VALID,
116		GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)
117	},
118
119	// GL_EXT_sRGB_write_control makes SRGB8_ALPHA8 color-renderable
120	{
121		"GL_EXT_sRGB_write_control",
122		REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID,
123		GLS_ARRAY_RANGE(s_extSrgbWriteControlFormats)
124	},
125};
126
127class ES2Checker : public Checker
128{
129public:
130			ES2Checker				(void) : m_width(-1), m_height(-1) {}
131	void	check					(GLenum attPoint, const Attachment& att,
132									 const Image* image);
133private:
134	GLsizei	m_width;	//< The common width of images
135	GLsizei	m_height;	//< The common height of images
136};
137
138void ES2Checker::check(GLenum attPoint, const Attachment& att, const Image* image)
139{
140	DE_UNREF(attPoint);
141	DE_UNREF(att);
142	// GLES2: "All attached images have the same width and height."
143	if (m_width == -1)
144	{
145		m_width = image->width;
146		m_height = image->height;
147	}
148	else
149	{
150		require(image->width == m_width && image->height == m_height,
151				GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
152	}
153	// GLES2, 4.4.5: "some implementations may not support rendering to
154	// particular combinations of internal formats. If the combination of
155	// formats of the images attached to a framebuffer object are not
156	// supported by the implementation, then the framebuffer is not complete
157	// under the clause labeled FRAMEBUFFER_UNSUPPORTED."
158	//
159	// Hence it is _always_ allowed to report FRAMEBUFFER_UNSUPPORTED.
160	canRequire(false, GL_FRAMEBUFFER_UNSUPPORTED);
161}
162
163struct FormatCombination
164{
165	GLenum			colorKind;
166	ImageFormat		colorFmt;
167	GLenum			depthKind;
168	ImageFormat		depthFmt;
169	GLenum			stencilKind;
170	ImageFormat		stencilFmt;
171};
172
173class SupportedCombinationTest : public fboc::TestBase
174{
175public:
176					SupportedCombinationTest	(fboc::Context& ctx,
177												 const char* name, const char* desc)
178						: TestBase		(ctx, name, desc) {}
179
180	IterateResult	iterate						(void);
181	bool			tryCombination				(const FormatCombination& comb);
182	GLenum			formatKind					(ImageFormat fmt);
183};
184
185bool SupportedCombinationTest::tryCombination (const FormatCombination& comb)
186{
187	glu::Framebuffer fbo(m_ctx.getRenderContext());
188	FboBuilder builder(*fbo, GL_FRAMEBUFFER, fboc::gl(*this));
189
190	attachTargetToNew(GL_COLOR_ATTACHMENT0,		comb.colorKind,		comb.colorFmt,
191					  64, 						64,					builder);
192	attachTargetToNew(GL_DEPTH_ATTACHMENT,		comb.depthKind,		comb.depthFmt,
193					  64,						64,					builder);
194	attachTargetToNew(GL_STENCIL_ATTACHMENT,	comb.stencilKind,	comb.stencilFmt,
195					  64,						64,					builder);
196
197	const GLenum glStatus = fboc::gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER);
198
199	return (glStatus == GL_FRAMEBUFFER_COMPLETE);
200}
201
202GLenum SupportedCombinationTest::formatKind (ImageFormat fmt)
203{
204	if (fmt.format == GL_NONE)
205		return GL_NONE;
206
207	const FormatFlags flags = m_ctx.getMinFormats().getFormatInfo(fmt, ANY_FORMAT);
208	const bool rbo = (flags & RENDERBUFFER_VALID) != 0;
209	// exactly one of renderbuffer and texture is supported by vanilla GLES2 formats
210	DE_ASSERT(rbo != ((flags & TEXTURE_VALID) != 0));
211
212	return rbo ? GL_RENDERBUFFER : GL_TEXTURE;
213}
214
215IterateResult SupportedCombinationTest::iterate (void)
216{
217	const FormatDB& db		= m_ctx.getMinFormats();
218	const ImageFormat none	= ImageFormat::none();
219	Formats colorFmts		= db.getFormats(COLOR_RENDERABLE);
220	Formats depthFmts		= db.getFormats(DEPTH_RENDERABLE);
221	Formats stencilFmts		= db.getFormats(STENCIL_RENDERABLE);
222	FormatCombination comb;
223	bool succ = false;
224
225	colorFmts.insert(none);
226	depthFmts.insert(none);
227	stencilFmts.insert(none);
228
229	for (Formats::const_iterator col = colorFmts.begin(); col != colorFmts.end(); col++)
230	{
231		comb.colorFmt = *col;
232		comb.colorKind = formatKind(*col);
233		for (Formats::const_iterator dep = depthFmts.begin(); dep != depthFmts.end(); dep++)
234		{
235			comb.depthFmt = *dep;
236			comb.depthKind = formatKind(*dep);
237			for (Formats::const_iterator stc = stencilFmts.begin();
238				 stc != stencilFmts.end(); stc++)
239			{
240				comb.stencilFmt = *stc;
241				comb.stencilKind = formatKind(*stc);
242				succ = tryCombination(comb);
243				if (succ)
244					break;
245			}
246		}
247	}
248
249	if (succ)
250		pass();
251	else
252		fail("No supported format combination found");
253
254	return STOP;
255}
256
257class ES2CheckerFactory : public CheckerFactory {
258public:
259	Checker*			createChecker	(void) { return new ES2Checker(); }
260};
261
262class TestGroup : public TestCaseGroup
263{
264public:
265						TestGroup		(Context& ctx);
266	void				init			(void);
267private:
268	ES2CheckerFactory	m_checkerFactory;
269	fboc::Context		m_fboc;
270};
271
272TestGroup::TestGroup (Context& ctx)
273	: TestCaseGroup		(ctx, "completeness", "Completeness tests")
274	, m_checkerFactory	()
275	, m_fboc			(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
276{
277	const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es2Formats);
278	const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es2ExtFormats);
279
280	m_fboc.addFormats(stdRange);
281	m_fboc.addExtFormats(extRange);
282	m_fboc.setHaveMulticolorAtts(
283		ctx.getContextInfo().isExtensionSupported("GL_NV_fbo_color_attachments"));
284}
285
286void TestGroup::init (void)
287{
288	tcu::TestCaseGroup* attCombTests = m_fboc.createAttachmentTests();
289	addChild(m_fboc.createRenderableTests());
290	attCombTests->addChild(new SupportedCombinationTest(
291							   m_fboc,
292							   "exists_supported",
293							   "Test for existence of a supported combination of formats"));
294	addChild(attCombTests);
295	addChild(m_fboc.createSizeTests());
296}
297
298tcu::TestCaseGroup* createFboCompletenessTests (Context& context)
299{
300	return new TestGroup(context);
301}
302
303} // Functional
304} // gles2
305} // deqp
306