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