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