Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 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 Base class for FBO tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fFboTestCase.hpp"
     25 #include "es31fFboTestUtil.hpp"
     26 #include "tcuTestLog.hpp"
     27 #include "tcuImageCompare.hpp"
     28 #include "tcuRenderTarget.hpp"
     29 #include "sglrGLContext.hpp"
     30 #include "sglrReferenceContext.hpp"
     31 #include "gluStrUtil.hpp"
     32 #include "gluContextInfo.hpp"
     33 #include "deRandom.hpp"
     34 #include "glwEnums.hpp"
     35 #include "glwFunctions.hpp"
     36 
     37 #include <algorithm>
     38 
     39 namespace deqp
     40 {
     41 namespace gles31
     42 {
     43 namespace Functional
     44 {
     45 
     46 using tcu::TestLog;
     47 using std::string;
     48 
     49 FboTestCase::FboTestCase (Context& context, const char* name, const char* description, bool useScreenSizedViewport)
     50 	: TestCase			(context, name, description)
     51 	, m_viewportWidth	(useScreenSizedViewport ? context.getRenderTarget().getWidth() : 128)
     52 	, m_viewportHeight	(useScreenSizedViewport ? context.getRenderTarget().getHeight() : 128)
     53 {
     54 }
     55 
     56 FboTestCase::~FboTestCase (void)
     57 {
     58 }
     59 
     60 FboTestCase::IterateResult FboTestCase::iterate (void)
     61 {
     62 	glu::RenderContext&			renderCtx		= TestCase::m_context.getRenderContext();
     63 	const tcu::RenderTarget&	renderTarget	= renderCtx.getRenderTarget();
     64 	TestLog&					log				= m_testCtx.getLog();
     65 
     66 	// Viewport.
     67 	de::Random					rnd				(deStringHash(getName()));
     68 	int							width			= deMin32(renderTarget.getWidth(),	m_viewportWidth);
     69 	int							height			= deMin32(renderTarget.getHeight(),	m_viewportHeight);
     70 	int							x				= rnd.getInt(0, renderTarget.getWidth()		- width);
     71 	int							y				= rnd.getInt(0, renderTarget.getHeight()	- height);
     72 
     73 	// Surface format and storage is choosen by render().
     74 	tcu::Surface				reference;
     75 	tcu::Surface				result;
     76 
     77 	// Call preCheck() that can throw exception if some requirement is not met.
     78 	preCheck();
     79 
     80 	log << TestLog::Message << "Rendering with GL driver" << TestLog::EndMessage;
     81 
     82 	// Render using GLES3.1
     83 	try
     84 	{
     85 		sglr::GLContext context(renderCtx, log, 0, tcu::IVec4(x, y, width, height));
     86 		setContext(&context);
     87 		render(result);
     88 
     89 		// Check error.
     90 		deUint32 err = glGetError();
     91 		if (err != GL_NO_ERROR)
     92 			throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), DE_NULL, __FILE__, __LINE__);
     93 
     94 		setContext(DE_NULL);
     95 	}
     96 	catch (const FboTestUtil::FboIncompleteException& e)
     97 	{
     98 		if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
     99 		{
    100 			log << e;
    101 			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
    102 			return STOP;
    103 		}
    104 		else
    105 			throw;
    106 	}
    107 
    108 	log << TestLog::Message << "Rendering reference image" << TestLog::EndMessage;
    109 
    110 	// Render reference.
    111 	{
    112 		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
    113 		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
    114 
    115 		setContext(&context);
    116 		render(reference);
    117 		setContext(DE_NULL);
    118 	}
    119 
    120 	bool isOk = compare(reference, result);
    121 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
    122 							isOk ? "Pass"				: "Image comparison failed");
    123 	return STOP;
    124 }
    125 
    126 bool FboTestCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
    127 {
    128 	return tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, 0.05f, tcu::COMPARE_LOG_RESULT);
    129 }
    130 
    131 void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height, const tcu::TextureFormat& format, const tcu::Vec4& scale, const tcu::Vec4& bias)
    132 {
    133 	FboTestUtil::readPixels(*getCurrentContext(), dst, x, y, width, height, format, scale, bias);
    134 }
    135 
    136 void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height)
    137 {
    138 	getCurrentContext()->readPixels(dst, x, y, width, height);
    139 }
    140 
    141 void FboTestCase::checkFramebufferStatus (deUint32 target)
    142 {
    143 	deUint32 status = glCheckFramebufferStatus(target);
    144 	if (status != GL_FRAMEBUFFER_COMPLETE)
    145 		throw FboTestUtil::FboIncompleteException(status, __FILE__, __LINE__);
    146 }
    147 
    148 void FboTestCase::checkError (void)
    149 {
    150 	deUint32 err = glGetError();
    151 	if (err != GL_NO_ERROR)
    152 		throw glu::Error((int)err, (string("Got ") + glu::getErrorStr(err).toString()).c_str(), DE_NULL, __FILE__, __LINE__);
    153 }
    154 
    155 static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext)
    156 {
    157 	const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
    158 	switch (format)
    159 	{
    160 		// Color-renderable formats
    161 		case GL_RGBA32I:
    162 		case GL_RGBA32UI:
    163 		case GL_RGBA16I:
    164 		case GL_RGBA16UI:
    165 		case GL_RGBA8:
    166 		case GL_RGBA8I:
    167 		case GL_RGBA8UI:
    168 		case GL_SRGB8_ALPHA8:
    169 		case GL_RGB10_A2:
    170 		case GL_RGB10_A2UI:
    171 		case GL_RGBA4:
    172 		case GL_RGB5_A1:
    173 		case GL_RGB8:
    174 		case GL_RGB565:
    175 		case GL_RG32I:
    176 		case GL_RG32UI:
    177 		case GL_RG16I:
    178 		case GL_RG16UI:
    179 		case GL_RG8:
    180 		case GL_RG8I:
    181 		case GL_RG8UI:
    182 		case GL_R32I:
    183 		case GL_R32UI:
    184 		case GL_R16I:
    185 		case GL_R16UI:
    186 		case GL_R8:
    187 		case GL_R8I:
    188 		case GL_R8UI:
    189 			return true;
    190 
    191 		// Depth formats
    192 		case GL_DEPTH_COMPONENT32F:
    193 		case GL_DEPTH_COMPONENT24:
    194 		case GL_DEPTH_COMPONENT16:
    195 			return true;
    196 
    197 		// Depth+stencil formats
    198 		case GL_DEPTH32F_STENCIL8:
    199 		case GL_DEPTH24_STENCIL8:
    200 			return true;
    201 
    202 		// Stencil formats
    203 		case GL_STENCIL_INDEX8:
    204 			return true;
    205 
    206 		// Float format
    207 		case GL_RGBA32F:
    208 		case GL_RGB32F:
    209 		case GL_R11F_G11F_B10F:
    210 		case GL_RG32F:
    211 		case GL_R32F:
    212 			return isES32;
    213 
    214 
    215 		default:
    216 			return false;
    217 	}
    218 }
    219 
    220 static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext)
    221 {
    222 	const bool					isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
    223 	std::vector<std::string>	out;
    224 
    225 	DE_ASSERT(!isRequiredFormat(format, renderContext));
    226 
    227 	switch (format)
    228 	{
    229 		case GL_RGB16F:
    230 			out.push_back("GL_EXT_color_buffer_half_float");
    231 			break;
    232 
    233 		case GL_RGBA16F:
    234 		case GL_RG16F:
    235 		case GL_R16F:
    236 			out.push_back("GL_EXT_color_buffer_half_float");
    237 
    238 		case GL_RGBA32F:
    239 		case GL_RGB32F:
    240 		case GL_R11F_G11F_B10F:
    241 		case GL_RG32F:
    242 		case GL_R32F:
    243 			if (!isES32)
    244 				out.push_back("GL_EXT_color_buffer_float");
    245 			break;
    246 
    247 		default:
    248 			break;
    249 	}
    250 
    251 	return out;
    252 }
    253 
    254 static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts)
    255 {
    256 	for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
    257 	{
    258 		const std::string& extension = *iter;
    259 
    260 		if (context.getContextInfo().isExtensionSupported(extension.c_str()))
    261 			return true;
    262 	}
    263 
    264 	return false;
    265 }
    266 
    267 void FboTestCase::checkFormatSupport (deUint32 sizedFormat)
    268 {
    269 	const bool						isCoreFormat	= isRequiredFormat(sizedFormat, m_context.getRenderContext());
    270 	const std::vector<std::string>	requiredExts	= (!isCoreFormat) ? getEnablingExtensions(sizedFormat, m_context.getRenderContext()) : std::vector<std::string>();
    271 
    272 	// Check that we don't try to use invalid formats.
    273 	DE_ASSERT(isCoreFormat || !requiredExts.empty());
    274 
    275 	if (!requiredExts.empty() && !isAnyExtensionSupported(m_context, requiredExts))
    276 		throw tcu::NotSupportedError("Format not supported");
    277 }
    278 
    279 static int getMinimumSampleCount (deUint32 format)
    280 {
    281 	switch (format)
    282 	{
    283 		// Core formats
    284 		case GL_RGBA32I:
    285 		case GL_RGBA32UI:
    286 		case GL_RGBA16I:
    287 		case GL_RGBA16UI:
    288 		case GL_RGBA8:
    289 		case GL_RGBA8I:
    290 		case GL_RGBA8UI:
    291 		case GL_SRGB8_ALPHA8:
    292 		case GL_RGB10_A2:
    293 		case GL_RGB10_A2UI:
    294 		case GL_RGBA4:
    295 		case GL_RGB5_A1:
    296 		case GL_RGB8:
    297 		case GL_RGB565:
    298 		case GL_RG32I:
    299 		case GL_RG32UI:
    300 		case GL_RG16I:
    301 		case GL_RG16UI:
    302 		case GL_RG8:
    303 		case GL_RG8I:
    304 		case GL_RG8UI:
    305 		case GL_R32I:
    306 		case GL_R32UI:
    307 		case GL_R16I:
    308 		case GL_R16UI:
    309 		case GL_R8:
    310 		case GL_R8I:
    311 		case GL_R8UI:
    312 		case GL_DEPTH_COMPONENT32F:
    313 		case GL_DEPTH_COMPONENT24:
    314 		case GL_DEPTH_COMPONENT16:
    315 		case GL_DEPTH32F_STENCIL8:
    316 		case GL_DEPTH24_STENCIL8:
    317 		case GL_STENCIL_INDEX8:
    318 			return 4;
    319 
    320 		// GL_EXT_color_buffer_float
    321 		case GL_R11F_G11F_B10F:
    322 		case GL_RG16F:
    323 		case GL_R16F:
    324 			return 4;
    325 
    326 		case GL_RGBA32F:
    327 		case GL_RGBA16F:
    328 		case GL_RG32F:
    329 		case GL_R32F:
    330 			return 0;
    331 
    332 		// GL_EXT_color_buffer_half_float
    333 		case GL_RGB16F:
    334 			return 0;
    335 
    336 		default:
    337 			DE_FATAL("Unknown format");
    338 			return 0;
    339 	}
    340 }
    341 
    342 static std::vector<int> querySampleCounts (const glw::Functions& gl, deUint32 format)
    343 {
    344 	int					numSampleCounts		= 0;
    345 	std::vector<int>	sampleCounts;
    346 
    347 	gl.getInternalformativ(GL_RENDERBUFFER, format, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts);
    348 
    349 	if (numSampleCounts > 0)
    350 	{
    351 		sampleCounts.resize(numSampleCounts);
    352 		gl.getInternalformativ(GL_RENDERBUFFER, format, GL_SAMPLES, (glw::GLsizei)sampleCounts.size(), &sampleCounts[0]);
    353 	}
    354 
    355 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query sample counts for format");
    356 
    357 	return sampleCounts;
    358 }
    359 
    360 void FboTestCase::checkSampleCount (deUint32 sizedFormat, int numSamples)
    361 {
    362 	const int minSampleCount = getMinimumSampleCount(sizedFormat);
    363 
    364 	if (numSamples > minSampleCount)
    365 	{
    366 		// Exceeds spec-mandated minimum - need to check.
    367 		const std::vector<int> supportedSampleCounts = querySampleCounts(m_context.getRenderContext().getFunctions(), sizedFormat);
    368 
    369 		if (std::find(supportedSampleCounts.begin(), supportedSampleCounts.end(), numSamples) == supportedSampleCounts.end())
    370 			throw tcu::NotSupportedError("Sample count not supported");
    371 	}
    372 }
    373 
    374 void FboTestCase::clearColorBuffer (const tcu::TextureFormat& format, const tcu::Vec4& value)
    375 {
    376 	FboTestUtil::clearColorBuffer(*getCurrentContext(), format, value);
    377 }
    378 
    379 } // Functional
    380 } // gles31
    381 } // deqp
    382