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 FBO colorbuffer tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fFboColorbufferTests.hpp"
     25 #include "es31fFboTestCase.hpp"
     26 #include "es31fFboTestUtil.hpp"
     27 
     28 #include "gluTextureUtil.hpp"
     29 #include "gluContextInfo.hpp"
     30 
     31 #include "tcuCommandLine.hpp"
     32 #include "tcuImageCompare.hpp"
     33 #include "tcuRGBA.hpp"
     34 #include "tcuTestLog.hpp"
     35 #include "tcuTextureUtil.hpp"
     36 
     37 #include "sglrContextUtil.hpp"
     38 
     39 #include "deRandom.hpp"
     40 #include "deString.h"
     41 
     42 #include "glwEnums.hpp"
     43 
     44 namespace deqp
     45 {
     46 namespace gles31
     47 {
     48 namespace Functional
     49 {
     50 
     51 using std::string;
     52 using tcu::Vec2;
     53 using tcu::Vec3;
     54 using tcu::Vec4;
     55 using tcu::IVec2;
     56 using tcu::IVec3;
     57 using tcu::IVec4;
     58 using tcu::UVec4;
     59 using tcu::TestLog;
     60 using namespace FboTestUtil;
     61 
     62 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
     63 
     64 static tcu::Vec4 generateRandomColor (de::Random& random)
     65 {
     66 	tcu::Vec4 retVal;
     67 
     68 	retVal[0] = random.getFloat();
     69 	retVal[1] = random.getFloat();
     70 	retVal[2] = random.getFloat();
     71 	retVal[3] = 1.0f;
     72 
     73 	return retVal;
     74 }
     75 
     76 static tcu::CubeFace getCubeFaceFromNdx (int ndx)
     77 {
     78 	switch (ndx)
     79 	{
     80 		case 0:	return tcu::CUBEFACE_POSITIVE_X;
     81 		case 1:	return tcu::CUBEFACE_NEGATIVE_X;
     82 		case 2:	return tcu::CUBEFACE_POSITIVE_Y;
     83 		case 3:	return tcu::CUBEFACE_NEGATIVE_Y;
     84 		case 4:	return tcu::CUBEFACE_POSITIVE_Z;
     85 		case 5:	return tcu::CUBEFACE_NEGATIVE_Z;
     86 		default:
     87 			DE_ASSERT(false);
     88 			return tcu::CUBEFACE_LAST;
     89 	}
     90 }
     91 
     92 class FboColorbufferCase : public FboTestCase
     93 {
     94 public:
     95 	FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
     96 		: FboTestCase	(context, name, desc)
     97 		, m_format		(format)
     98 	{
     99 	}
    100 
    101 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
    102 	{
    103 		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
    104 
    105 		m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
    106 
    107 		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
    108 	}
    109 
    110 protected:
    111 	const deUint32	m_format;
    112 };
    113 
    114 class FboColorTexCubeArrayCase : public FboColorbufferCase
    115 {
    116 public:
    117 	FboColorTexCubeArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
    118 		: FboColorbufferCase	(context, name, description, texFmt)
    119 		, m_texSize				(texSize)
    120 	{
    121 		DE_ASSERT(texSize.z() % 6 == 0);
    122 	}
    123 
    124 protected:
    125 	void preCheck (void)
    126 	{
    127 		if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"))
    128 			TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_texture_cube_map_array or a context version equal or higher than 3.2");
    129 
    130 		checkFormatSupport(m_format);
    131 	}
    132 
    133 	void render (tcu::Surface& dst)
    134 	{
    135 		TestLog&				log					= m_testCtx.getLog();
    136 		de::Random				rnd					(deStringHash(getName()) ^ 0xed607a89 ^ m_testCtx.getCommandLine().getBaseSeed());
    137 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
    138 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
    139 
    140 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
    141 		TextureCubeArrayShader	arrayTexShader		(glu::getSamplerCubeArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
    142 
    143 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
    144 		deUint32				arrayTexShaderID	= getCurrentContext()->createProgram(&arrayTexShader);
    145 
    146 		// Setup textures
    147 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
    148 		arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
    149 
    150 		// Framebuffers.
    151 		std::vector<deUint32>	fbos;
    152 		deUint32				tex;
    153 
    154 		{
    155 			glu::TransferFormat	transferFmt		= glu::getTransferFormat(texFmt);
    156 			bool				isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
    157 			const IVec3&		size			= m_texSize;
    158 
    159 			log << TestLog::Message
    160 				<< "Creating a cube map array texture ("
    161 				<< size.x() << "x" << size.y()
    162 				<< ", depth: "
    163 				<< size.z() << ")"
    164 				<< TestLog::EndMessage;
    165 
    166 			glGenTextures(1, &tex);
    167 
    168 			glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
    169 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    170 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    171 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
    172 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    173 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    174 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    175 
    176 			log << TestLog::Message << "Creating a framebuffer object for each layer-face" << TestLog::EndMessage;
    177 
    178 			// Generate an FBO for each layer-face
    179 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
    180 			{
    181 				deUint32 layerFbo;
    182 
    183 				glGenFramebuffers(1, &layerFbo);
    184 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
    185 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
    186 				checkError();
    187 				checkFramebufferStatus(GL_FRAMEBUFFER);
    188 
    189 				fbos.push_back(layerFbo);
    190 			}
    191 		}
    192 
    193 		log << TestLog::Message << "Rendering test images to layer-faces in randomized order" << TestLog::EndMessage;
    194 
    195 		{
    196 			std::vector<int> order(fbos.size());
    197 
    198 			for (size_t n = 0; n < order.size(); n++)
    199 				order[n] = (int)n;
    200 			rnd.shuffle(order.begin(), order.end());
    201 
    202 			for (size_t ndx = 0; ndx < order.size(); ndx++)
    203 			{
    204 				const int			layerFace	= order[ndx];
    205 				const deUint32		format		= GL_RGBA;
    206 				const deUint32		dataType	= GL_UNSIGNED_BYTE;
    207 				const int			texW		= 128;
    208 				const int			texH		= 128;
    209 				deUint32			tmpTex		= 0;
    210 				const deUint32		fbo			= fbos[layerFace];
    211 				const IVec3&		viewport	= m_texSize;
    212 				tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    213 
    214 				tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
    215 
    216 				glGenTextures(1, &tmpTex);
    217 				glBindTexture(GL_TEXTURE_2D, tmpTex);
    218 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    219 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    220 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
    221 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
    222 				glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    223 
    224 				glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    225 				glViewport(0, 0, viewport.x(), viewport.y());
    226 				sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    227 				checkError();
    228 
    229 				// Render to framebuffer
    230 				{
    231 					const Vec3			p0		= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
    232 					const Vec3			p1		= p0 + Vec3(1.0f, 1.0f, 0.0f);
    233 					const int			layer	= layerFace / 6;
    234 					const tcu::CubeFace	face	= getCubeFaceFromNdx(layerFace % 6);
    235 
    236 					glBindFramebuffer(GL_FRAMEBUFFER, 0);
    237 					glViewport(0, 0, getWidth(), getHeight());
    238 
    239 					glActiveTexture(GL_TEXTURE0);
    240 					glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
    241 
    242 					arrayTexShader.setLayer(layer);
    243 					arrayTexShader.setFace(face);
    244 					arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
    245 
    246 					sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
    247 					checkError();
    248 				}
    249 			}
    250 		}
    251 
    252 		readPixels(dst, 0, 0, getWidth(), getHeight());
    253 	}
    254 
    255 private:
    256 	IVec3 m_texSize;
    257 };
    258 
    259 FboColorTests::FboColorTests (Context& context)
    260 	: TestCaseGroup(context, "color", "Colorbuffer tests")
    261 {
    262 }
    263 
    264 FboColorTests::~FboColorTests (void)
    265 {
    266 }
    267 
    268 void FboColorTests::init (void)
    269 {
    270 	static const deUint32 colorFormats[] =
    271 	{
    272 		// RGBA formats
    273 		GL_RGBA32I,
    274 		GL_RGBA32UI,
    275 		GL_RGBA16I,
    276 		GL_RGBA16UI,
    277 		GL_RGBA8,
    278 		GL_RGBA8I,
    279 		GL_RGBA8UI,
    280 		GL_SRGB8_ALPHA8,
    281 		GL_RGB10_A2,
    282 		GL_RGB10_A2UI,
    283 		GL_RGBA4,
    284 		GL_RGB5_A1,
    285 
    286 		// RGB formats
    287 		GL_RGB8,
    288 		GL_RGB565,
    289 
    290 		// RG formats
    291 		GL_RG32I,
    292 		GL_RG32UI,
    293 		GL_RG16I,
    294 		GL_RG16UI,
    295 		GL_RG8,
    296 		GL_RG8I,
    297 		GL_RG8UI,
    298 
    299 		// R formats
    300 		GL_R32I,
    301 		GL_R32UI,
    302 		GL_R16I,
    303 		GL_R16UI,
    304 		GL_R8,
    305 		GL_R8I,
    306 		GL_R8UI,
    307 
    308 		// GL_EXT_color_buffer_float
    309 		GL_RGBA32F,
    310 		GL_RGBA16F,
    311 		GL_R11F_G11F_B10F,
    312 		GL_RG32F,
    313 		GL_RG16F,
    314 		GL_R32F,
    315 		GL_R16F,
    316 
    317 		// GL_EXT_color_buffer_half_float
    318 		GL_RGB16F
    319 	};
    320 
    321 	// .texcubearray
    322 	{
    323 		tcu::TestCaseGroup* texCubeArrayGroup = new tcu::TestCaseGroup(m_testCtx, "texcubearray", "Cube map array texture tests");
    324 		addChild(texCubeArrayGroup);
    325 
    326 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    327 			texCubeArrayGroup->addChild(new FboColorTexCubeArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
    328 																	 colorFormats[fmtNdx], IVec3(128, 128, 12)));
    329 	}
    330 }
    331 
    332 } // Functional
    333 } // gles31
    334 } // deqp
    335