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