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 Stencil texturing tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es31fStencilTexturingTests.hpp" 25 26#include "gluStrUtil.hpp" 27#include "gluObjectWrapper.hpp" 28#include "gluRenderContext.hpp" 29#include "gluShaderProgram.hpp" 30#include "gluDrawUtil.hpp" 31#include "gluPixelTransfer.hpp" 32#include "gluTextureUtil.hpp" 33#include "gluContextInfo.hpp" 34 35#include "glsTextureTestUtil.hpp" 36 37#include "tcuVector.hpp" 38#include "tcuTexture.hpp" 39#include "tcuTextureUtil.hpp" 40#include "tcuTestLog.hpp" 41#include "tcuTexLookupVerifier.hpp" 42 43#include "glwFunctions.hpp" 44#include "glwEnums.hpp" 45 46#include "deStringUtil.hpp" 47 48namespace deqp 49{ 50namespace gles31 51{ 52namespace Functional 53{ 54 55using std::vector; 56using std::string; 57using tcu::IVec4; 58using tcu::Vec2; 59using tcu::Vec4; 60using tcu::TestLog; 61using tcu::TextureLevel; 62using tcu::TextureFormat; 63 64namespace 65{ 66 67static void genTestRects (vector<IVec4>& rects, int width, int height) 68{ 69 int curWidth = width; 70 int curHeight = height; 71 int ndx = 0; 72 73 for (;;) 74 { 75 rects.push_back(IVec4(width-curWidth, height-curHeight, curWidth, curHeight)); 76 77 DE_ASSERT(curWidth >= 1 && curHeight >= 1); 78 if (curWidth == 1 && curHeight == 1) 79 break; 80 else if (curHeight > 1 && ((ndx%2) == 0 || curWidth == 1)) 81 curHeight -= 1; 82 else 83 curWidth -= 1; 84 85 ndx += 1; 86 } 87} 88 89static void rectsToTriangles (const vector<IVec4>& rects, int width, int height, vector<Vec2>& positions, vector<deUint16>& indices) 90{ 91 const float w = float(width); 92 const float h = float(height); 93 94 positions.resize(rects.size()*4); 95 indices.resize(rects.size()*6); 96 97 for (int rectNdx = 0; rectNdx < (int)rects.size(); rectNdx++) 98 { 99 const int rx = rects[rectNdx].x(); 100 const int ry = rects[rectNdx].y(); 101 const int rw = rects[rectNdx].z(); 102 const int rh = rects[rectNdx].w(); 103 104 const float x0 = float(rx*2)/w - 1.0f; 105 const float x1 = float((rx+rw)*2)/w - 1.0f; 106 const float y0 = float(ry*2)/h - 1.0f; 107 const float y1 = float((ry+rh)*2)/h - 1.0f; 108 109 positions[rectNdx*4 + 0] = Vec2(x0, y0); 110 positions[rectNdx*4 + 1] = Vec2(x1, y0); 111 positions[rectNdx*4 + 2] = Vec2(x0, y1); 112 positions[rectNdx*4 + 3] = Vec2(x1, y1); 113 114 indices[rectNdx*6 + 0] = (deUint16)(rectNdx*4 + 0); 115 indices[rectNdx*6 + 1] = (deUint16)(rectNdx*4 + 1); 116 indices[rectNdx*6 + 2] = (deUint16)(rectNdx*4 + 2); 117 indices[rectNdx*6 + 3] = (deUint16)(rectNdx*4 + 2); 118 indices[rectNdx*6 + 4] = (deUint16)(rectNdx*4 + 1); 119 indices[rectNdx*6 + 5] = (deUint16)(rectNdx*4 + 3); 120 } 121} 122 123static void drawTestPattern (const glu::RenderContext& renderCtx, int width, int height) 124{ 125 const glu::ShaderProgram program(renderCtx, glu::ProgramSources() 126 << glu::VertexSource( 127 "#version 300 es\n" 128 "in highp vec4 a_position;\n" 129 "void main (void)\n" 130 "{\n" 131 " gl_Position = a_position;\n" 132 "}\n") 133 << glu::FragmentSource( 134 "#version 300 es\n" 135 "void main (void) {}\n")); 136 137 const glw::Functions& gl = renderCtx.getFunctions(); 138 vector<IVec4> rects; 139 vector<Vec2> positions; 140 vector<deUint16> indices; 141 142 if (!program.isOk()) 143 throw tcu::TestError("Compile failed"); 144 145 gl.useProgram (program.getProgram()); 146 gl.viewport (0, 0, width, height); 147 gl.clear (GL_STENCIL_BUFFER_BIT); 148 gl.enable (GL_STENCIL_TEST); 149 gl.stencilOp (GL_KEEP, GL_KEEP, GL_INCR_WRAP); 150 gl.stencilFunc (GL_ALWAYS, 0, ~0u); 151 GLU_EXPECT_NO_ERROR(gl.getError(), "State setup failed"); 152 153 genTestRects (rects, width, height); 154 rectsToTriangles(rects, width, height, positions, indices); 155 156 { 157 const glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 2, (int)positions.size(), 0, positions[0].getPtr()); 158 glu::draw(renderCtx, program.getProgram(), 1, &posBinding, glu::pr::Triangles((int)indices.size(), &indices[0])); 159 } 160 161 gl.disable(GL_STENCIL_TEST); 162} 163 164static void renderTestPatternReference (const tcu::PixelBufferAccess& dst) 165{ 166 const int stencilBits = tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilAccess(dst, tcu::Sampler::MODE_STENCIL).getFormat()).x(); 167 const deUint32 stencilMask = (1u<<stencilBits)-1u; 168 vector<IVec4> rects; 169 170 DE_ASSERT(dst.getFormat().order == TextureFormat::S || dst.getFormat().order == TextureFormat::DS); 171 172 // clear depth and stencil 173 if (dst.getFormat().order == TextureFormat::DS) 174 tcu::clearDepth(dst, 0.0f); 175 tcu::clearStencil(dst, 0u); 176 177 genTestRects(rects, dst.getWidth(), dst.getHeight()); 178 179 for (vector<IVec4>::const_iterator rectIter = rects.begin(); rectIter != rects.end(); ++rectIter) 180 { 181 const int x0 = rectIter->x(); 182 const int y0 = rectIter->y(); 183 const int x1 = x0+rectIter->z(); 184 const int y1 = y0+rectIter->w(); 185 186 for (int y = y0; y < y1; y++) 187 { 188 for (int x = x0; x < x1; x++) 189 { 190 const int oldVal = dst.getPixStencil(x, y); 191 const int newVal = (oldVal+1)&stencilMask; 192 193 dst.setPixStencil(newVal, x, y); 194 } 195 } 196 } 197} 198 199static void blitStencilToColor2D (const glu::RenderContext& renderCtx, deUint32 srcTex, int width, int height) 200{ 201 const glu::ShaderProgram program(renderCtx, glu::ProgramSources() 202 << glu::VertexSource( 203 "#version 300 es\n" 204 "in highp vec4 a_position;\n" 205 "in highp vec2 a_texCoord;\n" 206 "out highp vec2 v_texCoord;\n" 207 "void main (void)\n" 208 "{\n" 209 " gl_Position = a_position;\n" 210 " v_texCoord = a_texCoord;\n" 211 "}\n") 212 << glu::FragmentSource( 213 "#version 300 es\n" 214 "uniform highp usampler2D u_sampler;\n" 215 "in highp vec2 v_texCoord;\n" 216 "layout(location = 0) out highp uint o_stencil;\n" 217 "void main (void)\n" 218 "{\n" 219 " o_stencil = texture(u_sampler, v_texCoord).x;\n" 220 "}\n")); 221 222 const float positions[] = 223 { 224 -1.0f, -1.0f, 225 +1.0f, -1.0f, 226 -1.0f, +1.0f, 227 +1.0f, +1.0f 228 }; 229 const float texCoord[] = 230 { 231 0.0f, 0.0f, 232 1.0f, 0.0f, 233 0.0f, 1.0f, 234 1.0f, 1.0f 235 }; 236 const glu::VertexArrayBinding vertexArrays[] = 237 { 238 glu::va::Float("a_position", 2, 4, 0, &positions[0]), 239 glu::va::Float("a_texCoord", 2, 4, 0, &texCoord[0]) 240 }; 241 const deUint8 indices[] = { 0, 1, 2, 2, 1, 3 }; 242 243 const glw::Functions& gl = renderCtx.getFunctions(); 244 245 if (!program.isOk()) 246 throw tcu::TestError("Compile failed"); 247 248 gl.activeTexture(GL_TEXTURE0); 249 gl.bindTexture(GL_TEXTURE_2D, srcTex); 250 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 251 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 252 gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); 253 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture state setup failed"); 254 255 gl.useProgram(program.getProgram()); 256 gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_sampler"), 0); 257 GLU_EXPECT_NO_ERROR(gl.getError(), "Program setup failed"); 258 259 gl.viewport(0, 0, width, height); 260 glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 261 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 262} 263 264static void blitStencilToColor2DArray (const glu::RenderContext& renderCtx, deUint32 srcTex, int width, int height, int level) 265{ 266 const glu::ShaderProgram program(renderCtx, glu::ProgramSources() 267 << glu::VertexSource( 268 "#version 300 es\n" 269 "in highp vec4 a_position;\n" 270 "in highp vec3 a_texCoord;\n" 271 "out highp vec3 v_texCoord;\n" 272 "void main (void)\n" 273 "{\n" 274 " gl_Position = a_position;\n" 275 " v_texCoord = a_texCoord;\n" 276 "}\n") 277 << glu::FragmentSource( 278 "#version 300 es\n" 279 "uniform highp usampler2DArray u_sampler;\n" 280 "in highp vec3 v_texCoord;\n" 281 "layout(location = 0) out highp uint o_stencil;\n" 282 "void main (void)\n" 283 "{\n" 284 " o_stencil = texture(u_sampler, v_texCoord).x;\n" 285 "}\n")); 286 287 const float positions[] = 288 { 289 -1.0f, -1.0f, 290 +1.0f, -1.0f, 291 -1.0f, +1.0f, 292 +1.0f, +1.0f 293 }; 294 const float texCoord[] = 295 { 296 0.0f, 0.0f, float(level), 297 1.0f, 0.0f, float(level), 298 0.0f, 1.0f, float(level), 299 1.0f, 1.0f, float(level) 300 }; 301 const glu::VertexArrayBinding vertexArrays[] = 302 { 303 glu::va::Float("a_position", 2, 4, 0, &positions[0]), 304 glu::va::Float("a_texCoord", 3, 4, 0, &texCoord[0]) 305 }; 306 const deUint8 indices[] = { 0, 1, 2, 2, 1, 3 }; 307 308 const glw::Functions& gl = renderCtx.getFunctions(); 309 310 if (!program.isOk()) 311 throw tcu::TestError("Compile failed"); 312 313 gl.activeTexture(GL_TEXTURE0); 314 gl.bindTexture(GL_TEXTURE_2D_ARRAY, srcTex); 315 gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 316 gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 317 gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); 318 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture state setup failed"); 319 320 gl.useProgram(program.getProgram()); 321 gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_sampler"), 0); 322 GLU_EXPECT_NO_ERROR(gl.getError(), "Program setup failed"); 323 324 gl.viewport(0, 0, width, height); 325 glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 326 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 327} 328 329static void blitStencilToColorCube (const glu::RenderContext& renderCtx, deUint32 srcTex, const float* texCoord, int width, int height) 330{ 331 const glu::ShaderProgram program(renderCtx, glu::ProgramSources() 332 << glu::VertexSource( 333 "#version 300 es\n" 334 "in highp vec4 a_position;\n" 335 "in highp vec3 a_texCoord;\n" 336 "out highp vec3 v_texCoord;\n" 337 "void main (void)\n" 338 "{\n" 339 " gl_Position = a_position;\n" 340 " v_texCoord = a_texCoord;\n" 341 "}\n") 342 << glu::FragmentSource( 343 "#version 300 es\n" 344 "uniform highp usamplerCube u_sampler;\n" 345 "in highp vec3 v_texCoord;\n" 346 "layout(location = 0) out highp vec4 o_color;\n" 347 "void main (void)\n" 348 "{\n" 349 " o_color.x = float(texture(u_sampler, v_texCoord).x) / 255.0;\n" 350 " o_color.yzw = vec3(0.0, 0.0, 1.0);\n" 351 "}\n")); 352 353 const float positions[] = 354 { 355 -1.0f, -1.0f, 356 -1.0f, +1.0f, 357 +1.0f, -1.0f, 358 +1.0f, +1.0f 359 }; 360 const glu::VertexArrayBinding vertexArrays[] = 361 { 362 glu::va::Float("a_position", 2, 4, 0, &positions[0]), 363 glu::va::Float("a_texCoord", 3, 4, 0, texCoord) 364 }; 365 const deUint8 indices[] = { 0, 1, 2, 2, 1, 3 }; 366 367 const glw::Functions& gl = renderCtx.getFunctions(); 368 369 if (!program.isOk()) 370 throw tcu::TestError("Compile failed"); 371 372 gl.activeTexture(GL_TEXTURE0); 373 gl.bindTexture(GL_TEXTURE_CUBE_MAP, srcTex); 374 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 375 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 376 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); 377 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture state setup failed"); 378 379 gl.useProgram(program.getProgram()); 380 gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_sampler"), 0); 381 GLU_EXPECT_NO_ERROR(gl.getError(), "Program setup failed"); 382 383 gl.viewport(0, 0, width, height); 384 glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 385 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 386} 387 388static inline tcu::ConstPixelBufferAccess stencilToRedAccess (const tcu::ConstPixelBufferAccess& access) 389{ 390 DE_ASSERT(access.getFormat() == TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8)); 391 return tcu::ConstPixelBufferAccess(TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8), access.getSize(), access.getPitch(), access.getDataPtr()); 392} 393 394static bool compareStencilToRed (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& stencilRef, const tcu::ConstPixelBufferAccess& result) 395{ 396 const int maxPrints = 10; 397 int numFailed = 0; 398 399 DE_ASSERT(stencilRef.getFormat().order == TextureFormat::S); 400 DE_ASSERT(stencilRef.getWidth() == result.getWidth() && stencilRef.getHeight() == result.getHeight()); 401 402 for (int y = 0; y < stencilRef.getHeight(); y++) 403 { 404 for (int x = 0; x < stencilRef.getWidth(); x++) 405 { 406 const int ref = stencilRef.getPixStencil(x, y); 407 const int res = result.getPixelInt(x, y).x(); 408 409 if (ref != res) 410 { 411 if (numFailed < maxPrints) 412 log << TestLog::Message << "ERROR: Expected " << ref << ", got " << res << " at (" << x << ", " << y << ")" << TestLog::EndMessage; 413 else if (numFailed == maxPrints) 414 log << TestLog::Message << "..." << TestLog::EndMessage; 415 416 numFailed += 1; 417 } 418 } 419 } 420 421 log << TestLog::Message << "Found " << numFailed << " faulty pixels, comparison " << (numFailed == 0 ? "passed." : "FAILED!") << TestLog::EndMessage; 422 423 log << TestLog::ImageSet("ComparisonResult", "Image comparison result") 424 << TestLog::Image("Result", "Result stencil buffer", result); 425 426 if (numFailed > 0) 427 log << TestLog::Image("Reference", "Reference stencil buffer", stencilToRedAccess(stencilRef)); 428 429 log << TestLog::EndImageSet; 430 431 return numFailed == 0; 432} 433 434static bool compareRedChannel (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& result, int reference) 435{ 436 const int maxPrints = 10; 437 int numFailed = 0; 438 439 for (int y = 0; y < result.getHeight(); y++) 440 { 441 for (int x = 0; x < result.getWidth(); x++) 442 { 443 const int res = result.getPixelInt(x, y).x(); 444 445 if (reference != res) 446 { 447 if (numFailed < maxPrints) 448 log << TestLog::Message << "ERROR: Expected " << reference << ", got " << res << " at (" << x << ", " << y << ")" << TestLog::EndMessage; 449 else if (numFailed == maxPrints) 450 log << TestLog::Message << "..." << TestLog::EndMessage; 451 452 numFailed += 1; 453 } 454 } 455 } 456 457 log << TestLog::Message << "Found " << numFailed << " faulty pixels, comparison " << (numFailed == 0 ? "passed." : "FAILED!") << TestLog::EndMessage; 458 459 log << TestLog::ImageSet("ComparisonResult", "Image comparison result") 460 << TestLog::Image("Result", "Result stencil buffer", result); 461 462 log << TestLog::EndImageSet; 463 464 return numFailed == 0; 465} 466 467static void stencilToUnorm8 (const tcu::TextureCube& src, tcu::TextureCube& dst) 468{ 469 for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++) 470 { 471 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 472 { 473 const tcu::CubeFace face = tcu::CubeFace(faceNdx); 474 475 if (!src.isLevelEmpty(face, levelNdx)) 476 { 477 dst.allocLevel(face, levelNdx); 478 479 const tcu::ConstPixelBufferAccess srcLevel = src.getLevelFace(levelNdx, face); 480 const tcu::PixelBufferAccess dstLevel = dst.getLevelFace(levelNdx, face); 481 482 for (int y = 0; y < src.getSize(); y++) 483 for (int x = 0; x < src.getSize(); x++) 484 dstLevel.setPixel(Vec4(float(srcLevel.getPixStencil(x, y)) / 255.f, 0.f, 0.f, 1.f), x, y); 485 } 486 } 487 } 488} 489 490static void checkDepthStencilFormatSupport (Context& context, deUint32 format) 491{ 492 if (format == GL_STENCIL_INDEX8) 493 { 494 const char* reqExt = "GL_OES_texture_stencil8"; 495 glu::ContextType contextType = context.getRenderContext().getType(); 496 if (!glu::contextSupports(contextType, glu::ApiType::es(3, 2)) && 497 !glu::contextSupports(contextType, glu::ApiType::core(4, 5)) && 498 !context.getContextInfo().isExtensionSupported(reqExt)) 499 throw tcu::NotSupportedError(glu::getTextureFormatStr(format).toString() + " requires " + reqExt); 500 } 501 else 502 { 503 DE_ASSERT(format == GL_DEPTH32F_STENCIL8 || format == GL_DEPTH24_STENCIL8); 504 } 505} 506 507static void checkFramebufferStatus (const glw::Functions& gl) 508{ 509 const deUint32 status = gl.checkFramebufferStatus(GL_FRAMEBUFFER); 510 511 if (status == GL_FRAMEBUFFER_UNSUPPORTED) 512 throw tcu::NotSupportedError("Unsupported framebuffer configuration"); 513 else if (status != GL_FRAMEBUFFER_COMPLETE) 514 throw tcu::TestError("Incomplete framebuffer: " + glu::getFramebufferStatusStr(status).toString()); 515} 516 517class UploadTex2DCase : public TestCase 518{ 519public: 520 UploadTex2DCase (Context& context, const char* name, deUint32 format) 521 : TestCase (context, name, glu::getTextureFormatName(format)) 522 , m_format (format) 523 { 524 } 525 526 IterateResult iterate (void) 527 { 528 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 529 const glw::Functions& gl = renderCtx.getFunctions(); 530 const int width = 129; 531 const int height = 113; 532 glu::Framebuffer fbo (renderCtx); 533 glu::Renderbuffer colorBuf (renderCtx); 534 glu::Texture depthStencilTex (renderCtx); 535 TextureLevel uploadLevel (glu::mapGLInternalFormat(m_format), width, height); 536 TextureLevel readLevel (TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), width, height); 537 TextureLevel stencilOnlyLevel (TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), width, height); 538 539 checkDepthStencilFormatSupport(m_context, m_format); 540 541 renderTestPatternReference(uploadLevel); 542 renderTestPatternReference(stencilOnlyLevel); 543 544 gl.bindTexture(GL_TEXTURE_2D, *depthStencilTex); 545 gl.texStorage2D(GL_TEXTURE_2D, 1, m_format, width, height); 546 glu::texSubImage2D(renderCtx, GL_TEXTURE_2D, 0, 0, 0, uploadLevel); 547 GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading texture data failed"); 548 549 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 550 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, width, height); 551 552 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 553 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 554 checkFramebufferStatus(gl); 555 556 blitStencilToColor2D(renderCtx, *depthStencilTex, width, height); 557 glu::readPixels(renderCtx, 0, 0, readLevel); 558 559 { 560 const bool compareOk = compareStencilToRed(m_testCtx.getLog(), stencilOnlyLevel, readLevel); 561 m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 562 compareOk ? "Pass" : "Image comparison failed"); 563 } 564 565 return STOP; 566 } 567 568private: 569 const deUint32 m_format; 570}; 571 572class UploadTex2DArrayCase : public TestCase 573{ 574public: 575 UploadTex2DArrayCase (Context& context, const char* name, deUint32 format) 576 : TestCase (context, name, glu::getTextureFormatName(format)) 577 , m_format (format) 578 { 579 } 580 581 IterateResult iterate (void) 582 { 583 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 584 const glw::Functions& gl = renderCtx.getFunctions(); 585 const int width = 41; 586 const int height = 13; 587 const int levels = 7; 588 const int ptrnLevel = 3; 589 glu::Framebuffer fbo (renderCtx); 590 glu::Renderbuffer colorBuf (renderCtx); 591 glu::Texture depthStencilTex (renderCtx); 592 TextureLevel uploadLevel (glu::mapGLInternalFormat(m_format), width, height, levels); 593 594 checkDepthStencilFormatSupport(m_context, m_format); 595 596 for (int levelNdx = 0; levelNdx < levels; levelNdx++) 597 { 598 const tcu::PixelBufferAccess levelAccess = tcu::getSubregion(uploadLevel.getAccess(), 0, 0, levelNdx, width, height, 1); 599 600 if (levelNdx == ptrnLevel) 601 renderTestPatternReference(levelAccess); 602 else 603 tcu::clearStencil(levelAccess, levelNdx); 604 } 605 606 gl.bindTexture(GL_TEXTURE_2D_ARRAY, *depthStencilTex); 607 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, m_format, width, height, levels); 608 glu::texSubImage3D(renderCtx, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, uploadLevel); 609 GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading texture data failed"); 610 611 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 612 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, width, height); 613 614 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 615 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 616 checkFramebufferStatus(gl); 617 618 { 619 TextureLevel readLevel (TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), width, height); 620 bool allLevelsOk = true; 621 622 for (int levelNdx = 0; levelNdx < levels; levelNdx++) 623 { 624 tcu::ScopedLogSection section(m_testCtx.getLog(), "Level" + de::toString(levelNdx), "Level " + de::toString(levelNdx)); 625 bool levelOk; 626 627 blitStencilToColor2DArray(renderCtx, *depthStencilTex, width, height, levelNdx); 628 glu::readPixels(renderCtx, 0, 0, readLevel); 629 630 if (levelNdx == ptrnLevel) 631 { 632 TextureLevel reference(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), width, height); 633 renderTestPatternReference(reference); 634 635 levelOk = compareStencilToRed(m_testCtx.getLog(), reference, readLevel); 636 } 637 else 638 levelOk = compareRedChannel(m_testCtx.getLog(), readLevel, levelNdx); 639 640 if (!levelOk) 641 { 642 allLevelsOk = false; 643 break; 644 } 645 } 646 647 m_testCtx.setTestResult(allLevelsOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 648 allLevelsOk ? "Pass" : "Image comparison failed"); 649 } 650 651 return STOP; 652 } 653 654private: 655 const deUint32 m_format; 656}; 657 658class UploadTexCubeCase : public TestCase 659{ 660public: 661 UploadTexCubeCase (Context& context, const char* name, deUint32 format) 662 : TestCase (context, name, glu::getTextureFormatName(format)) 663 , m_format (format) 664 { 665 } 666 667 IterateResult iterate (void) 668 { 669 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 670 const glw::Functions& gl = renderCtx.getFunctions(); 671 const int size = 64; 672 const int renderWidth = 128; 673 const int renderHeight = 128; 674 vector<float> texCoord; 675 glu::Framebuffer fbo (renderCtx); 676 glu::Renderbuffer colorBuf (renderCtx); 677 glu::Texture depthStencilTex (renderCtx); 678 tcu::TextureCube texData (glu::mapGLInternalFormat(m_format), size); 679 tcu::TextureLevel result (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), renderWidth, renderHeight); 680 681 checkDepthStencilFormatSupport(m_context, m_format); 682 683 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 684 { 685 const tcu::CubeFace face = tcu::CubeFace(faceNdx); 686 const int stencilVal = 42*faceNdx; 687 688 texData.allocLevel(face, 0); 689 tcu::clearStencil(texData.getLevelFace(0, face), stencilVal); 690 } 691 692 glu::TextureTestUtil::computeQuadTexCoordCube(texCoord, tcu::CUBEFACE_NEGATIVE_X, Vec2(-1.5f, -1.3f), Vec2(1.3f, 1.4f)); 693 694 gl.bindTexture(GL_TEXTURE_CUBE_MAP, *depthStencilTex); 695 gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1, m_format, size, size); 696 697 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 698 glu::texSubImage2D(renderCtx, glu::getGLCubeFace(tcu::CubeFace(faceNdx)), 0, 0, 0, texData.getLevelFace(0, tcu::CubeFace(faceNdx))); 699 700 GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading texture data failed"); 701 702 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 703 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, renderWidth, renderHeight); 704 705 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 706 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 707 checkFramebufferStatus(gl); 708 709 blitStencilToColorCube(renderCtx, *depthStencilTex, &texCoord[0], renderWidth, renderHeight); 710 glu::readPixels(renderCtx, 0, 0, result); 711 712 { 713 using namespace glu::TextureTestUtil; 714 715 tcu::TextureCube redTex (TextureFormat(TextureFormat::R, TextureFormat::UNORM_INT8), size); 716 const ReferenceParams sampleParams (TEXTURETYPE_CUBE, tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, 717 tcu::Sampler::CLAMP_TO_EDGE, 718 tcu::Sampler::CLAMP_TO_EDGE, 719 tcu::Sampler::NEAREST, 720 tcu::Sampler::NEAREST)); 721 tcu::LookupPrecision lookupPrec; 722 tcu::LodPrecision lodPrec; 723 bool compareOk; 724 725 lookupPrec.colorMask = tcu::BVec4(true, true, true, true); 726 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(IVec4(8, 8, 8, 8)); 727 lookupPrec.coordBits = tcu::IVec3(22, 22, 22); 728 lookupPrec.uvwBits = tcu::IVec3(5, 5, 0); 729 lodPrec.lodBits = 7; 730 lodPrec.derivateBits = 16; 731 732 stencilToUnorm8(texData, redTex); 733 734 compareOk = verifyTextureResult(m_testCtx, result, redTex, &texCoord[0], sampleParams, lookupPrec, lodPrec, tcu::PixelFormat(8, 8, 8, 8)); 735 736 m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 737 compareOk ? "Pass" : "Image comparison failed"); 738 } 739 740 return STOP; 741 } 742 743private: 744 const deUint32 m_format; 745}; 746 747class RenderTex2DCase : public TestCase 748{ 749public: 750 RenderTex2DCase (Context& context, const char* name, deUint32 format) 751 : TestCase (context, name, glu::getTextureFormatName(format)) 752 , m_format (format) 753 { 754 } 755 756 IterateResult iterate (void) 757 { 758 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 759 const glw::Functions& gl = renderCtx.getFunctions(); 760 const int width = 117; 761 const int height = 193; 762 glu::Framebuffer fbo (renderCtx); 763 glu::Renderbuffer colorBuf (renderCtx); 764 glu::Texture depthStencilTex (renderCtx); 765 TextureLevel result (TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), width, height); 766 TextureLevel reference (TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), width, height); 767 768 checkDepthStencilFormatSupport(m_context, m_format); 769 770 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 771 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, width, height); 772 773 gl.bindTexture(GL_TEXTURE_2D, *depthStencilTex); 774 gl.texStorage2D(GL_TEXTURE_2D, 1, m_format, width, height); 775 776 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 777 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 778 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, *depthStencilTex, 0); 779 checkFramebufferStatus(gl); 780 781 drawTestPattern(renderCtx, width, height); 782 783 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); 784 checkFramebufferStatus(gl); 785 786 blitStencilToColor2D(renderCtx, *depthStencilTex, width, height); 787 glu::readPixels(renderCtx, 0, 0, result.getAccess()); 788 789 renderTestPatternReference(reference); 790 791 { 792 const bool compareOk = compareStencilToRed(m_testCtx.getLog(), reference, result); 793 m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 794 compareOk ? "Pass" : "Image comparison failed"); 795 } 796 797 return STOP; 798 } 799 800private: 801 const deUint32 m_format; 802}; 803 804class ClearTex2DCase : public TestCase 805{ 806public: 807 ClearTex2DCase (Context& context, const char* name, deUint32 format) 808 : TestCase (context, name, glu::getTextureFormatName(format)) 809 , m_format (format) 810 { 811 } 812 813 IterateResult iterate (void) 814 { 815 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 816 const glw::Functions& gl = renderCtx.getFunctions(); 817 const int width = 125; 818 const int height = 117; 819 const int cellSize = 8; 820 glu::Framebuffer fbo (renderCtx); 821 glu::Renderbuffer colorBuf (renderCtx); 822 glu::Texture depthStencilTex (renderCtx); 823 TextureLevel result (TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), width, height); 824 TextureLevel reference (TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), width, height); 825 826 checkDepthStencilFormatSupport(m_context, m_format); 827 828 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 829 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, width, height); 830 831 gl.bindTexture(GL_TEXTURE_2D, *depthStencilTex); 832 gl.texStorage2D(GL_TEXTURE_2D, 1, m_format, width, height); 833 834 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 835 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 836 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, *depthStencilTex, 0); 837 checkFramebufferStatus(gl); 838 839 gl.enable(GL_SCISSOR_TEST); 840 841 for (int y = 0; y < height; y += cellSize) 842 { 843 for (int x = 0; x < width; x += cellSize) 844 { 845 const int clearW = de::min(cellSize, width-x); 846 const int clearH = de::min(cellSize, height-y); 847 const int stencil = int((deInt32Hash(x) ^ deInt32Hash(y)) & 0xff); 848 849 gl.clearStencil(stencil); 850 gl.scissor(x, y, clearW, clearH); 851 gl.clear(GL_STENCIL_BUFFER_BIT); 852 853 tcu::clearStencil(tcu::getSubregion(reference.getAccess(), x, y, clearW, clearH), stencil); 854 } 855 } 856 857 gl.disable(GL_SCISSOR_TEST); 858 859 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); 860 checkFramebufferStatus(gl); 861 862 blitStencilToColor2D(renderCtx, *depthStencilTex, width, height); 863 glu::readPixels(renderCtx, 0, 0, result.getAccess()); 864 865 { 866 const bool compareOk = compareStencilToRed(m_testCtx.getLog(), reference, result); 867 m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 868 compareOk ? "Pass" : "Image comparison failed"); 869 } 870 871 return STOP; 872 } 873 874private: 875 const deUint32 m_format; 876}; 877 878class CompareModeCase : public TestCase 879{ 880public: 881 CompareModeCase (Context& context, const char* name, deUint32 format) 882 : TestCase (context, name, glu::getTextureFormatName(format)) 883 , m_format (format) 884 { 885 } 886 887 IterateResult iterate (void) 888 { 889 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 890 const glw::Functions& gl = renderCtx.getFunctions(); 891 const int width = 64; 892 const int height = 64; 893 glu::Framebuffer fbo (renderCtx); 894 glu::Renderbuffer colorBuf (renderCtx); 895 glu::Texture depthStencilTex (renderCtx); 896 TextureLevel uploadLevel (glu::mapGLInternalFormat(m_format), width, height); 897 TextureLevel readLevel (TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), width, height); 898 TextureLevel stencilOnlyLevel (TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), width, height); 899 900 checkDepthStencilFormatSupport(m_context, m_format); 901 902 m_testCtx.getLog() << TestLog::Message << "NOTE: Texture compare mode has no effect when reading stencil values." << TestLog::EndMessage; 903 904 renderTestPatternReference(uploadLevel); 905 renderTestPatternReference(stencilOnlyLevel); 906 907 gl.bindTexture(GL_TEXTURE_2D, *depthStencilTex); 908 gl.texStorage2D(GL_TEXTURE_2D, 1, m_format, width, height); 909 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 910 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); 911 glu::texSubImage2D(renderCtx, GL_TEXTURE_2D, 0, 0, 0, uploadLevel); 912 GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading texture data failed"); 913 914 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 915 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, width, height); 916 917 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 918 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 919 checkFramebufferStatus(gl); 920 921 blitStencilToColor2D(renderCtx, *depthStencilTex, width, height); 922 glu::readPixels(renderCtx, 0, 0, readLevel); 923 924 { 925 const bool compareOk = compareStencilToRed(m_testCtx.getLog(), stencilOnlyLevel, readLevel); 926 m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 927 compareOk ? "Pass" : "Image comparison failed"); 928 } 929 930 return STOP; 931 } 932 933private: 934 const deUint32 m_format; 935}; 936 937class BaseLevelCase : public TestCase 938{ 939public: 940 BaseLevelCase (Context& context, const char* name, deUint32 format) 941 : TestCase (context, name, glu::getTextureFormatName(format)) 942 , m_format (format) 943 { 944 } 945 946 IterateResult iterate (void) 947 { 948 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 949 const glw::Functions& gl = renderCtx.getFunctions(); 950 const int width = 128; 951 const int height = 128; 952 const int levelNdx = 2; 953 const int levelWidth = width>>levelNdx; 954 const int levelHeight = height>>levelNdx; 955 glu::Framebuffer fbo (renderCtx); 956 glu::Renderbuffer colorBuf (renderCtx); 957 glu::Texture depthStencilTex (renderCtx); 958 TextureLevel uploadLevel (glu::mapGLInternalFormat(m_format), levelWidth, levelHeight); 959 TextureLevel readLevel (TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32), levelWidth, levelHeight); 960 TextureLevel stencilOnlyLevel (TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), levelWidth, levelHeight); 961 962 checkDepthStencilFormatSupport(m_context, m_format); 963 964 m_testCtx.getLog() << TestLog::Message << "GL_TEXTURE_BASE_LEVEL = " << levelNdx << TestLog::EndMessage; 965 966 renderTestPatternReference(uploadLevel); 967 renderTestPatternReference(stencilOnlyLevel); 968 969 gl.bindTexture(GL_TEXTURE_2D, *depthStencilTex); 970 gl.texStorage2D(GL_TEXTURE_2D, deLog2Floor32(de::max(width, height))+1, m_format, width, height); 971 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, levelNdx); 972 glu::texSubImage2D(renderCtx, GL_TEXTURE_2D, levelNdx, 0, 0, uploadLevel); 973 GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading texture data failed"); 974 975 gl.bindRenderbuffer(GL_RENDERBUFFER, *colorBuf); 976 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, levelWidth, levelHeight); 977 978 gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 979 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuf); 980 checkFramebufferStatus(gl); 981 982 blitStencilToColor2D(renderCtx, *depthStencilTex, levelWidth, levelHeight); 983 glu::readPixels(renderCtx, 0, 0, readLevel); 984 985 { 986 const bool compareOk = compareStencilToRed(m_testCtx.getLog(), stencilOnlyLevel, readLevel); 987 m_testCtx.setTestResult(compareOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 988 compareOk ? "Pass" : "Image comparison failed"); 989 } 990 991 return STOP; 992 } 993 994private: 995 const deUint32 m_format; 996}; 997 998} // anonymous 999 1000StencilTexturingTests::StencilTexturingTests (Context& context) 1001 : TestCaseGroup(context, "stencil_texturing", "Stencil texturing tests") 1002{ 1003} 1004 1005StencilTexturingTests::~StencilTexturingTests (void) 1006{ 1007} 1008 1009void StencilTexturingTests::init (void) 1010{ 1011 // .format 1012 { 1013 tcu::TestCaseGroup* const formatGroup = new tcu::TestCaseGroup(m_testCtx, "format", "Formats"); 1014 addChild(formatGroup); 1015 1016 formatGroup->addChild(new UploadTex2DCase (m_context, "depth32f_stencil8_2d", GL_DEPTH32F_STENCIL8)); 1017 formatGroup->addChild(new UploadTex2DArrayCase (m_context, "depth32f_stencil8_2d_array", GL_DEPTH32F_STENCIL8)); 1018 formatGroup->addChild(new UploadTexCubeCase (m_context, "depth32f_stencil8_cube", GL_DEPTH32F_STENCIL8)); 1019 formatGroup->addChild(new UploadTex2DCase (m_context, "depth24_stencil8_2d", GL_DEPTH24_STENCIL8)); 1020 formatGroup->addChild(new UploadTex2DArrayCase (m_context, "depth24_stencil8_2d_array", GL_DEPTH24_STENCIL8)); 1021 formatGroup->addChild(new UploadTexCubeCase (m_context, "depth24_stencil8_cube", GL_DEPTH24_STENCIL8)); 1022 1023 // OES_texture_stencil8 1024 formatGroup->addChild(new UploadTex2DCase (m_context, "stencil_index8_2d", GL_STENCIL_INDEX8)); 1025 formatGroup->addChild(new UploadTex2DArrayCase (m_context, "stencil_index8_2d_array", GL_STENCIL_INDEX8)); 1026 formatGroup->addChild(new UploadTexCubeCase (m_context, "stencil_index8_cube", GL_STENCIL_INDEX8)); 1027 } 1028 1029 // .render 1030 { 1031 tcu::TestCaseGroup* const readRenderGroup = new tcu::TestCaseGroup(m_testCtx, "render", "Read rendered stencil values"); 1032 addChild(readRenderGroup); 1033 1034 readRenderGroup->addChild(new ClearTex2DCase (m_context, "depth32f_stencil8_clear", GL_DEPTH32F_STENCIL8)); 1035 readRenderGroup->addChild(new RenderTex2DCase (m_context, "depth32f_stencil8_draw", GL_DEPTH32F_STENCIL8)); 1036 readRenderGroup->addChild(new ClearTex2DCase (m_context, "depth24_stencil8_clear", GL_DEPTH24_STENCIL8)); 1037 readRenderGroup->addChild(new RenderTex2DCase (m_context, "depth24_stencil8_draw", GL_DEPTH24_STENCIL8)); 1038 } 1039 1040 // .misc 1041 { 1042 tcu::TestCaseGroup* const miscGroup = new tcu::TestCaseGroup(m_testCtx, "misc", "Misc cases"); 1043 addChild(miscGroup); 1044 1045 miscGroup->addChild(new CompareModeCase (m_context, "compare_mode_effect", GL_DEPTH24_STENCIL8)); 1046 miscGroup->addChild(new BaseLevelCase (m_context, "base_level", GL_DEPTH24_STENCIL8)); 1047 } 1048} 1049 1050} // Functional 1051} // gles31 1052} // deqp 1053