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 44namespace deqp 45{ 46namespace gles31 47{ 48namespace Functional 49{ 50 51using std::string; 52using tcu::Vec2; 53using tcu::Vec3; 54using tcu::Vec4; 55using tcu::IVec2; 56using tcu::IVec3; 57using tcu::IVec4; 58using tcu::UVec4; 59using tcu::TestLog; 60using namespace FboTestUtil; 61 62const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12); 63 64static 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 76static 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 92class FboColorbufferCase : public FboTestCase 93{ 94public: 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 110protected: 111 const deUint32 m_format; 112}; 113 114class FboColorTexCubeArrayCase : public FboColorbufferCase 115{ 116public: 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 124protected: 125 void preCheck (void) 126 { 127 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array")) 128 throw tcu::NotSupportedError("GL_EXT_texture_cube_map_array not supported"); 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 255private: 256 IVec3 m_texSize; 257}; 258 259FboColorTests::FboColorTests (Context& context) 260 : TestCaseGroup(context, "color", "Colorbuffer tests") 261{ 262} 263 264FboColorTests::~FboColorTests (void) 265{ 266} 267 268void 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