1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 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 Framebuffer Object Tests. 22 * 23 * Notes: 24 * + Like in API tests, tcu::sgl2s::Context class is used. 25 * + ReferenceContext is used to generate reference images. 26 * + API calls can be logged \todo [pyry] Implement. 27 *//*--------------------------------------------------------------------*/ 28 29 #include "es2fFboRenderTest.hpp" 30 #include "sglrContextUtil.hpp" 31 #include "sglrGLContext.hpp" 32 #include "sglrReferenceContext.hpp" 33 #include "tcuSurface.hpp" 34 #include "tcuTextureUtil.hpp" 35 #include "tcuImageCompare.hpp" 36 #include "tcuRenderTarget.hpp" 37 #include "gluPixelTransfer.hpp" 38 #include "gluTextureUtil.hpp" 39 #include "gluStrUtil.hpp" 40 #include "deRandom.hpp" 41 #include "deString.h" 42 43 #include "glwFunctions.hpp" 44 #include "glwEnums.hpp" 45 46 using std::vector; 47 using std::string; 48 using tcu::Vec2; 49 using tcu::Vec3; 50 using tcu::Vec4; 51 using tcu::RGBA; 52 using tcu::Surface; 53 using namespace glw; // GL types 54 55 namespace deqp 56 { 57 namespace gles2 58 { 59 namespace Functional 60 { 61 62 // Shaders. 63 64 class FlatColorShader : public sglr::ShaderProgram 65 { 66 public: 67 FlatColorShader (void) 68 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 69 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 70 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 71 << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4) 72 << sglr::pdec::VertexSource( 73 "attribute highp vec4 a_position;\n" 74 "void main (void)\n" 75 "{\n" 76 " gl_Position = a_position;\n" 77 "}\n") 78 << sglr::pdec::FragmentSource( 79 "uniform mediump vec4 u_color;\n" 80 "void main (void)\n" 81 "{\n" 82 " gl_FragColor = u_color;\n" 83 "}\n")) 84 { 85 } 86 87 void setColor (sglr::Context& gl, deUint32 program, const tcu::Vec4& color) 88 { 89 gl.useProgram(program); 90 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, color.getPtr()); 91 } 92 93 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 94 { 95 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 96 packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx); 97 } 98 99 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 100 { 101 const tcu::Vec4 color(m_uniforms[0].value.f4); 102 103 DE_UNREF(packets); 104 105 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 106 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 107 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); 108 } 109 }; 110 111 class SingleTex2DShader : public sglr::ShaderProgram 112 { 113 public: 114 SingleTex2DShader (void) 115 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 116 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 117 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT) 118 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 119 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 120 << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D) 121 << sglr::pdec::VertexSource( 122 "attribute highp vec4 a_position;\n" 123 "attribute mediump vec2 a_coord;\n" 124 "varying mediump vec2 v_coord;\n" 125 "void main (void)\n" 126 "{\n" 127 " gl_Position = a_position;\n" 128 " v_coord = a_coord;\n" 129 "}\n") 130 << sglr::pdec::FragmentSource( 131 "uniform sampler2D u_sampler0;\n" 132 "varying mediump vec2 v_coord;\n" 133 "void main (void)\n" 134 "{\n" 135 " gl_FragColor = texture2D(u_sampler0, v_coord);\n" 136 "}\n")) 137 { 138 } 139 140 void setUnit (sglr::Context& gl, deUint32 program, int unitNdx) 141 { 142 gl.useProgram(program); 143 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unitNdx); 144 } 145 146 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 147 { 148 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 149 { 150 rr::VertexPacket& packet = *packets[packetNdx]; 151 152 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); 153 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx); 154 } 155 } 156 157 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 158 { 159 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 160 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 161 { 162 const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx); 163 const float lod = 0.0f; 164 165 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod)); 166 } 167 } 168 169 }; 170 171 class MixTexturesShader : public sglr::ShaderProgram 172 { 173 public: 174 MixTexturesShader (void) 175 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 176 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 177 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT) 178 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 179 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 180 << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D) 181 << sglr::pdec::Uniform("u_sampler1", glu::TYPE_SAMPLER_2D) 182 << sglr::pdec::VertexSource( 183 "attribute highp vec4 a_position;\n" 184 "attribute mediump vec2 a_coord;\n" 185 "varying mediump vec2 v_coord;\n" 186 "void main (void)\n" 187 "{\n" 188 " gl_Position = a_position;\n" 189 " v_coord = a_coord;\n" 190 "}\n") 191 << sglr::pdec::FragmentSource( 192 "uniform sampler2D u_sampler0;\n" 193 "uniform sampler2D u_sampler1;\n" 194 "varying mediump vec2 v_coord;\n" 195 "void main (void)\n" 196 "{\n" 197 " gl_FragColor = texture2D(u_sampler0, v_coord)*0.5 + texture2D(u_sampler1, v_coord)*0.5;\n" 198 "}\n")) 199 { 200 } 201 202 void setUnits (sglr::Context& gl, deUint32 program, int unit0, int unit1) 203 { 204 gl.useProgram(program); 205 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unit0); 206 gl.uniform1i(gl.getUniformLocation(program, "u_sampler1"), unit1); 207 } 208 209 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 210 { 211 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 212 { 213 rr::VertexPacket& packet = *packets[packetNdx]; 214 215 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); 216 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx); 217 } 218 } 219 220 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 221 { 222 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 223 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 224 { 225 const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx); 226 const float lod = 0.0f; 227 228 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f 229 + this->m_uniforms[1].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f); 230 } 231 } 232 }; 233 234 // Framebuffer config. 235 236 class FboConfig 237 { 238 public: 239 FboConfig (void) 240 : colorbufferType (GL_NONE) 241 , colorbufferFormat (GL_NONE) 242 , depthbufferType (GL_NONE) 243 , depthbufferFormat (GL_NONE) 244 , stencilbufferType (GL_NONE) 245 , stencilbufferFormat (GL_NONE) 246 { 247 } 248 249 std::string getName (void) const; 250 251 GLenum colorbufferType; //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER 252 GLenum colorbufferFormat; //!< Internal format for color buffer texture or renderbuffer 253 254 GLenum depthbufferType; //!< GL_RENDERBUFFER 255 GLenum depthbufferFormat; 256 257 GLenum stencilbufferType; //!< GL_RENDERBUFFER 258 GLenum stencilbufferFormat; 259 260 private: 261 static const char* getFormatName (GLenum format); 262 }; 263 264 const char* FboConfig::getFormatName (GLenum format) 265 { 266 switch (format) 267 { 268 case GL_RGB: return "rgb"; 269 case GL_RGBA: return "rgba"; 270 case GL_ALPHA: return "alpha"; 271 case GL_LUMINANCE: return "luminance"; 272 case GL_LUMINANCE_ALPHA: return "luminance_alpha"; 273 case GL_RGB565: return "rgb565"; 274 case GL_RGB5_A1: return "rgb5_a1"; 275 case GL_RGBA4: return "rgba4"; 276 case GL_RGBA16F: return "rgba16f"; 277 case GL_RGB16F: return "rgb16f"; 278 case GL_DEPTH_COMPONENT16: return "depth_component16"; 279 case GL_STENCIL_INDEX8: return "stencil_index8"; 280 default: DE_ASSERT(false); return DE_NULL; 281 } 282 } 283 284 std::string FboConfig::getName (void) const 285 { 286 std::string name = ""; 287 288 if (colorbufferType != GL_NONE) 289 { 290 switch (colorbufferType) 291 { 292 case GL_TEXTURE_2D: name += "tex2d_"; break; 293 case GL_TEXTURE_CUBE_MAP: name += "texcube_"; break; 294 case GL_RENDERBUFFER: name += "rbo_"; break; 295 default: DE_ASSERT(false); break; 296 } 297 name += getFormatName(colorbufferFormat); 298 } 299 300 if (depthbufferType != GL_NONE) 301 { 302 DE_ASSERT(depthbufferType == GL_RENDERBUFFER); 303 if (name.length() > 0) 304 name += "_"; 305 name += getFormatName(depthbufferFormat); 306 } 307 308 if (stencilbufferType != GL_NONE) 309 { 310 DE_ASSERT(stencilbufferType == GL_RENDERBUFFER); 311 if (name.length() > 0) 312 name += "_"; 313 name += getFormatName(stencilbufferFormat); 314 } 315 316 return name; 317 } 318 319 class FboIncompleteException : public tcu::TestError 320 { 321 public: 322 FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line); 323 virtual ~FboIncompleteException (void) throw() {} 324 325 const FboConfig& getConfig (void) const { return m_config; } 326 GLenum getReason (void) const { return m_reason; } 327 328 private: 329 FboConfig m_config; 330 GLenum m_reason; 331 }; 332 333 static const char* getFboIncompleteReasonName (GLenum reason) 334 { 335 switch (reason) 336 { 337 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; 338 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; 339 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; 340 case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED"; 341 case GL_FRAMEBUFFER_COMPLETE: return "GL_FRAMEBUFFER_COMPLETE"; 342 default: return "UNKNOWN"; 343 } 344 } 345 346 FboIncompleteException::FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line) 347 : TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line) 348 , m_config(config) 349 , m_reason(reason) 350 { 351 } 352 353 class Framebuffer 354 { 355 public: 356 Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorbuffer = 0, deUint32 depthbuffer = 0, deUint32 stencilbuffer = 0); 357 ~Framebuffer (void); 358 359 const FboConfig& getConfig (void) const { return m_config; } 360 deUint32 getFramebuffer (void) const { return m_framebuffer; } 361 deUint32 getColorbuffer (void) const { return m_colorbuffer; } 362 deUint32 getDepthbuffer (void) const { return m_depthbuffer; } 363 deUint32 getStencilbuffer (void) const { return m_stencilbuffer; } 364 365 void checkCompleteness (void); 366 367 private: 368 void createRbo (deUint32& name, GLenum format, int width, int height); 369 void destroyBuffer (deUint32 name, GLenum type); 370 371 FboConfig m_config; 372 sglr::Context& m_context; 373 deUint32 m_framebuffer; 374 deUint32 m_colorbuffer; 375 deUint32 m_depthbuffer; 376 deUint32 m_stencilbuffer; 377 }; 378 379 static bool isExtensionSupported (sglr::Context& context, const char* name) 380 { 381 std::istringstream extensions(context.getString(GL_EXTENSIONS)); 382 std::string extension; 383 384 while (std::getline(extensions, extension, ' ')) 385 { 386 if (extension == name) 387 return true; 388 } 389 390 return false; 391 } 392 393 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat) 394 { 395 switch (sizedFormat) 396 { 397 case GL_RGBA16F: 398 case GL_RGB16F: 399 case GL_RG16F: 400 case GL_R16F: 401 if (!isExtensionSupported(context, "GL_EXT_color_buffer_half_float")) 402 throw tcu::NotSupportedError("GL_EXT_color_buffer_half_float is not supported"); 403 404 default: 405 break; 406 } 407 } 408 409 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorbuffer, deUint32 depthbuffer, deUint32 stencilbuffer) 410 : m_config (config) 411 , m_context (context) 412 , m_framebuffer (fbo) 413 , m_colorbuffer (colorbuffer) 414 , m_depthbuffer (depthbuffer) 415 , m_stencilbuffer (stencilbuffer) 416 { 417 // Verify that color format is supported 418 checkColorFormatSupport(context, config.colorbufferFormat); 419 420 if (m_framebuffer == 0) 421 context.genFramebuffers(1, &m_framebuffer); 422 context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 423 424 switch (m_config.colorbufferType) 425 { 426 case GL_TEXTURE_2D: 427 if (m_colorbuffer == 0) 428 context.genTextures(1, &m_colorbuffer); 429 context.bindTexture(GL_TEXTURE_2D, m_colorbuffer); 430 context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorbufferFormat, width, height); 431 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 432 433 if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height)) 434 { 435 // Set wrap mode to clamp for NPOT FBOs 436 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 437 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 438 } 439 440 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorbuffer, 0); 441 break; 442 443 case GL_TEXTURE_CUBE_MAP: 444 DE_FATAL("TODO"); 445 break; 446 447 case GL_RENDERBUFFER: 448 createRbo(m_colorbuffer, m_config.colorbufferFormat, width, height); 449 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorbuffer); 450 break; 451 452 default: 453 DE_ASSERT(m_config.colorbufferType == GL_NONE); 454 break; 455 } 456 457 if (m_config.depthbufferType == GL_RENDERBUFFER) 458 { 459 createRbo(m_depthbuffer, m_config.depthbufferFormat, width, height); 460 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer); 461 } 462 else 463 DE_ASSERT(m_config.depthbufferType == GL_NONE); 464 465 if (m_config.stencilbufferType == GL_RENDERBUFFER) 466 { 467 createRbo(m_stencilbuffer, m_config.stencilbufferFormat, width, height); 468 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer); 469 } 470 else 471 DE_ASSERT(m_config.stencilbufferType == GL_NONE); 472 473 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 474 } 475 476 Framebuffer::~Framebuffer (void) 477 { 478 m_context.deleteFramebuffers(1, &m_framebuffer); 479 destroyBuffer(m_colorbuffer, m_config.colorbufferType); 480 destroyBuffer(m_depthbuffer, m_config.depthbufferType); 481 destroyBuffer(m_stencilbuffer, m_config.stencilbufferType); 482 } 483 484 void Framebuffer::checkCompleteness (void) 485 { 486 m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 487 GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER); 488 m_context.bindFramebuffer(GL_FRAMEBUFFER, 0); 489 if (status != GL_FRAMEBUFFER_COMPLETE) 490 throw FboIncompleteException(m_config, status, __FILE__, __LINE__); 491 } 492 493 void Framebuffer::createRbo (deUint32& name, GLenum format, int width, int height) 494 { 495 if (name == 0) 496 m_context.genRenderbuffers(1, &name); 497 m_context.bindRenderbuffer(GL_RENDERBUFFER, name); 498 m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height); 499 } 500 501 void Framebuffer::destroyBuffer (deUint32 name, GLenum type) 502 { 503 if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP) 504 m_context.deleteTextures(1, &name); 505 else if (type == GL_RENDERBUFFER) 506 m_context.deleteRenderbuffers(1, &name); 507 else 508 DE_ASSERT(type == GL_NONE); 509 } 510 511 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height) 512 { 513 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType); 514 tcu::TextureLevel level (texFormat, width, height); 515 516 tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height); 517 518 context.bindTexture(GL_TEXTURE_2D, name); 519 context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr()); 520 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 521 } 522 523 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height) 524 { 525 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType); 526 tcu::TextureLevel level (texFormat, width, height); 527 528 tcu::fillWithRGBAQuads(level.getAccess()); 529 530 context.bindTexture(GL_TEXTURE_2D, name); 531 context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr()); 532 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 533 } 534 535 class FboRenderCase : public TestCase 536 { 537 public: 538 FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config); 539 virtual ~FboRenderCase (void) {} 540 541 virtual IterateResult iterate (void); 542 virtual void render (sglr::Context& fboContext, Surface& dst) = DE_NULL; 543 544 const FboConfig& getConfig (void) const { return m_config; } 545 546 static bool isConfigSupported (const FboConfig& config) { DE_UNREF(config); return true; } 547 548 private: 549 FboConfig m_config; 550 }; 551 552 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config) 553 : TestCase(context, name, description) 554 , m_config(config) 555 { 556 } 557 558 TestCase::IterateResult FboRenderCase::iterate (void) 559 { 560 Vec4 clearColor (0.125f, 0.25f, 0.5f, 1.0f); 561 glu::RenderContext& renderCtx = m_context.getRenderContext(); 562 const tcu::RenderTarget& renderTarget = m_context.getRenderTarget(); 563 tcu::TestLog& log = m_testCtx.getLog(); 564 const char* failReason = DE_NULL; 565 566 // Position & size for context 567 deRandom rnd; 568 deRandom_init(&rnd, deStringHash(getName())); 569 570 int width = deMin32(renderTarget.getWidth(), 128); 571 int height = deMin32(renderTarget.getHeight(), 128); 572 int xMax = renderTarget.getWidth()-width+1; 573 int yMax = renderTarget.getHeight()-height+1; 574 int x = deRandom_getUint32(&rnd) % xMax; 575 int y = deRandom_getUint32(&rnd) % yMax; 576 577 tcu::Surface gles2Frame (width, height); 578 tcu::Surface refFrame (width, height); 579 GLenum gles2Error; 580 GLenum refError; 581 582 // Render using GLES2 583 try 584 { 585 sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height)); 586 587 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); 588 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 589 590 render(context, gles2Frame); // Call actual render func 591 gles2Error = context.getError(); 592 } 593 catch (const FboIncompleteException& e) 594 { 595 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED) 596 { 597 // Mark test case as unsupported 598 log << e; 599 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 600 return STOP; 601 } 602 else 603 throw; // Propagate error 604 } 605 606 // Render reference image 607 { 608 sglr::ReferenceContextBuffers buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height); 609 sglr::ReferenceContext context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 610 611 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); 612 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 613 614 render(context, refFrame); 615 refError = context.getError(); 616 } 617 618 // Compare error codes 619 bool errorCodesOk = (gles2Error == refError); 620 621 if (!errorCodesOk) 622 { 623 log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles2Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage; 624 failReason = "Got unexpected error"; 625 } 626 627 // Compare images 628 const float threshold = 0.03f; 629 bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame, threshold, tcu::COMPARE_LOG_RESULT); 630 631 if (!imagesOk && !failReason) 632 failReason = "Image comparison failed"; 633 634 // Store test result 635 bool isOk = errorCodesOk && imagesOk; 636 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 637 isOk ? "Pass" : failReason); 638 639 return STOP; 640 } 641 642 namespace FboCases 643 { 644 645 class ColorClearsTest : public FboRenderCase 646 { 647 public: 648 ColorClearsTest (Context& context, const FboConfig& config); 649 ~ColorClearsTest (void) {} 650 651 void render (sglr::Context& context, Surface& dst); 652 }; 653 654 ColorClearsTest::ColorClearsTest (Context& context, const FboConfig& config) 655 : FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config) 656 { 657 } 658 659 void ColorClearsTest::render (sglr::Context& context, Surface& dst) 660 { 661 int width = 128; 662 int height = 128; 663 deRandom rnd; 664 665 deRandom_init(&rnd, 0); 666 667 // Create framebuffer 668 Framebuffer fbo(context, getConfig(), width, height); 669 fbo.checkCompleteness(); 670 671 // Clear fbo 672 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 673 context.viewport(0, 0, width, height); 674 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 675 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 676 677 // Enable scissor test. 678 context.enable(GL_SCISSOR_TEST); 679 680 // Do 10 random color clears 681 for (int i = 0; i < 15; i++) 682 { 683 int cX = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % width; 684 int cY = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % height; 685 int cWidth = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (width-cX); 686 int cHeight = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (height-cY); 687 Vec4 color = RGBA(deRandom_getUint32(&rnd)).toVec(); 688 689 context.scissor(cX, cY, cWidth, cHeight); 690 context.clearColor(color.x(), color.y(), color.z(), color.w()); 691 context.clear(GL_COLOR_BUFFER_BIT); 692 } 693 694 // Disable scissor. 695 context.disable(GL_SCISSOR_TEST); 696 697 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D) 698 { 699 // Unbind fbo 700 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 701 702 // Draw to screen 703 SingleTex2DShader shader; 704 deUint32 shaderID = context.createProgram(&shader); 705 706 shader.setUnit(context, shaderID, 0); 707 708 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 709 context.viewport(0, 0, context.getWidth(), context.getHeight()); 710 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 711 712 // Read from screen 713 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 714 } 715 else 716 { 717 // clear alpha channel for GL_RGB5_A1 format because test 718 // thresholds for the alpha channel do not account for dithering 719 if(getConfig().colorbufferFormat == GL_RGB5_A1) 720 { 721 context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); 722 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 723 context.clear(GL_COLOR_BUFFER_BIT); 724 context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 725 } 726 727 // Read from fbo 728 context.readPixels(dst, 0, 0, width, height); 729 } 730 } 731 732 class IntersectingQuadsTest : public FboRenderCase 733 { 734 public: 735 IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot = false); 736 virtual ~IntersectingQuadsTest (void) {} 737 738 virtual void render (sglr::Context& context, Surface& dst); 739 740 static bool isConfigSupported (const FboConfig& config); 741 742 private: 743 int m_fboWidth; 744 int m_fboHeight; 745 }; 746 747 class IntersectingQuadsNpotTest : public IntersectingQuadsTest 748 { 749 public: 750 IntersectingQuadsNpotTest (Context& context, const FboConfig& config) 751 : IntersectingQuadsTest(context, config, true) 752 { 753 } 754 }; 755 756 IntersectingQuadsTest::IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot) 757 : FboRenderCase (context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads", config) 758 , m_fboWidth (npot ? 127 : 128) 759 , m_fboHeight (npot ? 95 : 128) 760 { 761 } 762 763 bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config) 764 { 765 // \note Disabled for stencil configurations since doesn't exercise stencil buffer 766 return config.depthbufferType != GL_NONE && 767 config.stencilbufferType == GL_NONE; 768 } 769 770 void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst) 771 { 772 SingleTex2DShader texShader; 773 deUint32 texShaderID = ctx.createProgram(&texShader); 774 775 deUint32 metaballsTex = 1; 776 deUint32 quadsTex = 2; 777 778 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 779 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 780 781 int width = m_fboWidth; 782 int height = m_fboHeight; 783 Framebuffer fbo(ctx, getConfig(), width, height); 784 fbo.checkCompleteness(); 785 786 // Setup shaders 787 texShader.setUnit(ctx, texShaderID, 0); 788 789 // Draw scene 790 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 791 ctx.viewport(0, 0, width, height); 792 ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f); 793 ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 794 795 ctx.enable(GL_DEPTH_TEST); 796 797 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex); 798 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); 799 800 ctx.bindTexture(GL_TEXTURE_2D, quadsTex); 801 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f)); 802 803 ctx.disable(GL_DEPTH_TEST); 804 805 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D) 806 { 807 // Unbind fbo 808 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0); 809 810 // Draw to screen 811 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 812 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight()); 813 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 814 815 // Read from screen 816 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight()); 817 } 818 else 819 { 820 // Read from fbo 821 ctx.readPixels(dst, 0, 0, width, height); 822 } 823 } 824 825 class MixTest : public FboRenderCase 826 { 827 public: 828 MixTest (Context& context, const FboConfig& config, bool npot = false); 829 virtual ~MixTest (void) {} 830 831 void render (sglr::Context& context, Surface& dst); 832 833 static bool isConfigSupported (const FboConfig& config); 834 835 private: 836 int m_fboAWidth; 837 int m_fboAHeight; 838 int m_fboBWidth; 839 int m_fboBHeight; 840 }; 841 842 class MixNpotTest : public MixTest 843 { 844 public: 845 MixNpotTest (Context& context, const FboConfig& config) 846 : MixTest(context, config, true) 847 { 848 } 849 }; 850 851 MixTest::MixTest (Context& context, const FboConfig& config, bool npot) 852 : FboRenderCase (context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(), "Use two fbos as sources in draw operation", config) 853 , m_fboAWidth (npot ? 127 : 128) 854 , m_fboAHeight (npot ? 95 : 128) 855 , m_fboBWidth (npot ? 55 : 64) 856 , m_fboBHeight (npot ? 63 : 64) 857 { 858 } 859 860 bool MixTest::isConfigSupported (const FboConfig& config) 861 { 862 // \note Disabled for stencil configurations since doesn't exercise stencil buffer 863 return config.colorbufferType == GL_TEXTURE_2D && 864 config.stencilbufferType == GL_NONE; 865 } 866 867 void MixTest::render (sglr::Context& context, Surface& dst) 868 { 869 SingleTex2DShader singleTexShader; 870 MixTexturesShader mixShader; 871 872 deUint32 singleTexShaderID = context.createProgram(&singleTexShader); 873 deUint32 mixShaderID = context.createProgram(&mixShader); 874 875 // Texture with metaballs 876 deUint32 metaballsTex = 1; 877 context.pixelStorei(GL_UNPACK_ALIGNMENT, 1); 878 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 879 880 // Setup shaders 881 singleTexShader.setUnit(context, singleTexShaderID, 0); 882 mixShader.setUnits(context, mixShaderID, 0, 1); 883 884 // Fbo, quad with metaballs texture 885 Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight); 886 fboA.checkCompleteness(); 887 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer()); 888 context.viewport(0, 0, m_fboAWidth, m_fboAHeight); 889 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 890 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 891 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 892 sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 893 894 // Fbo, color clears 895 Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight); 896 fboB.checkCompleteness(); 897 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); 898 context.viewport(0, 0, m_fboBWidth, m_fboBHeight); 899 context.enable(GL_SCISSOR_TEST); 900 context.scissor(0, 0, 32, 64); 901 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f); 902 context.clear(GL_COLOR_BUFFER_BIT); 903 context.scissor(32, 0, 32, 64); 904 context.clearColor(0.0f, 1.0f, 0.0f, 1.0f); 905 context.clear(GL_COLOR_BUFFER_BIT); 906 context.disable(GL_SCISSOR_TEST); 907 908 // Final mix op 909 context.activeTexture(GL_TEXTURE0); 910 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer()); 911 context.activeTexture(GL_TEXTURE1); 912 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer()); 913 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 914 context.viewport(0, 0, context.getWidth(), context.getHeight()); 915 sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 916 917 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 918 } 919 920 class BlendTest : public FboRenderCase 921 { 922 public: 923 BlendTest (Context& context, const FboConfig& config, bool npot = false); 924 virtual ~BlendTest (void) {} 925 926 void render (sglr::Context& context, Surface& dst); 927 928 static bool isConfigSupported (const FboConfig& config); 929 930 private: 931 int m_fboWidth; 932 int m_fboHeight; 933 }; 934 935 class BlendNpotTest : public BlendTest 936 { 937 public: 938 BlendNpotTest (Context& context, const FboConfig& config) 939 : BlendTest(context, config, true) 940 { 941 } 942 }; 943 944 BlendTest::BlendTest (Context& context, const FboConfig& config, bool npot) 945 : FboRenderCase (context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo", config) 946 , m_fboWidth (npot ? 111 : 128) 947 , m_fboHeight (npot ? 122 : 128) 948 { 949 } 950 951 bool BlendTest::isConfigSupported (const FboConfig& config) 952 { 953 // \note Disabled for stencil configurations since doesn't exercise stencil buffer 954 return config.stencilbufferType == GL_NONE; 955 } 956 957 void BlendTest::render (sglr::Context& context, Surface& dst) 958 { 959 SingleTex2DShader shader; 960 deUint32 shaderID = context.createProgram(&shader); 961 int width = m_fboWidth; 962 int height = m_fboHeight; 963 deUint32 metaballsTex = 1; 964 965 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64); 966 967 Framebuffer fbo(context, getConfig(), width, height); 968 fbo.checkCompleteness(); 969 970 shader.setUnit(context, shaderID, 0); 971 972 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 973 context.viewport(0, 0, width, height); 974 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 975 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f); 976 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 977 978 context.enable(GL_BLEND); 979 context.blendEquation(GL_FUNC_ADD); 980 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); 981 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 982 context.disable(GL_BLEND); 983 984 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D) 985 { 986 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 987 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 988 context.viewport(0, 0, context.getWidth(), context.getHeight()); 989 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 990 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 991 } 992 else 993 context.readPixels(dst, 0, 0, width, height); 994 } 995 996 class StencilClearsTest : public FboRenderCase 997 { 998 public: 999 StencilClearsTest (Context& context, const FboConfig& config); 1000 virtual ~StencilClearsTest (void) {}; 1001 1002 void render (sglr::Context& context, Surface& dst); 1003 1004 static bool isConfigSupported (const FboConfig& config); 1005 }; 1006 1007 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config) 1008 : FboRenderCase(context, config.getName().c_str(), "Stencil clears", config) 1009 { 1010 } 1011 1012 void StencilClearsTest::render (sglr::Context& context, Surface& dst) 1013 { 1014 SingleTex2DShader shader; 1015 deUint32 shaderID = context.createProgram(&shader); 1016 int width = 128; 1017 int height = 128; 1018 deUint32 quadsTex = 1; 1019 deUint32 metaballsTex = 2; 1020 1021 createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height); 1022 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height); 1023 1024 Framebuffer fbo(context, getConfig(), width, height); 1025 fbo.checkCompleteness(); 1026 1027 // Bind framebuffer and clear 1028 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 1029 context.viewport(0, 0, width, height); 1030 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1031 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1032 1033 // Do stencil clears 1034 context.enable(GL_SCISSOR_TEST); 1035 context.scissor(10, 16, 32, 120); 1036 context.clearStencil(1); 1037 context.clear(GL_STENCIL_BUFFER_BIT); 1038 context.scissor(16, 32, 100, 64); 1039 context.clearStencil(2); 1040 context.clear(GL_STENCIL_BUFFER_BIT); 1041 context.disable(GL_SCISSOR_TEST); 1042 1043 // Draw 2 textures with stecil tests 1044 context.activeTexture(GL_TEXTURE0); 1045 context.bindTexture(GL_TEXTURE_2D, quadsTex); 1046 context.activeTexture(GL_TEXTURE1); 1047 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 1048 1049 context.enable(GL_STENCIL_TEST); 1050 context.stencilFunc(GL_EQUAL, 1, 0xffffffffu); 1051 shader.setUnit(context, shaderID, 0); 1052 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1053 1054 context.stencilFunc(GL_EQUAL, 2, 0xffffffffu); 1055 shader.setUnit(context, shaderID, 1); 1056 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1057 1058 context.disable(GL_STENCIL_TEST); 1059 1060 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D) 1061 { 1062 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1063 context.activeTexture(GL_TEXTURE0); 1064 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 1065 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1066 shader.setUnit(context, shaderID, 0); 1067 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1068 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1069 } 1070 else 1071 { 1072 // clear alpha channel for GL_RGB5_A1 format because test 1073 // thresholds for the alpha channel do not account for dithering 1074 if(getConfig().colorbufferFormat == GL_RGB5_A1) 1075 { 1076 context.colorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); 1077 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1078 context.clear(GL_COLOR_BUFFER_BIT); 1079 context.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 1080 } 1081 1082 context.readPixels(dst, 0, 0, width, height); 1083 } 1084 } 1085 1086 bool StencilClearsTest::isConfigSupported (const FboConfig& config) 1087 { 1088 return config.stencilbufferType != GL_NONE; 1089 } 1090 1091 class StencilTest : public FboRenderCase 1092 { 1093 public: 1094 StencilTest (Context& context, const FboConfig& config, bool npot = false); 1095 virtual ~StencilTest (void) {}; 1096 1097 void render (sglr::Context& context, Surface& dst); 1098 1099 static bool isConfigSupported (const FboConfig& config); 1100 1101 private: 1102 int m_fboWidth; 1103 int m_fboHeight; 1104 }; 1105 1106 class StencilNpotTest : public StencilTest 1107 { 1108 public: 1109 StencilNpotTest (Context& context, const FboConfig& config) 1110 : StencilTest(context, config, true) 1111 { 1112 } 1113 }; 1114 1115 StencilTest::StencilTest (Context& context, const FboConfig& config, bool npot) 1116 : FboRenderCase (context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config) 1117 , m_fboWidth (npot ? 99 : 128) 1118 , m_fboHeight (npot ? 110 : 128) 1119 { 1120 } 1121 1122 bool StencilTest::isConfigSupported (const FboConfig& config) 1123 { 1124 return config.stencilbufferType != GL_NONE; 1125 } 1126 1127 void StencilTest::render (sglr::Context& ctx, Surface& dst) 1128 { 1129 FlatColorShader colorShader; 1130 SingleTex2DShader texShader; 1131 deUint32 colorShaderID = ctx.createProgram(&colorShader); 1132 deUint32 texShaderID = ctx.createProgram(&texShader); 1133 int width = m_fboWidth; 1134 int height = m_fboHeight; 1135 int texWidth = 64; 1136 int texHeight = 64; 1137 deUint32 quadsTex = 1; 1138 deUint32 metaballsTex = 2; 1139 bool depth = getConfig().depthbufferType != GL_NONE; 1140 1141 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight); 1142 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight); 1143 1144 Framebuffer fbo(ctx, getConfig(), width, height); 1145 fbo.checkCompleteness(); 1146 1147 // Bind framebuffer and clear 1148 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 1149 ctx.viewport(0, 0, width, height); 1150 ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1151 ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1152 1153 // Render intersecting quads - increment stencil on depth pass 1154 ctx.enable(GL_DEPTH_TEST); 1155 ctx.enable(GL_STENCIL_TEST); 1156 ctx.stencilFunc(GL_ALWAYS, 0, 0xffu); 1157 ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR); 1158 1159 colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 1160 sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 1161 1162 ctx.bindTexture(GL_TEXTURE_2D, quadsTex); 1163 texShader.setUnit(ctx, texShaderID, 0); 1164 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f)); 1165 1166 // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure 1167 ctx.disable(GL_DEPTH_TEST); 1168 ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu); 1169 ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP); 1170 colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 1171 sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f)); 1172 1173 // Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer 1174 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex); 1175 ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu); 1176 ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 1177 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 1178 1179 ctx.disable(GL_STENCIL_TEST); 1180 1181 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D) 1182 { 1183 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0); 1184 ctx.activeTexture(GL_TEXTURE0); 1185 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 1186 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight()); 1187 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1188 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight()); 1189 } 1190 else 1191 ctx.readPixels(dst, 0, 0, width, height); 1192 } 1193 1194 class SharedColorbufferTest : public FboRenderCase 1195 { 1196 public: 1197 SharedColorbufferTest (Context& context, const FboConfig& config); 1198 virtual ~SharedColorbufferTest (void) {}; 1199 1200 void render (sglr::Context& context, Surface& dst); 1201 }; 1202 1203 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config) 1204 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config) 1205 { 1206 } 1207 1208 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst) 1209 { 1210 SingleTex2DShader shader; 1211 deUint32 shaderID = context.createProgram(&shader); 1212 int width = 128; 1213 int height = 128; 1214 // bool depth = getConfig().depthbufferFormat != GL_NONE; 1215 bool stencil = getConfig().stencilbufferFormat != GL_NONE; 1216 1217 // Textures 1218 deUint32 quadsTex = 1; 1219 deUint32 metaballsTex = 2; 1220 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 1221 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64); 1222 1223 context.viewport(0, 0, width, height); 1224 1225 shader.setUnit(context, shaderID, 0); 1226 1227 // Fbo A 1228 Framebuffer fboA(context, getConfig(), width, height); 1229 fboA.checkCompleteness(); 1230 1231 // Fbo B - don't create colorbuffer 1232 FboConfig cfg = getConfig(); 1233 cfg.colorbufferType = GL_NONE; 1234 cfg.colorbufferFormat = GL_NONE; 1235 Framebuffer fboB(context, cfg, width, height); 1236 1237 // Attach color buffer from fbo A 1238 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); 1239 switch (getConfig().colorbufferType) 1240 { 1241 case GL_TEXTURE_2D: 1242 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0); 1243 break; 1244 1245 case GL_RENDERBUFFER: 1246 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer()); 1247 break; 1248 1249 default: 1250 DE_ASSERT(false); 1251 } 1252 1253 // Clear depth and stencil in fbo B 1254 context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1255 1256 // Render quads to fbo 1, with depth 0.0 1257 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer()); 1258 context.bindTexture(GL_TEXTURE_2D, quadsTex); 1259 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1260 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1261 1262 if (stencil) 1263 { 1264 // Stencil to 1 in fbo A 1265 context.clearStencil(1); 1266 context.clear(GL_STENCIL_BUFFER_BIT); 1267 } 1268 1269 context.enable(GL_DEPTH_TEST); 1270 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1271 context.disable(GL_DEPTH_TEST); 1272 1273 // Blend metaballs to fbo 2 1274 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); 1275 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 1276 context.enable(GL_BLEND); 1277 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); 1278 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1279 1280 // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits 1281 context.bindTexture(GL_TEXTURE_2D, quadsTex); 1282 context.enable(GL_DEPTH_TEST); 1283 sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f)); 1284 context.disable(GL_DEPTH_TEST); 1285 1286 if (stencil) 1287 { 1288 FlatColorShader flatShader; 1289 deUint32 flatShaderID = context.createProgram(&flatShader); 1290 1291 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 1292 1293 // Clear subset of stencil buffer to 1 1294 context.enable(GL_SCISSOR_TEST); 1295 context.scissor(10, 10, 12, 25); 1296 context.clearStencil(1); 1297 context.clear(GL_STENCIL_BUFFER_BIT); 1298 context.disable(GL_SCISSOR_TEST); 1299 1300 // Render quad with stencil mask == 1 1301 context.enable(GL_STENCIL_TEST); 1302 context.stencilFunc(GL_EQUAL, 1, 0xffu); 1303 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1304 context.disable(GL_STENCIL_TEST); 1305 } 1306 1307 // Get results 1308 if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D) 1309 { 1310 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1311 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer()); 1312 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1313 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1314 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1315 } 1316 else 1317 context.readPixels(dst, 0, 0, width, height); 1318 } 1319 1320 class SharedColorbufferClearsTest : public FboRenderCase 1321 { 1322 public: 1323 SharedColorbufferClearsTest (Context& context, const FboConfig& config); 1324 virtual ~SharedColorbufferClearsTest (void) {} 1325 1326 static bool isConfigSupported (const FboConfig& config); 1327 void render (sglr::Context& context, Surface& dst); 1328 }; 1329 1330 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config) 1331 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config) 1332 { 1333 } 1334 1335 bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config) 1336 { 1337 return config.colorbufferType != GL_NONE && 1338 config.depthbufferType == GL_NONE && 1339 config.stencilbufferType == GL_NONE; 1340 } 1341 1342 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst) 1343 { 1344 int width = 128; 1345 int height = 128; 1346 deUint32 colorbuffer = 1; 1347 1348 checkColorFormatSupport(context, getConfig().colorbufferFormat); 1349 1350 // Single colorbuffer 1351 if (getConfig().colorbufferType == GL_TEXTURE_2D) 1352 { 1353 context.bindTexture(GL_TEXTURE_2D, colorbuffer); 1354 context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height); 1355 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1356 } 1357 else 1358 { 1359 DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER); 1360 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer); 1361 context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height); 1362 } 1363 1364 // Multiple framebuffers sharing the colorbuffer 1365 for (int fbo = 1; fbo <= 3; fbo++) 1366 { 1367 context.bindFramebuffer(GL_FRAMEBUFFER, fbo); 1368 1369 if (getConfig().colorbufferType == GL_TEXTURE_2D) 1370 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0); 1371 else 1372 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer); 1373 } 1374 1375 context.bindFramebuffer(GL_FRAMEBUFFER, 1); 1376 1377 // Check completeness 1378 { 1379 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER); 1380 if (status != GL_FRAMEBUFFER_COMPLETE) 1381 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__); 1382 } 1383 1384 // Render to them 1385 context.viewport(0, 0, width, height); 1386 context.clearColor(0.0f, 0.0f, 1.0f, 1.0f); 1387 context.clear(GL_COLOR_BUFFER_BIT); 1388 1389 context.enable(GL_SCISSOR_TEST); 1390 1391 context.bindFramebuffer(GL_FRAMEBUFFER, 2); 1392 context.clearColor(0.6f, 0.0f, 0.0f, 1.0f); 1393 context.scissor(10, 10, 64, 64); 1394 context.clear(GL_COLOR_BUFFER_BIT); 1395 context.clearColor(0.0f, 0.6f, 0.0f, 1.0f); 1396 context.scissor(60, 60, 40, 20); 1397 context.clear(GL_COLOR_BUFFER_BIT); 1398 1399 context.bindFramebuffer(GL_FRAMEBUFFER, 3); 1400 context.clearColor(0.0f, 0.0f, 0.6f, 1.0f); 1401 context.scissor(20, 20, 100, 10); 1402 context.clear(GL_COLOR_BUFFER_BIT); 1403 1404 context.bindFramebuffer(GL_FRAMEBUFFER, 1); 1405 context.clearColor(0.6f, 0.0f, 0.6f, 1.0f); 1406 context.scissor(20, 20, 5, 100); 1407 context.clear(GL_COLOR_BUFFER_BIT); 1408 1409 context.disable(GL_SCISSOR_TEST); 1410 1411 if (getConfig().colorbufferType == GL_TEXTURE_2D) 1412 { 1413 SingleTex2DShader shader; 1414 deUint32 shaderID = context.createProgram(&shader); 1415 1416 shader.setUnit(context, shaderID, 0); 1417 1418 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1419 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1420 sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f)); 1421 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1422 } 1423 else 1424 context.readPixels(dst, 0, 0, width, height); 1425 } 1426 1427 class SharedDepthbufferTest : public FboRenderCase 1428 { 1429 public: 1430 SharedDepthbufferTest (Context& context, const FboConfig& config); 1431 virtual ~SharedDepthbufferTest (void) {}; 1432 1433 static bool isConfigSupported (const FboConfig& config); 1434 void render (sglr::Context& context, Surface& dst); 1435 }; 1436 1437 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config) 1438 : FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config) 1439 { 1440 } 1441 1442 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config) 1443 { 1444 return config.depthbufferType == GL_RENDERBUFFER; 1445 } 1446 1447 void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst) 1448 { 1449 SingleTex2DShader texShader; 1450 FlatColorShader colorShader; 1451 deUint32 texShaderID = context.createProgram(&texShader); 1452 deUint32 colorShaderID = context.createProgram(&colorShader); 1453 int width = 128; 1454 int height = 128; 1455 bool stencil = getConfig().stencilbufferType != GL_NONE; 1456 1457 // Setup shaders 1458 texShader.setUnit(context, texShaderID, 0); 1459 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 1460 1461 // Textures 1462 deUint32 metaballsTex = 5; 1463 deUint32 quadsTex = 6; 1464 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 1465 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 1466 1467 context.viewport(0, 0, width, height); 1468 1469 // Fbo A 1470 Framebuffer fboA(context, getConfig(), width, height); 1471 fboA.checkCompleteness(); 1472 1473 // Fbo B 1474 FboConfig cfg = getConfig(); 1475 cfg.depthbufferType = GL_NONE; 1476 cfg.depthbufferFormat = GL_NONE; 1477 Framebuffer fboB(context, cfg, width, height); 1478 1479 // Bind depth buffer from fbo A to fbo B 1480 DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER); 1481 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); 1482 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer()); 1483 1484 // Clear fbo B color to red and stencil to 1 1485 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f); 1486 context.clearStencil(1); 1487 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1488 1489 // Enable depth test. 1490 context.enable(GL_DEPTH_TEST); 1491 1492 // Render quad to fbo A 1493 context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer()); 1494 context.bindTexture(GL_TEXTURE_2D, quadsTex); 1495 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1496 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1497 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1498 1499 // Render metaballs to fbo B 1500 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); 1501 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 1502 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); 1503 1504 context.disable(GL_DEPTH_TEST); 1505 1506 if (stencil) 1507 { 1508 // Clear subset of stencil buffer to 0 1509 context.enable(GL_SCISSOR_TEST); 1510 context.scissor(10, 10, 12, 25); 1511 context.clearStencil(0); 1512 context.clear(GL_STENCIL_BUFFER_BIT); 1513 context.disable(GL_SCISSOR_TEST); 1514 1515 // Render quad with stencil mask == 0 1516 context.enable(GL_STENCIL_TEST); 1517 context.stencilFunc(GL_EQUAL, 0, 0xffu); 1518 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1519 context.disable(GL_STENCIL_TEST); 1520 } 1521 1522 if (getConfig().colorbufferType == GL_TEXTURE_2D) 1523 { 1524 // Render both to screen 1525 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1526 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1527 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer()); 1528 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f)); 1529 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer()); 1530 sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1531 1532 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1533 } 1534 else 1535 { 1536 // Read results from fbo B 1537 context.readPixels(dst, 0, 0, width, height); 1538 } 1539 } 1540 1541 class TexSubImageAfterRenderTest : public FboRenderCase 1542 { 1543 public: 1544 TexSubImageAfterRenderTest (Context& context, const FboConfig& config); 1545 virtual ~TexSubImageAfterRenderTest (void) {} 1546 1547 static bool isConfigSupported (const FboConfig& config); 1548 void render (sglr::Context& context, Surface& dst); 1549 }; 1550 1551 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config) 1552 : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config) 1553 { 1554 } 1555 1556 bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config) 1557 { 1558 return config.colorbufferType == GL_TEXTURE_2D && 1559 (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) && 1560 config.depthbufferType == GL_NONE && 1561 config.stencilbufferType == GL_NONE; 1562 } 1563 1564 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst) 1565 { 1566 SingleTex2DShader shader; 1567 deUint32 shaderID = context.createProgram(&shader); 1568 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA; 1569 1570 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64); 1571 tcu::fillWithRGBAQuads(fourQuads.getAccess()); 1572 1573 tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64); 1574 tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3); 1575 1576 shader.setUnit(context, shaderID, 0); 1577 1578 deUint32 fourQuadsTex = 1; 1579 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); 1580 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1581 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr()); 1582 1583 context.bindFramebuffer(GL_FRAMEBUFFER, 1); 1584 1585 deUint32 fboTex = 2; 1586 context.bindTexture(GL_TEXTURE_2D, fboTex); 1587 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128); 1588 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1589 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0); 1590 1591 // Render to fbo 1592 context.viewport(0, 0, 128, 128); 1593 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); 1594 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1595 1596 // Update texture using TexSubImage2D 1597 context.bindTexture(GL_TEXTURE_2D, fboTex); 1598 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr()); 1599 1600 // Draw to screen 1601 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1602 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1603 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1604 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1605 } 1606 1607 class TexSubImageBetweenRenderTest : public FboRenderCase 1608 { 1609 public: 1610 TexSubImageBetweenRenderTest (Context& context, const FboConfig& config); 1611 virtual ~TexSubImageBetweenRenderTest (void) {} 1612 1613 static bool isConfigSupported (const FboConfig& config); 1614 void render (sglr::Context& context, Surface& dst); 1615 }; 1616 1617 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config) 1618 : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config) 1619 { 1620 } 1621 1622 bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config) 1623 { 1624 return config.colorbufferType == GL_TEXTURE_2D && 1625 (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) && 1626 config.depthbufferType == GL_NONE && 1627 config.stencilbufferType == GL_NONE; 1628 } 1629 1630 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst) 1631 { 1632 SingleTex2DShader shader; 1633 deUint32 shaderID = context.createProgram(&shader); 1634 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA; 1635 1636 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64); 1637 tcu::fillWithRGBAQuads(fourQuads.getAccess()); 1638 1639 tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64); 1640 tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3); 1641 1642 tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64); 1643 tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4); 1644 1645 deUint32 metaballsTex = 3; 1646 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 1647 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1648 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, metaballs2.getAccess().getDataPtr()); 1649 1650 deUint32 fourQuadsTex = 1; 1651 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); 1652 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1653 context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr()); 1654 1655 context.bindFramebuffer(GL_FRAMEBUFFER, 1); 1656 1657 deUint32 fboTex = 2; 1658 context.bindTexture(GL_TEXTURE_2D, fboTex); 1659 context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128); 1660 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1661 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0); 1662 1663 shader.setUnit(context, shaderID, 0); 1664 1665 // Render to fbo 1666 context.viewport(0, 0, 128, 128); 1667 context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); 1668 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1669 1670 // Update texture using TexSubImage2D 1671 context.bindTexture(GL_TEXTURE_2D, fboTex); 1672 context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr()); 1673 1674 // Render again to fbo 1675 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 1676 context.enable(GL_BLEND); 1677 context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); 1678 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1679 context.disable(GL_BLEND); 1680 1681 // Draw to screen 1682 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1683 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1684 context.bindTexture(GL_TEXTURE_2D, fboTex); 1685 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1686 1687 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1688 } 1689 1690 class ResizeTest : public FboRenderCase 1691 { 1692 public: 1693 ResizeTest (Context& context, const FboConfig& config); 1694 virtual ~ResizeTest (void) {} 1695 1696 void render (sglr::Context& context, Surface& dst); 1697 }; 1698 1699 ResizeTest::ResizeTest (Context& context, const FboConfig& config) 1700 : FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config) 1701 { 1702 } 1703 1704 void ResizeTest::render (sglr::Context& context, Surface& dst) 1705 { 1706 SingleTex2DShader texShader; 1707 FlatColorShader colorShader; 1708 deUint32 texShaderID = context.createProgram(&texShader); 1709 deUint32 colorShaderID = context.createProgram(&colorShader); 1710 deUint32 quadsTex = 1; 1711 deUint32 metaballsTex = 2; 1712 bool depth = getConfig().depthbufferType != GL_NONE; 1713 bool stencil = getConfig().stencilbufferType != GL_NONE; 1714 1715 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 1716 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32); 1717 1718 Framebuffer fbo(context, getConfig(), 128, 128); 1719 fbo.checkCompleteness(); 1720 1721 // Setup shaders 1722 texShader.setUnit(context, texShaderID, 0); 1723 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 1724 1725 // Render quads 1726 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 1727 context.viewport(0, 0, 128, 128); 1728 context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1729 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1730 context.bindTexture(GL_TEXTURE_2D, quadsTex); 1731 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1732 1733 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D) 1734 { 1735 // Render fbo to screen 1736 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1737 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1738 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 1739 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1740 1741 // Restore binding 1742 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 1743 } 1744 1745 int newWidth = 64; 1746 int newHeight = 32; 1747 1748 // Resize buffers 1749 switch (fbo.getConfig().colorbufferType) 1750 { 1751 case GL_TEXTURE_2D: 1752 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 1753 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight); 1754 break; 1755 1756 case GL_RENDERBUFFER: 1757 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer()); 1758 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight); 1759 break; 1760 1761 default: 1762 DE_ASSERT(false); 1763 } 1764 1765 if (depth) 1766 { 1767 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER); 1768 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer()); 1769 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight); 1770 } 1771 1772 if (stencil) 1773 { 1774 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER); 1775 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer()); 1776 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight); 1777 } 1778 1779 // Render to resized fbo 1780 context.viewport(0, 0, newWidth, newHeight); 1781 context.clearColor(1.0f, 0.0f, 0.0f, 1.0f); 1782 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1783 1784 context.enable(GL_DEPTH_TEST); 1785 1786 context.bindTexture(GL_TEXTURE_2D, metaballsTex); 1787 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 1788 1789 context.bindTexture(GL_TEXTURE_2D, quadsTex); 1790 sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f)); 1791 1792 context.disable(GL_DEPTH_TEST); 1793 1794 if (stencil) 1795 { 1796 context.enable(GL_SCISSOR_TEST); 1797 context.scissor(10, 10, 5, 15); 1798 context.clearStencil(1); 1799 context.clear(GL_STENCIL_BUFFER_BIT); 1800 context.disable(GL_SCISSOR_TEST); 1801 1802 context.enable(GL_STENCIL_TEST); 1803 context.stencilFunc(GL_EQUAL, 1, 0xffu); 1804 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); 1805 context.disable(GL_STENCIL_TEST); 1806 } 1807 1808 if (getConfig().colorbufferType == GL_TEXTURE_2D) 1809 { 1810 context.bindFramebuffer(GL_FRAMEBUFFER, 0); 1811 context.viewport(0, 0, context.getWidth(), context.getHeight()); 1812 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer()); 1813 sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f)); 1814 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); 1815 } 1816 else 1817 context.readPixels(dst, 0, 0, newWidth, newHeight); 1818 } 1819 1820 template <GLenum Buffers> 1821 class RecreateBuffersTest : public FboRenderCase 1822 { 1823 public: 1824 RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind); 1825 virtual ~RecreateBuffersTest (void) {} 1826 1827 static bool isConfigSupported (const FboConfig& config); 1828 void render (sglr::Context& context, Surface& dst); 1829 1830 private: 1831 bool m_rebind; 1832 }; 1833 1834 template <GLenum Buffers> 1835 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers> 1836 { 1837 public: 1838 RecreateBuffersNoRebindTest (Context& context, const FboConfig& config) 1839 : RecreateBuffersTest<Buffers>(context, config, false) 1840 { 1841 } 1842 }; 1843 1844 template <GLenum Buffers> 1845 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers> 1846 { 1847 public: 1848 RecreateBuffersRebindTest (Context& context, const FboConfig& config) 1849 : RecreateBuffersTest<Buffers>(context, config, true) 1850 { 1851 } 1852 }; 1853 1854 template <GLenum Buffers> 1855 RecreateBuffersTest<Buffers>::RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind) 1856 : FboRenderCase (context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers", config) 1857 , m_rebind (rebind) 1858 { 1859 } 1860 1861 template <GLenum Buffers> 1862 bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config) 1863 { 1864 if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE) 1865 return false; 1866 if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE) 1867 return false; 1868 if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE) 1869 return false; 1870 return true; 1871 } 1872 1873 template <GLenum Buffers> 1874 void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst) 1875 { 1876 SingleTex2DShader texShader; 1877 deUint32 texShaderID = ctx.createProgram(&texShader); 1878 int width = 128; 1879 int height = 128; 1880 deUint32 metaballsTex = 1; 1881 deUint32 quadsTex = 2; 1882 bool stencil = getConfig().stencilbufferType != GL_NONE; 1883 1884 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 1885 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); 1886 1887 Framebuffer fbo(ctx, getConfig(), width, height); 1888 fbo.checkCompleteness(); 1889 1890 // Setup shader 1891 texShader.setUnit(ctx, texShaderID, 0); 1892 1893 // Draw scene 1894 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 1895 ctx.viewport(0, 0, width, height); 1896 ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f); 1897 ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1898 1899 ctx.enable(GL_DEPTH_TEST); 1900 1901 ctx.bindTexture(GL_TEXTURE_2D, quadsTex); 1902 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 1903 1904 if (stencil) 1905 { 1906 ctx.enable(GL_SCISSOR_TEST); 1907 ctx.scissor(width/4, height/4, width/2, height/2); 1908 ctx.clearStencil(1); 1909 ctx.clear(GL_STENCIL_BUFFER_BIT); 1910 ctx.disable(GL_SCISSOR_TEST); 1911 } 1912 1913 // Recreate buffers 1914 if (!m_rebind) 1915 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0); 1916 1917 if (Buffers & GL_COLOR_BUFFER_BIT) 1918 { 1919 deUint32 colorbuf = fbo.getColorbuffer(); 1920 switch (fbo.getConfig().colorbufferType) 1921 { 1922 case GL_TEXTURE_2D: 1923 ctx.deleteTextures(1, &colorbuf); 1924 ctx.bindTexture(GL_TEXTURE_2D, colorbuf); 1925 ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height); 1926 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1927 1928 if (m_rebind) 1929 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0); 1930 break; 1931 1932 case GL_RENDERBUFFER: 1933 ctx.deleteRenderbuffers(1, &colorbuf); 1934 ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf); 1935 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height); 1936 1937 if (m_rebind) 1938 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf); 1939 break; 1940 1941 default: 1942 DE_ASSERT(false); 1943 } 1944 } 1945 1946 if (Buffers & GL_DEPTH_BUFFER_BIT) 1947 { 1948 deUint32 depthbuf = fbo.getDepthbuffer(); 1949 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER); 1950 1951 ctx.deleteRenderbuffers(1, &depthbuf); 1952 ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf); 1953 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height); 1954 1955 if (m_rebind) 1956 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf); 1957 } 1958 1959 if (Buffers & GL_STENCIL_BUFFER_BIT) 1960 { 1961 deUint32 stencilbuf = fbo.getStencilbuffer(); 1962 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER); 1963 1964 ctx.deleteRenderbuffers(1, &stencilbuf); 1965 ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf); 1966 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height); 1967 1968 if (m_rebind) 1969 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf); 1970 } 1971 1972 if (!m_rebind) 1973 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); 1974 1975 ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f); 1976 ctx.clearStencil(0); 1977 ctx.clear(Buffers); // \note Clear only buffers that were re-created 1978 1979 if (stencil) 1980 { 1981 // \note Stencil test enabled only if we have stencil buffer 1982 ctx.enable(GL_STENCIL_TEST); 1983 ctx.stencilFunc(GL_EQUAL, 0, 0xffu); 1984 } 1985 ctx.bindTexture(GL_TEXTURE_2D, metaballsTex); 1986 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f)); 1987 if (stencil) 1988 ctx.disable(GL_STENCIL_TEST); 1989 1990 ctx.disable(GL_DEPTH_TEST); 1991 1992 // Read from fbo 1993 ctx.readPixels(dst, 0, 0, width, height); 1994 } 1995 1996 class RepeatedClearCase : public FboRenderCase 1997 { 1998 private: 1999 static FboConfig makeConfig (deUint32 format) 2000 { 2001 FboConfig cfg; 2002 cfg.colorbufferType = GL_TEXTURE_2D; 2003 cfg.colorbufferFormat = format; 2004 cfg.depthbufferType = GL_NONE; 2005 cfg.stencilbufferType = GL_NONE; 2006 return cfg; 2007 } 2008 2009 public: 2010 RepeatedClearCase (Context& context, deUint32 format) 2011 : FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format)) 2012 { 2013 } 2014 2015 protected: 2016 void render (sglr::Context& ctx, Surface& dst) 2017 { 2018 const int numRowsCols = 4; 2019 const int cellSize = 16; 2020 const int fboSizes[] = { cellSize, cellSize*numRowsCols }; 2021 2022 SingleTex2DShader fboBlitShader; 2023 const deUint32 fboBlitShaderID = ctx.createProgram(&fboBlitShader); 2024 2025 de::Random rnd (18169662); 2026 deUint32 fbos[] = { 0, 0 }; 2027 deUint32 textures[] = { 0, 0 }; 2028 2029 ctx.genFramebuffers(2, &fbos[0]); 2030 ctx.genTextures(2, &textures[0]); 2031 2032 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++) 2033 { 2034 ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]); 2035 ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0, 2036 getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, DE_NULL); 2037 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 2038 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 2039 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2040 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2041 2042 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]); 2043 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0); 2044 2045 { 2046 const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER); 2047 if (status != GL_FRAMEBUFFER_COMPLETE) 2048 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__); 2049 } 2050 } 2051 2052 // larger fbo bound -- clear to transparent black 2053 ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 2054 ctx.clear(GL_COLOR_BUFFER_BIT); 2055 2056 fboBlitShader.setUnit(ctx, fboBlitShaderID, 0); 2057 ctx.bindTexture(GL_TEXTURE_2D, textures[0]); 2058 2059 for (int cellY = 0; cellY < numRowsCols; cellY++) 2060 for (int cellX = 0; cellX < numRowsCols; cellX++) 2061 { 2062 const float r = rnd.getFloat(); 2063 const float g = rnd.getFloat(); 2064 const float b = rnd.getFloat(); 2065 const float a = rnd.getFloat(); 2066 2067 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]); 2068 ctx.clearColor(r, g, b, a); 2069 ctx.clear(GL_COLOR_BUFFER_BIT); 2070 2071 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]); 2072 ctx.viewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize); 2073 sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 2074 } 2075 2076 ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]); 2077 } 2078 }; 2079 2080 } // FboCases 2081 2082 FboRenderTestGroup::FboRenderTestGroup (Context& context) 2083 : TestCaseGroup(context, "render", "Rendering Tests") 2084 { 2085 } 2086 2087 FboRenderTestGroup::~FboRenderTestGroup (void) 2088 { 2089 } 2090 2091 namespace 2092 { 2093 2094 struct TypeFormatPair 2095 { 2096 GLenum type; 2097 GLenum format; 2098 }; 2099 2100 template <typename CaseType> 2101 void addChildVariants (deqp::gles2::TestCaseGroup* group) 2102 { 2103 TypeFormatPair colorbufferConfigs[] = 2104 { 2105 // { GL_TEXTURE_2D, GL_ALPHA }, 2106 // { GL_TEXTURE_2D, GL_LUMINANCE }, 2107 // { GL_TEXTURE_2D, GL_LUMINANCE_ALPHA }, 2108 { GL_TEXTURE_2D, GL_RGB }, 2109 { GL_TEXTURE_2D, GL_RGBA }, 2110 { GL_RENDERBUFFER, GL_RGB565 }, 2111 { GL_RENDERBUFFER, GL_RGB5_A1 }, 2112 { GL_RENDERBUFFER, GL_RGBA4 }, 2113 // { GL_RENDERBUFFER, GL_RGBA16F }, 2114 // { GL_RENDERBUFFER, GL_RGB16F } 2115 }; 2116 TypeFormatPair depthbufferConfigs[] = 2117 { 2118 { GL_NONE, GL_NONE }, 2119 { GL_RENDERBUFFER, GL_DEPTH_COMPONENT16 } 2120 }; 2121 TypeFormatPair stencilbufferConfigs[] = 2122 { 2123 { GL_NONE, GL_NONE }, 2124 { GL_RENDERBUFFER, GL_STENCIL_INDEX8 } 2125 }; 2126 2127 for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++) 2128 for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++) 2129 for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs); stencilbufferNdx++) 2130 { 2131 FboConfig config; 2132 config.colorbufferType = colorbufferConfigs[colorbufferNdx].type; 2133 config.colorbufferFormat = colorbufferConfigs[colorbufferNdx].format; 2134 config.depthbufferType = depthbufferConfigs[depthbufferNdx].type; 2135 config.depthbufferFormat = depthbufferConfigs[depthbufferNdx].format; 2136 config.stencilbufferType = stencilbufferConfigs[stencilbufferNdx].type; 2137 config.stencilbufferFormat = stencilbufferConfigs[stencilbufferNdx].format; 2138 2139 if (CaseType::isConfigSupported(config)) 2140 group->addChild(new CaseType(group->getContext(), config)); 2141 } 2142 } 2143 2144 template <typename CaseType> 2145 void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description) 2146 { 2147 deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description); 2148 parent->addChild(tmpGroup); 2149 addChildVariants<CaseType>(tmpGroup); 2150 } 2151 2152 template <GLbitfield Buffers> 2153 void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description) 2154 { 2155 deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description); 2156 parent->addChild(tmpGroup); 2157 addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers> > (tmpGroup); 2158 addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers> > (tmpGroup); 2159 } 2160 2161 } // anonymous 2162 2163 void FboRenderTestGroup::init (void) 2164 { 2165 createChildGroup<FboCases::ColorClearsTest> (this, "color_clear", "Color buffer clears"); 2166 createChildGroup<FboCases::StencilClearsTest> (this, "stencil_clear", "Stencil buffer clears"); 2167 2168 deqp::gles2::TestCaseGroup* colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests"); 2169 addChild(colorGroup); 2170 addChildVariants<FboCases::MixTest> (colorGroup); 2171 addChildVariants<FboCases::MixNpotTest> (colorGroup); 2172 addChildVariants<FboCases::BlendTest> (colorGroup); 2173 addChildVariants<FboCases::BlendNpotTest> (colorGroup); 2174 2175 deqp::gles2::TestCaseGroup* depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests"); 2176 addChild(depthGroup); 2177 addChildVariants<FboCases::IntersectingQuadsTest> (depthGroup); 2178 addChildVariants<FboCases::IntersectingQuadsNpotTest> (depthGroup); 2179 2180 deqp::gles2::TestCaseGroup* stencilGroup = new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests"); 2181 addChild(stencilGroup); 2182 addChildVariants<FboCases::StencilTest> (stencilGroup); 2183 addChildVariants<FboCases::StencilNpotTest> (stencilGroup); 2184 2185 createChildGroup<FboCases::SharedColorbufferClearsTest> (this, "shared_colorbuffer_clear", "Shared colorbuffer clears"); 2186 createChildGroup<FboCases::SharedColorbufferTest> (this, "shared_colorbuffer", "Shared colorbuffer tests"); 2187 createChildGroup<FboCases::SharedDepthbufferTest> (this, "shared_depthbuffer", "Shared depthbuffer tests"); 2188 createChildGroup<FboCases::ResizeTest> (this, "resize", "FBO resize tests"); 2189 2190 createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT> (this, "recreate_colorbuffer", "Recreate colorbuffer tests"); 2191 createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT> (this, "recreate_depthbuffer", "Recreate depthbuffer tests"); 2192 createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT> (this, "recreate_stencilbuffer", "Recreate stencilbuffer tests"); 2193 2194 deqp::gles2::TestCaseGroup* texSubImageGroup = new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture"); 2195 addChild(texSubImageGroup); 2196 addChildVariants<FboCases::TexSubImageAfterRenderTest> (texSubImageGroup); 2197 addChildVariants<FboCases::TexSubImageBetweenRenderTest> (texSubImageGroup); 2198 2199 { 2200 tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears"); 2201 addChild(repeatedClearGroup); 2202 2203 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB)); 2204 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA)); 2205 } 2206 } 2207 2208 } // Functional 2209 } // gles2 2210 } // deqp 2211