• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23 
24 /*!
25  * \file  esextcDrawBuffersIndexedColorMasks.hpp
26  * \brief Draw Buffers Indexed tests 4. Color masks
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "esextcDrawBuffersIndexedColorMasks.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "tcuTestLog.hpp"
33 #include <cmath>
34 
35 namespace glcts
36 {
37 
38 /** Constructor
39  *
40  *  @param context     Test context
41  *  @param name        Test case's name
42  *  @param description Test case's description
43  **/
DrawBuffersIndexedColorMasks(Context & context,const ExtParameters & extParams,const char * name,const char * description)44 DrawBuffersIndexedColorMasks::DrawBuffersIndexedColorMasks(Context& context, const ExtParameters& extParams,
45 														   const char* name, const char* description)
46 	: DrawBuffersIndexedBase(context, extParams, name, description)
47 	, m_fbo(0)
48 {
49 	/* Left blank on purpose */
50 }
51 
prepareFramebuffer()52 void DrawBuffersIndexedColorMasks::prepareFramebuffer()
53 {
54 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
55 
56 	glw::GLint maxDrawBuffers = 0;
57 	gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
58 	if (maxDrawBuffers < 4)
59 	{
60 		throw tcu::ResourceError("Minimum number of draw buffers too low");
61 	}
62 
63 	gl.genFramebuffers(1, &m_fbo);
64 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
65 
66 	std::vector<glw::GLenum> bufs(maxDrawBuffers);
67 	for (int i = 0; i < maxDrawBuffers; ++i)
68 	{
69 		bufs[i] = GL_COLOR_ATTACHMENT0 + i;
70 	}
71 	gl.drawBuffers(maxDrawBuffers, &bufs[0]);
72 
73 	gl.disable(GL_DITHER);
74 }
75 
releaseFramebuffer()76 void DrawBuffersIndexedColorMasks::releaseFramebuffer()
77 {
78 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
79 
80 	glw::GLint maxDrawBuffers = 0;
81 	gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
82 	if (maxDrawBuffers < 4)
83 	{
84 		throw tcu::ResourceError("Minimum number of draw buffers too low");
85 	}
86 
87 	BlendMaskStateMachine state(m_context, m_testCtx.getLog(), maxDrawBuffers);
88 	state.SetDefaults();
89 	gl.deleteFramebuffers(1, &m_fbo);
90 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
91 	glw::GLenum bufs[1] = { GL_BACK };
92 	gl.drawBuffers(1, bufs);
93 	gl.readBuffer(GL_BACK);
94 }
95 
iterate()96 tcu::TestNode::IterateResult DrawBuffersIndexedColorMasks::iterate()
97 {
98 	static const glw::GLenum WriteMasksFormats[] = { GL_R8,		 GL_RG8,	 GL_RGB8,	 GL_RGB565,  GL_RGBA4,
99 													 GL_RGB5_A1, GL_RGBA8,   GL_R8I,	  GL_R8UI,	GL_R16I,
100 													 GL_R16UI,   GL_R32I,	GL_R32UI,	GL_RG8I,	GL_RG8UI,
101 													 GL_RG16I,   GL_RG16UI,  GL_RG32I,	GL_RG32UI,  GL_RGBA8I,
102 													 GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI };
103 	static const int	kSize	= 32;
104 	static unsigned int formatId = 0;
105 
106 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
107 	glw::GLenum			  format = WriteMasksFormats[formatId];
108 
109 	prepareFramebuffer();
110 
111 	// Check number of available draw buffers
112 	glw::GLint maxDrawBuffers = 0;
113 	gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
114 	if (maxDrawBuffers < 4)
115 	{
116 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Minimum number of draw buffers too low");
117 		return STOP;
118 	}
119 
120 	// Prepare render targets
121 	glw::GLuint tex;
122 	gl.genTextures(1, &tex);
123 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, tex);
124 	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, format, kSize, kSize, maxDrawBuffers);
125 	for (int i = 0; i < maxDrawBuffers; ++i)
126 	{
127 		gl.framebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, tex, 0, i);
128 	}
129 
130 	// Clear all buffers
131 	switch (ReadableType(format))
132 	{
133 	case GL_UNSIGNED_BYTE:
134 	{
135 		tcu::Vec4 c0(0.15f, 0.3f, 0.45f, 0.6f);
136 		for (int i = 0; i < maxDrawBuffers; ++i)
137 		{
138 			gl.clearBufferfv(GL_COLOR, i, &c0[0]);
139 		}
140 		break;
141 	}
142 	case GL_UNSIGNED_INT:
143 	{
144 		tcu::UVec4 c0(2, 3, 4, 5);
145 		for (int i = 0; i < maxDrawBuffers; ++i)
146 		{
147 			gl.clearBufferuiv(GL_COLOR, i, &c0[0]);
148 		}
149 		break;
150 	}
151 	case GL_INT:
152 	{
153 		tcu::IVec4 c0(2, 3, 4, 5);
154 		for (int i = 0; i < maxDrawBuffers; ++i)
155 		{
156 			gl.clearBufferiv(GL_COLOR, i, &c0[0]);
157 		}
158 		break;
159 	}
160 	}
161 
162 	// Set color masks for each buffer
163 	BlendMaskStateMachine state(m_context, m_testCtx.getLog(), maxDrawBuffers);
164 
165 	glw::GLboolean mask[] = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE };
166 	for (int i = 0; i < maxDrawBuffers; ++i)
167 	{
168 		mask[i % 4] = GL_TRUE;
169 		state.SetColorMaski(i, mask[0], mask[1], mask[2], mask[3]);
170 		mask[i % 4] = GL_FALSE;
171 	}
172 
173 	// Clear all buffers
174 	switch (ReadableType(format))
175 	{
176 	case GL_UNSIGNED_BYTE:
177 	{
178 		tcu::Vec4 c1(0.85f, 0.85f, 0.85f, 0.85f);
179 		for (int i = 0; i < maxDrawBuffers; ++i)
180 		{
181 			gl.clearBufferfv(GL_COLOR, i, &c1[0]);
182 		}
183 		break;
184 	}
185 	case GL_UNSIGNED_INT:
186 	{
187 		tcu::UVec4 c1(23, 23, 23, 23);
188 		for (int i = 0; i < maxDrawBuffers; ++i)
189 		{
190 			gl.clearBufferuiv(GL_COLOR, i, &c1[0]);
191 		}
192 		break;
193 	}
194 	case GL_INT:
195 	{
196 		tcu::IVec4 c1(23, 23, 23, 23);
197 		for (int i = 0; i < maxDrawBuffers; ++i)
198 		{
199 			gl.clearBufferiv(GL_COLOR, i, &c1[0]);
200 		}
201 		break;
202 	}
203 	}
204 
205 	// Verify color
206 	int		  numComponents = NumComponents(format);
207 	tcu::RGBA epsilon		= GetEpsilon();
208 	bool	  success		= true;
209 
210 	for (int i = 0; i < maxDrawBuffers; ++i)
211 	{
212 		gl.readBuffer(GL_COLOR_ATTACHMENT0 + i);
213 
214 		switch (ReadableType(format))
215 		{
216 		case GL_UNSIGNED_BYTE:
217 		{
218 			tcu::UVec4 e(static_cast<unsigned int>(0.15f * 255), static_cast<unsigned int>(0.30f * 255),
219 						 static_cast<unsigned int>(0.45f * 255), static_cast<unsigned int>(0.60f * 255));
220 			e[i % 4] = static_cast<unsigned int>(0.85f * 255);
221 			e		 = tcu::UVec4(e.x(), numComponents >= 2 ? e.y() : 0, numComponents >= 3 ? e.z() : 0,
222 						   numComponents == 4 ? e.w() : 255);
223 			tcu::RGBA expected(e.x(), e.y(), e.z(), e.w());
224 
225 			std::vector<unsigned char> rendered(kSize * kSize * 4, 45);
226 
227 			tcu::TextureLevel textureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
228 										   kSize, kSize);
229 			glu::readPixels(m_context.getRenderContext(), 0, 0, textureLevel.getAccess());
230 
231 			if (!VerifyImg(textureLevel, expected, epsilon))
232 			{
233 				m_testCtx.getLog() << tcu::TestLog::Message << "Write mask error in texture format " << format
234 								   << " occurred for buffer #" << i << "\n"
235 								   << tcu::TestLog::EndMessage;
236 				m_testCtx.getLog() << tcu::TestLog::Image("Result", "Rendered result image", textureLevel.getAccess());
237 				success = false;
238 			}
239 			break;
240 		}
241 		case GL_UNSIGNED_INT:
242 		{
243 			tcu::UVec4 e(2, 3, 4, 5);
244 			e[i % 4] = 23;
245 			e		 = tcu::UVec4(e.x(), numComponents >= 2 ? e.y() : 0, numComponents >= 3 ? e.z() : 0,
246 						   numComponents == 4 ? e.w() : 1);
247 			tcu::RGBA expected(e.x(), e.y(), e.z(), e.w());
248 
249 			tcu::TextureLevel textureLevel(
250 				tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32), kSize, kSize);
251 			glu::readPixels(m_context.getRenderContext(), 0, 0, textureLevel.getAccess());
252 
253 			if (!VerifyImg(textureLevel, expected, epsilon))
254 			{
255 				m_testCtx.getLog() << tcu::TestLog::Message << "Write mask error in texture format " << format
256 								   << " occurred for buffer #" << i << "\n"
257 								   << tcu::TestLog::EndMessage;
258 				m_testCtx.getLog() << tcu::TestLog::Image("Result", "Rendered result image", textureLevel.getAccess());
259 				success = false;
260 			}
261 			break;
262 		}
263 		case GL_INT:
264 		{
265 			tcu::UVec4 e(2, 3, 4, 5);
266 			e[i % 4] = 23;
267 			e		 = tcu::UVec4(e.x(), numComponents >= 2 ? e.y() : 0, numComponents >= 3 ? e.z() : 0,
268 						   numComponents == 4 ? e.w() : 1);
269 			tcu::RGBA expected(e.x(), e.y(), e.z(), e.w());
270 
271 			tcu::TextureLevel textureLevel(
272 				tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32), kSize, kSize);
273 			glu::readPixels(m_context.getRenderContext(), 0, 0, textureLevel.getAccess());
274 
275 			if (!VerifyImg(textureLevel, expected, epsilon))
276 			{
277 				m_testCtx.getLog() << tcu::TestLog::Message << "Write mask error in texture format " << format
278 								   << " occurred for buffer #" << i << "\n"
279 								   << tcu::TestLog::EndMessage;
280 				m_testCtx.getLog() << tcu::TestLog::Image("Result", "Rendered result image", textureLevel.getAccess());
281 				success = false;
282 			}
283 			break;
284 		}
285 		}
286 	}
287 
288 	gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
289 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
290 	gl.deleteTextures(1, &tex);
291 	releaseFramebuffer();
292 
293 	// Check for error
294 	glw::GLenum error_code = gl.getError();
295 	if (error_code != GL_NO_ERROR)
296 	{
297 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Some functions generated error");
298 		formatId = 0;
299 		return STOP;
300 	}
301 
302 	if (!success)
303 	{
304 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Write mask error occurred");
305 		formatId = 0;
306 		return STOP;
307 	}
308 	else
309 	{
310 		++formatId;
311 		if (formatId < (sizeof(WriteMasksFormats) / sizeof(WriteMasksFormats[0])))
312 		{
313 			return CONTINUE;
314 		}
315 		else
316 		{
317 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
318 			formatId = 0;
319 			return STOP;
320 		}
321 	}
322 }
323 
NumComponents(glw::GLenum format)324 unsigned int DrawBuffersIndexedColorMasks::NumComponents(glw::GLenum format)
325 {
326 	switch (format)
327 	{
328 	case GL_R8:
329 	case GL_R8I:
330 	case GL_R8UI:
331 	case GL_R16I:
332 	case GL_R16UI:
333 	case GL_R32I:
334 	case GL_R32UI:
335 		return 1;
336 	case GL_RG8:
337 	case GL_RG8I:
338 	case GL_RG8UI:
339 	case GL_RG16I:
340 	case GL_RG16UI:
341 	case GL_RG32I:
342 	case GL_RG32UI:
343 		return 2;
344 	case GL_RGB8:
345 	case GL_RGB565:
346 		return 3;
347 	case GL_RGBA4:
348 	case GL_RGB5_A1:
349 	case GL_RGBA8:
350 	case GL_RGB10_A2:
351 	case GL_RGBA8I:
352 	case GL_RGBA8UI:
353 	case GL_RGBA16I:
354 	case GL_RGBA16UI:
355 	case GL_RGBA32I:
356 	case GL_RGBA32UI:
357 		return 4;
358 	default:
359 		return 0;
360 	}
361 }
362 
ReadableType(glw::GLenum format)363 glw::GLenum DrawBuffersIndexedColorMasks::ReadableType(glw::GLenum format)
364 {
365 	switch (format)
366 	{
367 	case GL_R8:
368 	case GL_RG8:
369 	case GL_RGB8:
370 	case GL_RGB565:
371 	case GL_RGBA4:
372 	case GL_RGB5_A1:
373 	case GL_RGBA8:
374 	case GL_RGB10_A2:
375 		return GL_UNSIGNED_BYTE;
376 
377 	case GL_R8I:
378 	case GL_R16I:
379 	case GL_R32I:
380 	case GL_RG8I:
381 	case GL_RG16I:
382 	case GL_RG32I:
383 	case GL_RGBA8I:
384 	case GL_RGBA16I:
385 	case GL_RGBA32I:
386 		return GL_INT;
387 
388 	case GL_R8UI:
389 	case GL_R16UI:
390 	case GL_R32UI:
391 	case GL_RG8UI:
392 	case GL_RG16UI:
393 	case GL_RG32UI:
394 	case GL_RGB10_A2UI:
395 	case GL_RGBA8UI:
396 	case GL_RGBA16UI:
397 	case GL_RGBA32UI:
398 		return GL_UNSIGNED_INT;
399 
400 	default:
401 		return 0;
402 	}
403 }
404 
GetEpsilon()405 tcu::RGBA DrawBuffersIndexedColorMasks::GetEpsilon()
406 {
407 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
408 
409 	tcu::IVec4 bits;
410 	tcu::UVec4 epsilon;
411 
412 	for (int i = 0; i < 4; ++i)
413 	{
414 		gl.getIntegerv(GL_RED_BITS + i, &bits[i]);
415 		epsilon[i] = de::min(
416 			255u, static_cast<unsigned int>(ceil(1.0 + 255.0 * (1.0 / pow(2.0, static_cast<double>(bits[i]))))));
417 	}
418 
419 	return tcu::RGBA(epsilon.x(), epsilon.y(), epsilon.z(), epsilon.w());
420 }
421 
VerifyImg(const tcu::TextureLevel & textureLevel,tcu::RGBA expectedColor,tcu::RGBA epsilon)422 bool DrawBuffersIndexedColorMasks::VerifyImg(const tcu::TextureLevel& textureLevel, tcu::RGBA expectedColor,
423 											 tcu::RGBA epsilon)
424 {
425 	for (int y = 0; y < textureLevel.getHeight(); ++y)
426 	{
427 		for (int x = 0; x < textureLevel.getWidth(); ++x)
428 		{
429 			tcu::IVec4 color(textureLevel.getAccess().getPixelInt(x, y));
430 			tcu::RGBA  pixel(color.x(), color.y(), color.z(), color.w());
431 
432 			if (!tcu::compareThreshold(pixel, expectedColor, epsilon))
433 			{
434 				m_testCtx.getLog() << tcu::TestLog::Message << "Expected value: " << expectedColor << "\n"
435 								   << "Read value:     " << pixel << "\n"
436 								   << "Epsilon:        " << epsilon << tcu::TestLog::EndMessage;
437 				return false;
438 			}
439 		}
440 	}
441 	return true;
442 }
443 
444 } // namespace glcts
445