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