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