1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.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 FBO stencilbuffer tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es3fFramebufferBlitTests.hpp" 25#include "es3fFboTestCase.hpp" 26#include "es3fFboTestUtil.hpp" 27#include "gluTextureUtil.hpp" 28#include "gluContextInfo.hpp" 29#include "tcuTextureUtil.hpp" 30#include "tcuVectorUtil.hpp" 31#include "tcuTestLog.hpp" 32#include "tcuImageCompare.hpp" 33#include "tcuRenderTarget.hpp" 34#include "sglrContextUtil.hpp" 35#include "glwEnums.hpp" 36#include "deStringUtil.hpp" 37 38namespace deqp 39{ 40namespace gles3 41{ 42namespace Functional 43{ 44 45using std::string; 46using tcu::TestLog; 47using tcu::Vec2; 48using tcu::Vec3; 49using tcu::Vec4; 50using tcu::IVec2; 51using tcu::IVec3; 52using tcu::IVec4; 53using tcu::UVec4; 54using namespace FboTestUtil; 55 56class BlitRectCase : public FboTestCase 57{ 58public: 59 BlitRectCase (Context& context, const char* name, const char* desc, deUint32 filter, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect, int cellSize = 8) 60 : FboTestCase (context, name, desc) 61 , m_filter (filter) 62 , m_srcSize (srcSize) 63 , m_srcRect (srcRect) 64 , m_dstSize (dstSize) 65 , m_dstRect (dstRect) 66 , m_cellSize (cellSize) 67 , m_gridCellColorA (0.2f, 0.7f, 0.1f, 1.0f) 68 , m_gridCellColorB (0.7f, 0.1f, 0.5f, 0.8f) 69 { 70 } 71 72 void render (tcu::Surface& dst) 73 { 74 const deUint32 colorFormat = GL_RGBA8; 75 76 GradientShader gradShader (glu::TYPE_FLOAT_VEC4); 77 Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); 78 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); 79 deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); 80 81 deUint32 srcFbo = 0; 82 deUint32 dstFbo = 0; 83 deUint32 srcRbo = 0; 84 deUint32 dstRbo = 0; 85 86 // Setup shaders 87 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); 88 texShader.setUniforms(*getCurrentContext(), texShaderID); 89 90 // Create framebuffers. 91 for (int ndx = 0; ndx < 2; ndx++) 92 { 93 deUint32& fbo = ndx ? dstFbo : srcFbo; 94 deUint32& rbo = ndx ? dstRbo : srcRbo; 95 const IVec2& size = ndx ? m_dstSize : m_srcSize; 96 97 glGenFramebuffers(1, &fbo); 98 glGenRenderbuffers(1, &rbo); 99 100 glBindRenderbuffer(GL_RENDERBUFFER, rbo); 101 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, size.x(), size.y()); 102 103 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 104 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); 105 checkError(); 106 checkFramebufferStatus(GL_FRAMEBUFFER); 107 } 108 109 // Fill destination with gradient. 110 glBindFramebuffer(GL_FRAMEBUFFER, dstFbo); 111 glViewport(0, 0, m_dstSize.x(), m_dstSize.y()); 112 113 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 114 115 // Fill source with grid pattern. 116 { 117 const deUint32 format = GL_RGBA; 118 const deUint32 dataType = GL_UNSIGNED_BYTE; 119 const int texW = m_srcSize.x(); 120 const int texH = m_srcSize.y(); 121 deUint32 gridTex = 0; 122 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); 123 124 tcu::fillWithGrid(data.getAccess(), m_cellSize, m_gridCellColorA, m_gridCellColorB); 125 126 glGenTextures(1, &gridTex); 127 glBindTexture(GL_TEXTURE_2D, gridTex); 128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 132 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); 133 134 glBindFramebuffer(GL_FRAMEBUFFER, srcFbo); 135 glViewport(0, 0, m_srcSize.x(), m_srcSize.y()); 136 sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 137 } 138 139 // Perform copy. 140 glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo); 141 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo); 142 glBlitFramebuffer(m_srcRect.x(), m_srcRect.y(), m_srcRect.z(), m_srcRect.w(), m_dstRect.x(), m_dstRect.y(), m_dstRect.z(), m_dstRect.w(), GL_COLOR_BUFFER_BIT, m_filter); 143 144 // Read back results. 145 glBindFramebuffer(GL_READ_FRAMEBUFFER, dstFbo); 146 readPixels(dst, 0, 0, m_dstSize.x(), m_dstSize.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); 147 } 148 149 virtual bool compare (const tcu::Surface& reference, const tcu::Surface& result) 150 { 151 // Use pixel-threshold compare for rect cases since 1px off will mean failure. 152 tcu::RGBA threshold = TestCase::m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7); 153 return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, tcu::COMPARE_LOG_RESULT); 154 } 155 156protected: 157 const deUint32 m_filter; 158 const IVec2 m_srcSize; 159 const IVec4 m_srcRect; 160 const IVec2 m_dstSize; 161 const IVec4 m_dstRect; 162 const int m_cellSize; 163 const Vec4 m_gridCellColorA; 164 const Vec4 m_gridCellColorB; 165}; 166 167class BlitNearestFilterConsistencyCase : public BlitRectCase 168{ 169public: 170 BlitNearestFilterConsistencyCase (Context& context, const char* name, const char* desc, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect); 171 172 bool compare (const tcu::Surface& reference, const tcu::Surface& result); 173}; 174 175BlitNearestFilterConsistencyCase::BlitNearestFilterConsistencyCase (Context& context, const char* name, const char* desc, const IVec2& srcSize, const IVec4& srcRect, const IVec2& dstSize, const IVec4& dstRect) 176 : BlitRectCase(context, name, desc, GL_NEAREST, srcSize, srcRect, dstSize, dstRect, 1) 177{ 178} 179 180bool BlitNearestFilterConsistencyCase::compare (const tcu::Surface& reference, const tcu::Surface& result) 181{ 182 DE_ASSERT(reference.getWidth() == result.getWidth()); 183 DE_ASSERT(reference.getHeight() == result.getHeight()); 184 DE_UNREF(reference); 185 186 // Image origin must be visible (for baseColor) 187 DE_ASSERT(de::min(m_dstRect.x(), m_dstRect.z()) >= 0); 188 DE_ASSERT(de::min(m_dstRect.y(), m_dstRect.w()) >= 0); 189 190 const tcu::RGBA cellColorA (m_gridCellColorA); 191 const tcu::RGBA cellColorB (m_gridCellColorB); 192 const tcu::RGBA threshold = TestCase::m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7); 193 const tcu::IVec4 destinationArea = tcu::IVec4(de::clamp(de::min(m_dstRect.x(), m_dstRect.z()), 0, result.getWidth()), 194 de::clamp(de::min(m_dstRect.y(), m_dstRect.w()), 0, result.getHeight()), 195 de::clamp(de::max(m_dstRect.x(), m_dstRect.z()), 0, result.getWidth()), 196 de::clamp(de::max(m_dstRect.y(), m_dstRect.w()), 0, result.getHeight())); 197 const tcu::RGBA baseColor = result.getPixel(destinationArea.x(), destinationArea.y()); 198 const bool signConfig = tcu::compareThreshold(baseColor, cellColorA, threshold); 199 200 bool error = false; 201 tcu::Surface errorMask (result.getWidth(), result.getHeight()); 202 std::vector<bool> horisontalSign (destinationArea.z() - destinationArea.x()); 203 std::vector<bool> verticalSign (destinationArea.w() - destinationArea.y()); 204 205 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 206 207 // Checking only area in our destination rect 208 209 m_testCtx.getLog() 210 << tcu::TestLog::Message 211 << "Verifying consistency of NEAREST filtering. Verifying rect " << m_dstRect << ".\n" 212 << "Rounding direction of the NEAREST filter at the horisontal texel edge (x = n + 0.5) should not depend on the y-coordinate.\n" 213 << "Rounding direction of the NEAREST filter at the vertical texel edge (y = n + 0.5) should not depend on the x-coordinate.\n" 214 << "Blitting a grid (with uniform sized cells) should result in a grid (with non-uniform sized cells)." 215 << tcu::TestLog::EndMessage; 216 217 // Verify that destination only contains valid colors 218 219 for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy) 220 for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx) 221 { 222 const tcu::RGBA color = result.getPixel(destinationArea.x() + dx, destinationArea.y() + dy); 223 const bool isValidColor = tcu::compareThreshold(color, cellColorA, threshold) || tcu::compareThreshold(color, cellColorB, threshold); 224 225 if (!isValidColor) 226 { 227 errorMask.setPixel(destinationArea.x() + dx, destinationArea.y() + dy, tcu::RGBA::red()); 228 error = true; 229 } 230 } 231 if (error) 232 { 233 m_testCtx.getLog() 234 << tcu::TestLog::Message 235 << "Image verification failed, destination rect contains unexpected values. " 236 << "Expected either " << cellColorA << " or " << cellColorB << "." 237 << tcu::TestLog::EndMessage 238 << tcu::TestLog::ImageSet("Result", "Image verification result") 239 << tcu::TestLog::Image("Result", "Result", result) 240 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask) 241 << tcu::TestLog::EndImageSet; 242 return false; 243 } 244 245 // Detect result edges by reading the first row and first column of the blitted area. 246 // Blitting a grid should result in a grid-like image. ("sign changes" should be consistent) 247 248 for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx) 249 { 250 const tcu::RGBA color = result.getPixel(destinationArea.x() + dx, destinationArea.y()); 251 252 if (tcu::compareThreshold(color, cellColorA, threshold)) 253 horisontalSign[dx] = true; 254 else if (tcu::compareThreshold(color, cellColorB, threshold)) 255 horisontalSign[dx] = false; 256 else 257 DE_ASSERT(DE_FALSE); 258 } 259 for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy) 260 { 261 const tcu::RGBA color = result.getPixel(destinationArea.x(), destinationArea.y() + dy); 262 263 if (tcu::compareThreshold(color, cellColorA, threshold)) 264 verticalSign[dy] = true; 265 else if (tcu::compareThreshold(color, cellColorB, threshold)) 266 verticalSign[dy] = false; 267 else 268 DE_ASSERT(DE_FALSE); 269 } 270 271 // Verify grid-like image 272 273 for (int dy = 0; dy < destinationArea.w() - destinationArea.y(); ++dy) 274 for (int dx = 0; dx < destinationArea.z() - destinationArea.x(); ++dx) 275 { 276 const tcu::RGBA color = result.getPixel(destinationArea.x() + dx, destinationArea.y() + dy); 277 const bool resultSign = tcu::compareThreshold(cellColorA, color, threshold); 278 const bool correctSign = (horisontalSign[dx] == verticalSign[dy]) == signConfig; 279 280 if (resultSign != correctSign) 281 { 282 errorMask.setPixel(destinationArea.x() + dx, destinationArea.y() + dy, tcu::RGBA::red()); 283 error = true; 284 } 285 } 286 287 // Report result 288 289 if (error) 290 { 291 m_testCtx.getLog() 292 << tcu::TestLog::Message 293 << "Image verification failed, nearest filter is not consistent." 294 << tcu::TestLog::EndMessage 295 << tcu::TestLog::ImageSet("Result", "Image verification result") 296 << tcu::TestLog::Image("Result", "Result", result) 297 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask) 298 << tcu::TestLog::EndImageSet; 299 } 300 else 301 { 302 m_testCtx.getLog() 303 << tcu::TestLog::Message 304 << "Image verification passed." 305 << tcu::TestLog::EndMessage 306 << tcu::TestLog::ImageSet("Result", "Image verification result") 307 << tcu::TestLog::Image("Result", "Result", result) 308 << tcu::TestLog::EndImageSet; 309 } 310 311 return !error; 312} 313 314static tcu::BVec4 getChannelMask (tcu::TextureFormat::ChannelOrder order) 315{ 316 switch (order) 317 { 318 case tcu::TextureFormat::R: return tcu::BVec4(true, false, false, false); 319 case tcu::TextureFormat::RG: return tcu::BVec4(true, true, false, false); 320 case tcu::TextureFormat::RGB: return tcu::BVec4(true, true, true, false); 321 case tcu::TextureFormat::RGBA: return tcu::BVec4(true, true, true, true); 322 case tcu::TextureFormat::sRGB: return tcu::BVec4(true, true, true, false); 323 case tcu::TextureFormat::sRGBA: return tcu::BVec4(true, true, true, true); 324 default: 325 DE_ASSERT(false); 326 return tcu::BVec4(false); 327 } 328} 329 330class BlitColorConversionCase : public FboTestCase 331{ 332public: 333 BlitColorConversionCase (Context& context, const char* name, const char* desc, deUint32 srcFormat, deUint32 dstFormat, const IVec2& size) 334 : FboTestCase (context, name, desc) 335 , m_srcFormat (srcFormat) 336 , m_dstFormat (dstFormat) 337 , m_size (size) 338 { 339 } 340 341protected: 342 void preCheck (void) 343 { 344 checkFormatSupport(m_srcFormat); 345 checkFormatSupport(m_dstFormat); 346 } 347 348 void render (tcu::Surface& dst) 349 { 350 tcu::TextureFormat srcFormat = glu::mapGLInternalFormat(m_srcFormat); 351 tcu::TextureFormat dstFormat = glu::mapGLInternalFormat(m_dstFormat); 352 glu::DataType srcOutputType = getFragmentOutputType(srcFormat); 353 glu::DataType dstOutputType = getFragmentOutputType(dstFormat); 354 355 // Compute ranges \note Doesn't handle case where src or dest is not subset of the another! 356 tcu::TextureFormatInfo srcFmtRangeInfo = tcu::getTextureFormatInfo(srcFormat); 357 tcu::TextureFormatInfo dstFmtRangeInfo = tcu::getTextureFormatInfo(dstFormat); 358 tcu::BVec4 copyMask = tcu::logicalAnd(getChannelMask(srcFormat.order), getChannelMask(dstFormat.order)); 359 tcu::BVec4 srcIsGreater = tcu::greaterThan(srcFmtRangeInfo.valueMax-srcFmtRangeInfo.valueMin, dstFmtRangeInfo.valueMax-dstFmtRangeInfo.valueMin); 360 tcu::TextureFormatInfo srcRangeInfo (tcu::select(dstFmtRangeInfo.valueMin, srcFmtRangeInfo.valueMin, tcu::logicalAnd(copyMask, srcIsGreater)), 361 tcu::select(dstFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMax, tcu::logicalAnd(copyMask, srcIsGreater)), 362 tcu::select(dstFmtRangeInfo.lookupScale, srcFmtRangeInfo.lookupScale, tcu::logicalAnd(copyMask, srcIsGreater)), 363 tcu::select(dstFmtRangeInfo.lookupBias, srcFmtRangeInfo.lookupBias, tcu::logicalAnd(copyMask, srcIsGreater))); 364 tcu::TextureFormatInfo dstRangeInfo (tcu::select(dstFmtRangeInfo.valueMin, srcFmtRangeInfo.valueMin, tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)), 365 tcu::select(dstFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMax, tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)), 366 tcu::select(dstFmtRangeInfo.lookupScale, srcFmtRangeInfo.lookupScale, tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater)), 367 tcu::select(dstFmtRangeInfo.lookupBias, srcFmtRangeInfo.lookupBias, tcu::logicalOr(tcu::logicalNot(copyMask), srcIsGreater))); 368 369 // Shaders. 370 GradientShader gradientToSrcShader (srcOutputType); 371 GradientShader gradientToDstShader (dstOutputType); 372 373 deUint32 gradShaderSrcID = getCurrentContext()->createProgram(&gradientToSrcShader); 374 deUint32 gradShaderDstID = getCurrentContext()->createProgram(&gradientToDstShader); 375 376 deUint32 srcFbo, dstFbo; 377 deUint32 srcRbo, dstRbo; 378 379 // Create framebuffers. 380 for (int ndx = 0; ndx < 2; ndx++) 381 { 382 deUint32& fbo = ndx ? dstFbo : srcFbo; 383 deUint32& rbo = ndx ? dstRbo : srcRbo; 384 deUint32 format = ndx ? m_dstFormat : m_srcFormat; 385 386 glGenFramebuffers(1, &fbo); 387 glGenRenderbuffers(1, &rbo); 388 389 glBindRenderbuffer(GL_RENDERBUFFER, rbo); 390 glRenderbufferStorage(GL_RENDERBUFFER, format, m_size.x(), m_size.y()); 391 392 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 393 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); 394 checkError(); 395 checkFramebufferStatus(GL_FRAMEBUFFER); 396 } 397 398 glViewport(0, 0, m_size.x(), m_size.y()); 399 400 // Render gradients. 401 for (int ndx = 0; ndx < 2; ndx++) 402 { 403 glBindFramebuffer(GL_FRAMEBUFFER, ndx ? dstFbo : srcFbo); 404 405 if (ndx) 406 { 407 gradientToDstShader.setGradient(*getCurrentContext(), gradShaderDstID, dstRangeInfo.valueMax, dstRangeInfo.valueMin); 408 sglr::drawQuad(*getCurrentContext(), gradShaderDstID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 409 } 410 else 411 { 412 gradientToSrcShader.setGradient(*getCurrentContext(), gradShaderSrcID, srcRangeInfo.valueMin, dstRangeInfo.valueMax); 413 sglr::drawQuad(*getCurrentContext(), gradShaderSrcID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 414 } 415 } 416 417 // Execute copy. 418 glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo); 419 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo); 420 glBlitFramebuffer(0, 0, m_size.x(), m_size.y(), 0, 0, m_size.x(), m_size.y(), GL_COLOR_BUFFER_BIT, GL_NEAREST); 421 checkError(); 422 423 // Read results. 424 glBindFramebuffer(GL_READ_FRAMEBUFFER, dstFbo); 425 readPixels(dst, 0, 0, m_size.x(), m_size.y(), dstFormat, dstRangeInfo.lookupScale, dstRangeInfo.lookupBias); 426 } 427 428 bool compare (const tcu::Surface& reference, const tcu::Surface& result) 429 { 430 const tcu::TextureFormat srcFormat = glu::mapGLInternalFormat(m_srcFormat); 431 const tcu::TextureFormat dstFormat = glu::mapGLInternalFormat(m_dstFormat); 432 const bool srcIsSRGB = tcu::isSRGB(srcFormat); 433 const bool dstIsSRGB = tcu::isSRGB(dstFormat); 434 435 tcu::RGBA threshold; 436 437 if (dstIsSRGB) 438 { 439 threshold = getToSRGBConversionThreshold(srcFormat, dstFormat); 440 } 441 else 442 { 443 const tcu::RGBA srcMaxDiff = getFormatThreshold(srcFormat) * (srcIsSRGB ? 2 : 1); 444 const tcu::RGBA dstMaxDiff = getFormatThreshold(dstFormat); 445 446 threshold = tcu::max(srcMaxDiff, dstMaxDiff); 447 } 448 449 m_testCtx.getLog() << tcu::TestLog::Message << "threshold = " << threshold << tcu::TestLog::EndMessage; 450 return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, threshold, tcu::COMPARE_LOG_RESULT); 451 } 452 453private: 454 deUint32 m_srcFormat; 455 deUint32 m_dstFormat; 456 IVec2 m_size; 457}; 458 459class BlitDepthStencilCase : public FboTestCase 460{ 461public: 462 BlitDepthStencilCase (Context& context, const char* name, const char* desc, deUint32 depthFormat, deUint32 stencilFormat, deUint32 srcBuffers, const IVec2& srcSize, const IVec4& srcRect, deUint32 dstBuffers, const IVec2& dstSize, const IVec4& dstRect, deUint32 copyBuffers) 463 : FboTestCase (context, name, desc) 464 , m_depthFormat (depthFormat) 465 , m_stencilFormat(stencilFormat) 466 , m_srcBuffers (srcBuffers) 467 , m_srcSize (srcSize) 468 , m_srcRect (srcRect) 469 , m_dstBuffers (dstBuffers) 470 , m_dstSize (dstSize) 471 , m_dstRect (dstRect) 472 , m_copyBuffers (copyBuffers) 473 { 474 } 475 476protected: 477 void preCheck (void) 478 { 479 if (m_depthFormat != GL_NONE) 480 checkFormatSupport(m_depthFormat); 481 if (m_stencilFormat != GL_NONE) 482 checkFormatSupport(m_stencilFormat); 483 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_separate_depth_stencil") 484 && m_depthFormat != GL_NONE && m_stencilFormat != GL_NONE) 485 throw tcu::NotSupportedError("Separate depth and stencil buffers not supported"); 486 } 487 488 void render (tcu::Surface& dst) 489 { 490 const deUint32 colorFormat = GL_RGBA8; 491 492 GradientShader gradShader (glu::TYPE_FLOAT_VEC4); 493 Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); 494 FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); 495 496 deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); 497 deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); 498 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); 499 500 deUint32 srcFbo = 0; 501 deUint32 dstFbo = 0; 502 deUint32 srcColorRbo = 0; 503 deUint32 dstColorRbo = 0; 504 deUint32 srcDepthRbo = 0; 505 deUint32 srcStencilRbo = 0; 506 deUint32 dstDepthRbo = 0; 507 deUint32 dstStencilRbo = 0; 508 509 // setup shaders 510 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); 511 texShader.setUniforms(*getCurrentContext(), texShaderID); 512 513 // Create framebuffers. 514 for (int ndx = 0; ndx < 2; ndx++) 515 { 516 deUint32& fbo = ndx ? dstFbo : srcFbo; 517 deUint32& colorRbo = ndx ? dstColorRbo : srcColorRbo; 518 deUint32& depthRbo = ndx ? dstDepthRbo : srcDepthRbo; 519 deUint32& stencilRbo = ndx ? dstStencilRbo : srcStencilRbo; 520 deUint32 bufs = ndx ? m_dstBuffers : m_srcBuffers; 521 const IVec2& size = ndx ? m_dstSize : m_srcSize; 522 523 glGenFramebuffers(1, &fbo); 524 glGenRenderbuffers(1, &colorRbo); 525 526 glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); 527 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, size.x(), size.y()); 528 529 if (m_depthFormat != GL_NONE) { 530 glGenRenderbuffers(1, &depthRbo); 531 glBindRenderbuffer(GL_RENDERBUFFER, depthRbo); 532 glRenderbufferStorage(GL_RENDERBUFFER, m_depthFormat, size.x(), size.y()); 533 } 534 535 if (m_stencilFormat != GL_NONE) { 536 glGenRenderbuffers(1, &stencilRbo); 537 glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo); 538 glRenderbufferStorage(GL_RENDERBUFFER, m_stencilFormat, size.x(), size.y()); 539 } 540 541 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 542 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); 543 544 if (bufs & GL_DEPTH_BUFFER_BIT) 545 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo); 546 if (bufs & GL_STENCIL_BUFFER_BIT) 547 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 548 m_stencilFormat == GL_NONE? depthRbo : stencilRbo); 549 550 checkError(); 551 checkFramebufferStatus(GL_FRAMEBUFFER); 552 553 // Clear depth to 1 and stencil to 0. 554 glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); 555 } 556 557 // Fill source with gradient, depth = [-1..1], stencil = 7 558 glBindFramebuffer(GL_FRAMEBUFFER, srcFbo); 559 glViewport(0, 0, m_srcSize.x(), m_srcSize.y()); 560 glEnable(GL_DEPTH_TEST); 561 glEnable(GL_STENCIL_TEST); 562 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 563 glStencilFunc(GL_ALWAYS, 7, 0xffu); 564 565 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); 566 567 // Fill destination with grid pattern, depth = 0 and stencil = 1 568 { 569 const deUint32 format = GL_RGBA; 570 const deUint32 dataType = GL_UNSIGNED_BYTE; 571 const int texW = m_srcSize.x(); 572 const int texH = m_srcSize.y(); 573 deUint32 gridTex = 0; 574 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); 575 576 tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f)); 577 578 glGenTextures(1, &gridTex); 579 glBindTexture(GL_TEXTURE_2D, gridTex); 580 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 581 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 583 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 584 glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); 585 586 glBindFramebuffer(GL_FRAMEBUFFER, dstFbo); 587 glViewport(0, 0, m_dstSize.x(), m_dstSize.y()); 588 glStencilFunc(GL_ALWAYS, 1, 0xffu); 589 sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 590 } 591 592 // Perform copy. 593 glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFbo); 594 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo); 595 glBlitFramebuffer(m_srcRect.x(), m_srcRect.y(), m_srcRect.z(), m_srcRect.w(), m_dstRect.x(), m_dstRect.y(), m_dstRect.z(), m_dstRect.w(), m_copyBuffers, GL_NEAREST); 596 597 // Render blue color where depth < 0, decrement on depth failure. 598 glBindFramebuffer(GL_FRAMEBUFFER, dstFbo); 599 glViewport(0, 0, m_dstSize.x(), m_dstSize.y()); 600 glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); 601 glStencilFunc(GL_ALWAYS, 0, 0xffu); 602 603 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 604 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 605 606 if (m_dstBuffers & GL_STENCIL_BUFFER_BIT) 607 { 608 // Render green color where stencil == 6. 609 glDisable(GL_DEPTH_TEST); 610 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 611 glStencilFunc(GL_EQUAL, 6, 0xffu); 612 613 flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 614 sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 615 } 616 617 readPixels(dst, 0, 0, m_dstSize.x(), m_dstSize.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f)); 618 } 619 620private: 621 deUint32 m_depthFormat; 622 deUint32 m_stencilFormat; 623 deUint32 m_srcBuffers; 624 IVec2 m_srcSize; 625 IVec4 m_srcRect; 626 deUint32 m_dstBuffers; 627 IVec2 m_dstSize; 628 IVec4 m_dstRect; 629 deUint32 m_copyBuffers; 630}; 631 632class BlitDefaultFramebufferCase : public FboTestCase 633{ 634public: 635 BlitDefaultFramebufferCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 filter) 636 : FboTestCase (context, name, desc) 637 , m_format (format) 638 , m_filter (filter) 639 { 640 } 641 642protected: 643 void preCheck (void) 644 { 645 if (m_context.getRenderTarget().getNumSamples() > 0) 646 throw tcu::NotSupportedError("Not supported in MSAA config"); 647 648 checkFormatSupport(m_format); 649 } 650 651 virtual void render (tcu::Surface& dst) 652 { 653 tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_format); 654 glu::TransferFormat transferFmt = glu::getTransferFormat(colorFormat); 655 GradientShader gradShader (glu::TYPE_FLOAT_VEC4); 656 Texture2DShader texShader (DataTypes() << glu::getSampler2DType(colorFormat), glu::TYPE_FLOAT_VEC4); 657 deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); 658 deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); 659 deUint32 fbo = 0; 660 deUint32 tex = 0; 661 const int texW = 128; 662 const int texH = 128; 663 664 // Setup shaders 665 gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f)); 666 texShader.setUniforms(*getCurrentContext(), texShaderID); 667 668 // FBO 669 glGenFramebuffers(1, &fbo); 670 glGenTextures(1, &tex); 671 672 glBindTexture(GL_TEXTURE_2D, tex); 673 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 674 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_filter); 676 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_filter); 677 glTexImage2D(GL_TEXTURE_2D, 0, m_format, texW, texH, 0, transferFmt.format, transferFmt.dataType, DE_NULL); 678 679 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 680 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); 681 checkError(); 682 checkFramebufferStatus(GL_FRAMEBUFFER); 683 684 // Render gradient to screen. 685 glBindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 686 687 sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 688 689 // Blit gradient from screen to fbo. 690 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); 691 glBlitFramebuffer(0, 0, getWidth(), getHeight(), 0, 0, texW, texH, GL_COLOR_BUFFER_BIT, m_filter); 692 693 // Fill left half of viewport with quad that uses texture. 694 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 695 glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 0.0f, 0.0f, 1.0f).getPtr()); 696 sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f)); 697 698 // Blit fbo to right half. 699 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); 700 glBlitFramebuffer(0, 0, texW, texH, getWidth()/2, 0, getWidth(), getHeight(), GL_COLOR_BUFFER_BIT, m_filter); 701 702 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 703 readPixels(dst, 0, 0, getWidth(), getHeight()); 704 } 705 706 bool compare (const tcu::Surface& reference, const tcu::Surface& result) 707 { 708 const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), tcu::RGBA(12, 12, 12, 12))); 709 710 m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage; 711 712 return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT); 713 } 714 715protected: 716 const deUint32 m_format; 717 const deUint32 m_filter; 718}; 719 720class DefaultFramebufferBlitCase : public BlitDefaultFramebufferCase 721{ 722public: 723 enum BlitDirection 724 { 725 BLIT_DEFAULT_TO_TARGET, 726 BLIT_TO_DEFAULT_FROM_TARGET, 727 728 BLIT_LAST 729 }; 730 enum BlitArea 731 { 732 AREA_SCALE, 733 AREA_OUT_OF_BOUNDS, 734 735 AREA_LAST 736 }; 737 738 DefaultFramebufferBlitCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 filter, BlitDirection dir, BlitArea area) 739 : BlitDefaultFramebufferCase (context, name, desc, format, filter) 740 , m_blitDir (dir) 741 , m_blitArea (area) 742 , m_srcRect (-1, -1, -1, -1) 743 , m_dstRect (-1, -1, -1, -1) 744 , m_interestingArea (-1, -1, -1, -1) 745 { 746 DE_ASSERT(dir < BLIT_LAST); 747 DE_ASSERT(area < AREA_LAST); 748 } 749 750 void init (void) 751 { 752 // requirements 753 const int minViewportSize = 128; 754 if (m_context.getRenderTarget().getWidth() < minViewportSize || m_context.getRenderTarget().getHeight() < minViewportSize) 755 throw tcu::NotSupportedError("Viewport size " + de::toString(minViewportSize) + "x" + de::toString(minViewportSize) + " required"); 756 757 // prevent viewport randoming 758 m_viewportWidth = m_context.getRenderTarget().getWidth(); 759 m_viewportHeight = m_context.getRenderTarget().getHeight(); 760 761 // set proper areas 762 if (m_blitArea == AREA_SCALE) 763 { 764 m_srcRect = IVec4( 10, 20, 65, 100); 765 m_dstRect = IVec4( 25, 30, 125, 94); 766 m_interestingArea = IVec4(0, 0, 128, 128); 767 } 768 else if (m_blitArea == AREA_OUT_OF_BOUNDS) 769 { 770 const tcu::IVec2 ubound = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (tcu::IVec2(128, 128)) : (tcu::IVec2(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight())); 771 772 m_srcRect = IVec4(-10, -15, 100, 63); 773 m_dstRect = ubound.swizzle(0, 1, 0, 1) + IVec4(-75, -99, 8, 16); 774 m_interestingArea = IVec4(ubound.x() - 128, ubound.y() - 128, ubound.x(), ubound.y()); 775 } 776 else 777 DE_ASSERT(false); 778 } 779 780 void render (tcu::Surface& dst) 781 { 782 const tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_format); 783 const glu::TransferFormat transferFmt = glu::getTransferFormat(colorFormat); 784 const tcu::TextureChannelClass targetClass = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (tcu::getTextureChannelClass(colorFormat.type)) : (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT); 785 deUint32 fbo = 0; 786 deUint32 fboTex = 0; 787 const int fboTexW = 128; 788 const int fboTexH = 128; 789 const int sourceWidth = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (getWidth()) : (fboTexW); 790 const int sourceHeight = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (getHeight()) : (fboTexH); 791 const int gridRenderWidth = de::min(256, sourceWidth); 792 const int gridRenderHeight= de::min(256, sourceHeight); 793 794 int targetFbo = -1; 795 int sourceFbo = -1; 796 797 // FBO 798 glGenFramebuffers(1, &fbo); 799 glGenTextures(1, &fboTex); 800 801 glBindTexture(GL_TEXTURE_2D, fboTex); 802 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 803 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 804 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_filter); 805 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_filter); 806 glTexImage2D(GL_TEXTURE_2D, 0, m_format, fboTexW, fboTexH, 0, transferFmt.format, transferFmt.dataType, DE_NULL); 807 808 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 809 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0); 810 checkError(); 811 checkFramebufferStatus(GL_FRAMEBUFFER); 812 813 targetFbo = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (fbo) : (m_context.getRenderContext().getDefaultFramebuffer()); 814 sourceFbo = (m_blitDir == BLIT_DEFAULT_TO_TARGET) ? (m_context.getRenderContext().getDefaultFramebuffer()) : (fbo); 815 816 // Render grid to source framebuffer 817 { 818 Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); 819 const deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); 820 const deUint32 internalFormat = GL_RGBA8; 821 const deUint32 format = GL_RGBA; 822 const deUint32 dataType = GL_UNSIGNED_BYTE; 823 const int gridTexW = 128; 824 const int gridTexH = 128; 825 deUint32 gridTex = 0; 826 tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), gridTexW, gridTexH, 1); 827 828 tcu::fillWithGrid(data.getAccess(), 9, tcu::Vec4(0.9f, 0.5f, 0.1f, 0.9f), tcu::Vec4(0.2f, 0.8f, 0.2f, 0.7f)); 829 830 glGenTextures(1, &gridTex); 831 glBindTexture(GL_TEXTURE_2D, gridTex); 832 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 833 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 834 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 835 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 836 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, gridTexW, gridTexH, 0, format, dataType, data.getAccess().getDataPtr()); 837 838 glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo); 839 glViewport(0, 0, gridRenderWidth, gridRenderHeight); 840 glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 0.0f, 0.0f, 1.0f).getPtr()); 841 842 texShader.setUniforms(*getCurrentContext(), texShaderID); 843 sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); 844 glUseProgram(0); 845 } 846 847 // Blit source framebuffer to destination 848 849 glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo); 850 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetFbo); 851 checkError(); 852 853 if (targetClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || targetClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || targetClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) 854 glClearBufferfv(GL_COLOR, 0, Vec4(1.0f, 1.0f, 0.0f, 1.0f).getPtr()); 855 else if (targetClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) 856 glClearBufferiv(GL_COLOR, 0, IVec4(0, 0, 0, 0).getPtr()); 857 else if (targetClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) 858 glClearBufferuiv(GL_COLOR, 0, UVec4(0, 0, 0, 0).getPtr()); 859 else 860 DE_ASSERT(false); 861 862 glBlitFramebuffer(m_srcRect.x(), m_srcRect.y(), m_srcRect.z(), m_srcRect.w(), m_dstRect.x(), m_dstRect.y(), m_dstRect.z(), m_dstRect.w(), GL_COLOR_BUFFER_BIT, m_filter); 863 checkError(); 864 865 // Read target 866 867 glBindFramebuffer(GL_FRAMEBUFFER, targetFbo); 868 869 if (m_blitDir == BLIT_TO_DEFAULT_FROM_TARGET) 870 readPixels(dst, m_interestingArea.x(), m_interestingArea.y(), m_interestingArea.z() - m_interestingArea.x(), m_interestingArea.w() - m_interestingArea.y()); 871 else 872 readPixels(dst, m_interestingArea.x(), m_interestingArea.y(), m_interestingArea.z() - m_interestingArea.x(), m_interestingArea.w() - m_interestingArea.y(), colorFormat, tcu::Vec4(1.0f), tcu::Vec4(0.0f)); 873 874 checkError(); 875 } 876 877private: 878 const BlitDirection m_blitDir; 879 const BlitArea m_blitArea; 880 tcu::IVec4 m_srcRect; 881 tcu::IVec4 m_dstRect; 882 tcu::IVec4 m_interestingArea; 883}; 884 885FramebufferBlitTests::FramebufferBlitTests (Context& context) 886 : TestCaseGroup(context, "blit", "Framebuffer blit tests") 887{ 888} 889 890FramebufferBlitTests::~FramebufferBlitTests (void) 891{ 892} 893 894void FramebufferBlitTests::init (void) 895{ 896 static const deUint32 colorFormats[] = 897 { 898 // RGBA formats 899 GL_RGBA32I, 900 GL_RGBA32UI, 901 GL_RGBA16I, 902 GL_RGBA16UI, 903 GL_RGBA8, 904 GL_RGBA8I, 905 GL_RGBA8UI, 906 GL_SRGB8_ALPHA8, 907 GL_RGB10_A2, 908 GL_RGB10_A2UI, 909 GL_RGBA4, 910 GL_RGB5_A1, 911 912 // RGB formats 913 GL_RGB8, 914 GL_RGB565, 915 916 // RG formats 917 GL_RG32I, 918 GL_RG32UI, 919 GL_RG16I, 920 GL_RG16UI, 921 GL_RG8, 922 GL_RG8I, 923 GL_RG8UI, 924 925 // R formats 926 GL_R32I, 927 GL_R32UI, 928 GL_R16I, 929 GL_R16UI, 930 GL_R8, 931 GL_R8I, 932 GL_R8UI, 933 934 // GL_EXT_color_buffer_float 935 GL_RGBA32F, 936 GL_RGBA16F, 937 GL_R11F_G11F_B10F, 938 GL_RG32F, 939 GL_RG16F, 940 GL_R32F, 941 GL_R16F 942 }; 943 944 static const deUint32 depthStencilFormats[] = 945 { 946 GL_NONE, 947 GL_DEPTH_COMPONENT32F, 948 GL_DEPTH_COMPONENT24, 949 GL_DEPTH_COMPONENT16, 950 GL_DEPTH32F_STENCIL8, 951 GL_DEPTH24_STENCIL8 952 }; 953 954 static const deUint32 stencilFormats[] = 955 { 956 GL_NONE, 957 GL_STENCIL_INDEX8 958 }; 959 960 // .rect 961 { 962 static const struct 963 { 964 const char* name; 965 IVec4 srcRect; 966 IVec4 dstRect; 967 } copyRects[] = 968 { 969 { "basic", IVec4( 10, 20, 65, 100), IVec4( 45, 5, 100, 85) }, 970 { "scale", IVec4( 10, 20, 65, 100), IVec4( 25, 30, 125, 94) }, 971 { "out_of_bounds", IVec4(-10, -15, 100, 63), IVec4( 50, 30, 136, 144) }, 972 }; 973 974 static const struct 975 { 976 const char* name; 977 IVec4 srcRect; 978 IVec4 dstRect; 979 } filterConsistencyRects[] = 980 { 981 { "mag", IVec4( 20, 10, 74, 88), IVec4( 10, 10, 91, 101) }, 982 { "min", IVec4( 10, 20, 78, 100), IVec4( 20, 20, 71, 80) }, 983 { "out_of_bounds_mag", IVec4( 21, 10, 73, 82), IVec4( 11, 43, 141, 151) }, 984 { "out_of_bounds_min", IVec4( 11, 21, 77, 97), IVec4( 80, 82, 135, 139) }, 985 }; 986 987 static const struct 988 { 989 const char* name; 990 IVec4 srcSwizzle; 991 IVec4 dstSwizzle; 992 } swizzles[] = 993 { 994 { DE_NULL, IVec4(0,1,2,3), IVec4(0,1,2,3) }, 995 { "reverse_src_x", IVec4(2,1,0,3), IVec4(0,1,2,3) }, 996 { "reverse_src_y", IVec4(0,3,2,1), IVec4(0,1,2,3) }, 997 { "reverse_dst_x", IVec4(0,1,2,3), IVec4(2,1,0,3) }, 998 { "reverse_dst_y", IVec4(0,1,2,3), IVec4(0,3,2,1) }, 999 { "reverse_src_dst_x", IVec4(2,1,0,3), IVec4(2,1,0,3) }, 1000 { "reverse_src_dst_y", IVec4(0,3,2,1), IVec4(0,3,2,1) } 1001 }; 1002 1003 const IVec2 srcSize(127, 119); 1004 const IVec2 dstSize(132, 128); 1005 1006 // Blit rectangle tests. 1007 tcu::TestCaseGroup* rectGroup = new tcu::TestCaseGroup(m_testCtx, "rect", "Blit rectangle tests"); 1008 addChild(rectGroup); 1009 for (int rectNdx = 0; rectNdx < DE_LENGTH_OF_ARRAY(copyRects); rectNdx++) 1010 { 1011 for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++) 1012 { 1013 string name = string(copyRects[rectNdx].name) + (swizzles[swzNdx].name ? (string("_") + swizzles[swzNdx].name) : string()); 1014 IVec4 srcSwz = swizzles[swzNdx].srcSwizzle; 1015 IVec4 dstSwz = swizzles[swzNdx].dstSwizzle; 1016 IVec4 srcRect = copyRects[rectNdx].srcRect.swizzle(srcSwz[0], srcSwz[1], srcSwz[2], srcSwz[3]); 1017 IVec4 dstRect = copyRects[rectNdx].dstRect.swizzle(dstSwz[0], dstSwz[1], dstSwz[2], dstSwz[3]); 1018 1019 rectGroup->addChild(new BlitRectCase(m_context, (name + "_nearest").c_str(), "", GL_NEAREST, srcSize, srcRect, dstSize, dstRect)); 1020 rectGroup->addChild(new BlitRectCase(m_context, (name + "_linear").c_str(), "", GL_LINEAR, srcSize, srcRect, dstSize, dstRect)); 1021 } 1022 } 1023 1024 // Nearest filter tests 1025 for (int rectNdx = 0; rectNdx < DE_LENGTH_OF_ARRAY(filterConsistencyRects); rectNdx++) 1026 { 1027 for (int swzNdx = 0; swzNdx < DE_LENGTH_OF_ARRAY(swizzles); swzNdx++) 1028 { 1029 string name = string("nearest_consistency_") + filterConsistencyRects[rectNdx].name + (swizzles[swzNdx].name ? (string("_") + swizzles[swzNdx].name) : string()); 1030 IVec4 srcSwz = swizzles[swzNdx].srcSwizzle; 1031 IVec4 dstSwz = swizzles[swzNdx].dstSwizzle; 1032 IVec4 srcRect = filterConsistencyRects[rectNdx].srcRect.swizzle(srcSwz[0], srcSwz[1], srcSwz[2], srcSwz[3]); 1033 IVec4 dstRect = filterConsistencyRects[rectNdx].dstRect.swizzle(dstSwz[0], dstSwz[1], dstSwz[2], dstSwz[3]); 1034 1035 rectGroup->addChild(new BlitNearestFilterConsistencyCase(m_context, name.c_str(), "Test consistency of the nearest filter", srcSize, srcRect, dstSize, dstRect)); 1036 } 1037 } 1038 } 1039 1040 // .conversion 1041 { 1042 tcu::TestCaseGroup* conversionGroup = new tcu::TestCaseGroup(m_testCtx, "conversion", "Color conversion tests"); 1043 addChild(conversionGroup); 1044 1045 for (int srcFmtNdx = 0; srcFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); srcFmtNdx++) 1046 { 1047 for (int dstFmtNdx = 0; dstFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); dstFmtNdx++) 1048 { 1049 deUint32 srcFormat = colorFormats[srcFmtNdx]; 1050 tcu::TextureFormat srcTexFmt = glu::mapGLInternalFormat(srcFormat); 1051 tcu::TextureChannelClass srcType = tcu::getTextureChannelClass(srcTexFmt.type); 1052 deUint32 dstFormat = colorFormats[dstFmtNdx]; 1053 tcu::TextureFormat dstTexFmt = glu::mapGLInternalFormat(dstFormat); 1054 tcu::TextureChannelClass dstType = tcu::getTextureChannelClass(dstTexFmt.type); 1055 1056 if (((srcType == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || srcType == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) != 1057 (dstType == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || dstType == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)) || 1058 ((srcType == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) != (dstType == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)) || 1059 ((srcType == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) != (dstType == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER))) 1060 continue; // Conversion not supported. 1061 1062 string name = string(getFormatName(srcFormat)) + "_to_" + getFormatName(dstFormat); 1063 1064 conversionGroup->addChild(new BlitColorConversionCase(m_context, name.c_str(), "", srcFormat, dstFormat, IVec2(127, 113))); 1065 } 1066 } 1067 } 1068 1069 // .depth_stencil 1070 { 1071 tcu::TestCaseGroup* depthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "depth_stencil", "Depth and stencil blits"); 1072 addChild(depthStencilGroup); 1073 1074 for (int dFmtNdx = 0; dFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); dFmtNdx++) 1075 { 1076 for (int sFmtNdx = 0; sFmtNdx < DE_LENGTH_OF_ARRAY(stencilFormats); sFmtNdx++) 1077 { 1078 deUint32 depthFormat = depthStencilFormats[dFmtNdx]; 1079 deUint32 stencilFormat = stencilFormats[sFmtNdx]; 1080 bool depth = false; 1081 bool stencil = false; 1082 string fmtName; 1083 1084 if (depthFormat != GL_NONE) 1085 { 1086 tcu::TextureFormat info = glu::mapGLInternalFormat(depthFormat); 1087 1088 fmtName += getFormatName(depthFormat); 1089 if (info.order == tcu::TextureFormat::D || info.order == tcu::TextureFormat::DS) 1090 depth = true; 1091 if (info.order == tcu::TextureFormat::DS) 1092 stencil = true; 1093 } 1094 1095 if (stencilFormat != GL_NONE) 1096 { 1097 // Do not try separate stencil along with a combined depth/stencil 1098 if (stencil) 1099 continue; 1100 1101 if (depthFormat != GL_NONE) 1102 fmtName += "_"; 1103 fmtName += getFormatName(stencilFormat); 1104 stencil = true; 1105 } 1106 1107 if (!stencil && !depth) 1108 continue; 1109 1110 deUint32 buffers = (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0); 1111 1112 depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_basic").c_str(), "", depthFormat, stencilFormat, buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers)); 1113 depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_scale").c_str(), "", depthFormat, stencilFormat, buffers, IVec2(127, 119), IVec4(10, 30, 100, 70), buffers, IVec2(111, 130), IVec4(20, 5, 80, 130), buffers)); 1114 1115 if (depth && stencil) 1116 { 1117 depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_depth_only").c_str(), "", depthFormat, stencilFormat, buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), GL_DEPTH_BUFFER_BIT)); 1118 depthStencilGroup->addChild(new BlitDepthStencilCase(m_context, (fmtName + "_stencil_only").c_str(), "", depthFormat, stencilFormat, buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), buffers, IVec2(128, 128), IVec4(0, 0, 128, 128), GL_STENCIL_BUFFER_BIT)); 1119 } 1120 } 1121 } 1122 } 1123 1124 // .default_framebuffer 1125 { 1126 static const struct 1127 { 1128 const char* name; 1129 DefaultFramebufferBlitCase::BlitArea area; 1130 } areas[] = 1131 { 1132 { "scale", DefaultFramebufferBlitCase::AREA_SCALE }, 1133 { "out_of_bounds", DefaultFramebufferBlitCase::AREA_OUT_OF_BOUNDS }, 1134 }; 1135 1136 tcu::TestCaseGroup* defaultFbGroup = new tcu::TestCaseGroup(m_testCtx, "default_framebuffer", "Blits with default framebuffer"); 1137 addChild(defaultFbGroup); 1138 1139 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) 1140 { 1141 const deUint32 format = colorFormats[fmtNdx]; 1142 const tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format); 1143 const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(texFmt.type); 1144 const deUint32 filter = glu::isGLInternalColorFormatFilterable(format) ? GL_LINEAR : GL_NEAREST; 1145 const bool filterable = glu::isGLInternalColorFormatFilterable(format); 1146 1147 if (fmtClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT && 1148 fmtClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && 1149 fmtClass != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) 1150 continue; // Conversion not supported. 1151 1152 defaultFbGroup->addChild(new BlitDefaultFramebufferCase(m_context, getFormatName(format), "", format, filter)); 1153 1154 for (int areaNdx = 0; areaNdx < DE_LENGTH_OF_ARRAY(areas); areaNdx++) 1155 { 1156 const string name = string(areas[areaNdx].name); 1157 const bool addLinear = filterable; 1158 const bool addNearest = !addLinear || (areas[areaNdx].area != DefaultFramebufferBlitCase::AREA_OUT_OF_BOUNDS); // No need to check out-of-bounds with different filtering 1159 1160 if (addNearest) 1161 { 1162 defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_nearest_" + name + "_blit_from_default").c_str(), "", format, GL_NEAREST, DefaultFramebufferBlitCase::BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area)); 1163 defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_nearest_" + name + "_blit_to_default").c_str(), "", format, GL_NEAREST, DefaultFramebufferBlitCase::BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area)); 1164 } 1165 1166 if (addLinear) 1167 { 1168 defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_linear_" + name + "_blit_from_default").c_str(), "", format, GL_LINEAR, DefaultFramebufferBlitCase::BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area)); 1169 defaultFbGroup->addChild(new DefaultFramebufferBlitCase(m_context, (std::string(getFormatName(format)) + "_linear_" + name + "_blit_to_default").c_str(), "", format, GL_LINEAR, DefaultFramebufferBlitCase::BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area)); 1170 } 1171 } 1172 } 1173 } 1174} 1175 1176} // Functional 1177} // gles3 1178} // deqp 1179