1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Base class for FBO tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fFboTestCase.hpp" 25 #include "es31fFboTestUtil.hpp" 26 #include "tcuTestLog.hpp" 27 #include "tcuImageCompare.hpp" 28 #include "tcuRenderTarget.hpp" 29 #include "sglrGLContext.hpp" 30 #include "sglrReferenceContext.hpp" 31 #include "gluStrUtil.hpp" 32 #include "gluContextInfo.hpp" 33 #include "deRandom.hpp" 34 #include "glwEnums.hpp" 35 #include "glwFunctions.hpp" 36 37 #include <algorithm> 38 39 namespace deqp 40 { 41 namespace gles31 42 { 43 namespace Functional 44 { 45 46 using tcu::TestLog; 47 using std::string; 48 49 FboTestCase::FboTestCase (Context& context, const char* name, const char* description, bool useScreenSizedViewport) 50 : TestCase (context, name, description) 51 , m_viewportWidth (useScreenSizedViewport ? context.getRenderTarget().getWidth() : 128) 52 , m_viewportHeight (useScreenSizedViewport ? context.getRenderTarget().getHeight() : 128) 53 { 54 } 55 56 FboTestCase::~FboTestCase (void) 57 { 58 } 59 60 FboTestCase::IterateResult FboTestCase::iterate (void) 61 { 62 glu::RenderContext& renderCtx = TestCase::m_context.getRenderContext(); 63 const tcu::RenderTarget& renderTarget = renderCtx.getRenderTarget(); 64 TestLog& log = m_testCtx.getLog(); 65 66 // Viewport. 67 de::Random rnd (deStringHash(getName())); 68 int width = deMin32(renderTarget.getWidth(), m_viewportWidth); 69 int height = deMin32(renderTarget.getHeight(), m_viewportHeight); 70 int x = rnd.getInt(0, renderTarget.getWidth() - width); 71 int y = rnd.getInt(0, renderTarget.getHeight() - height); 72 73 // Surface format and storage is choosen by render(). 74 tcu::Surface reference; 75 tcu::Surface result; 76 77 // Call preCheck() that can throw exception if some requirement is not met. 78 preCheck(); 79 80 log << TestLog::Message << "Rendering with GL driver" << TestLog::EndMessage; 81 82 // Render using GLES3.1 83 try 84 { 85 sglr::GLContext context(renderCtx, log, 0, tcu::IVec4(x, y, width, height)); 86 setContext(&context); 87 render(result); 88 89 // Check error. 90 deUint32 err = glGetError(); 91 if (err != GL_NO_ERROR) 92 throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), DE_NULL, __FILE__, __LINE__); 93 94 setContext(DE_NULL); 95 } 96 catch (const FboTestUtil::FboIncompleteException& e) 97 { 98 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED) 99 { 100 log << e; 101 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 102 return STOP; 103 } 104 else 105 throw; 106 } 107 108 log << TestLog::Message << "Rendering reference image" << TestLog::EndMessage; 109 110 // Render reference. 111 { 112 sglr::ReferenceContextBuffers buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height); 113 sglr::ReferenceContext context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 114 115 setContext(&context); 116 render(reference); 117 setContext(DE_NULL); 118 } 119 120 bool isOk = compare(reference, result); 121 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 122 isOk ? "Pass" : "Image comparison failed"); 123 return STOP; 124 } 125 126 bool FboTestCase::compare (const tcu::Surface& reference, const tcu::Surface& result) 127 { 128 return tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result, 0.05f, tcu::COMPARE_LOG_RESULT); 129 } 130 131 void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height, const tcu::TextureFormat& format, const tcu::Vec4& scale, const tcu::Vec4& bias) 132 { 133 FboTestUtil::readPixels(*getCurrentContext(), dst, x, y, width, height, format, scale, bias); 134 } 135 136 void FboTestCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height) 137 { 138 getCurrentContext()->readPixels(dst, x, y, width, height); 139 } 140 141 void FboTestCase::checkFramebufferStatus (deUint32 target) 142 { 143 deUint32 status = glCheckFramebufferStatus(target); 144 if (status != GL_FRAMEBUFFER_COMPLETE) 145 throw FboTestUtil::FboIncompleteException(status, __FILE__, __LINE__); 146 } 147 148 void FboTestCase::checkError (void) 149 { 150 deUint32 err = glGetError(); 151 if (err != GL_NO_ERROR) 152 throw glu::Error((int)err, (string("Got ") + glu::getErrorStr(err).toString()).c_str(), DE_NULL, __FILE__, __LINE__); 153 } 154 155 static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext) 156 { 157 const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); 158 switch (format) 159 { 160 // Color-renderable formats 161 case GL_RGBA32I: 162 case GL_RGBA32UI: 163 case GL_RGBA16I: 164 case GL_RGBA16UI: 165 case GL_RGBA8: 166 case GL_RGBA8I: 167 case GL_RGBA8UI: 168 case GL_SRGB8_ALPHA8: 169 case GL_RGB10_A2: 170 case GL_RGB10_A2UI: 171 case GL_RGBA4: 172 case GL_RGB5_A1: 173 case GL_RGB8: 174 case GL_RGB565: 175 case GL_RG32I: 176 case GL_RG32UI: 177 case GL_RG16I: 178 case GL_RG16UI: 179 case GL_RG8: 180 case GL_RG8I: 181 case GL_RG8UI: 182 case GL_R32I: 183 case GL_R32UI: 184 case GL_R16I: 185 case GL_R16UI: 186 case GL_R8: 187 case GL_R8I: 188 case GL_R8UI: 189 return true; 190 191 // Depth formats 192 case GL_DEPTH_COMPONENT32F: 193 case GL_DEPTH_COMPONENT24: 194 case GL_DEPTH_COMPONENT16: 195 return true; 196 197 // Depth+stencil formats 198 case GL_DEPTH32F_STENCIL8: 199 case GL_DEPTH24_STENCIL8: 200 return true; 201 202 // Stencil formats 203 case GL_STENCIL_INDEX8: 204 return true; 205 206 // Float format 207 case GL_RGBA32F: 208 case GL_RGB32F: 209 case GL_R11F_G11F_B10F: 210 case GL_RG32F: 211 case GL_R32F: 212 return isES32; 213 214 215 default: 216 return false; 217 } 218 } 219 220 static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext) 221 { 222 const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); 223 std::vector<std::string> out; 224 225 DE_ASSERT(!isRequiredFormat(format, renderContext)); 226 227 switch (format) 228 { 229 case GL_RGB16F: 230 out.push_back("GL_EXT_color_buffer_half_float"); 231 break; 232 233 case GL_RGBA16F: 234 case GL_RG16F: 235 case GL_R16F: 236 out.push_back("GL_EXT_color_buffer_half_float"); 237 238 case GL_RGBA32F: 239 case GL_RGB32F: 240 case GL_R11F_G11F_B10F: 241 case GL_RG32F: 242 case GL_R32F: 243 if (!isES32) 244 out.push_back("GL_EXT_color_buffer_float"); 245 break; 246 247 default: 248 break; 249 } 250 251 return out; 252 } 253 254 static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts) 255 { 256 for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++) 257 { 258 const std::string& extension = *iter; 259 260 if (context.getContextInfo().isExtensionSupported(extension.c_str())) 261 return true; 262 } 263 264 return false; 265 } 266 267 void FboTestCase::checkFormatSupport (deUint32 sizedFormat) 268 { 269 const bool isCoreFormat = isRequiredFormat(sizedFormat, m_context.getRenderContext()); 270 const std::vector<std::string> requiredExts = (!isCoreFormat) ? getEnablingExtensions(sizedFormat, m_context.getRenderContext()) : std::vector<std::string>(); 271 272 // Check that we don't try to use invalid formats. 273 DE_ASSERT(isCoreFormat || !requiredExts.empty()); 274 275 if (!requiredExts.empty() && !isAnyExtensionSupported(m_context, requiredExts)) 276 throw tcu::NotSupportedError("Format not supported"); 277 } 278 279 static int getMinimumSampleCount (deUint32 format) 280 { 281 switch (format) 282 { 283 // Core formats 284 case GL_RGBA32I: 285 case GL_RGBA32UI: 286 case GL_RGBA16I: 287 case GL_RGBA16UI: 288 case GL_RGBA8: 289 case GL_RGBA8I: 290 case GL_RGBA8UI: 291 case GL_SRGB8_ALPHA8: 292 case GL_RGB10_A2: 293 case GL_RGB10_A2UI: 294 case GL_RGBA4: 295 case GL_RGB5_A1: 296 case GL_RGB8: 297 case GL_RGB565: 298 case GL_RG32I: 299 case GL_RG32UI: 300 case GL_RG16I: 301 case GL_RG16UI: 302 case GL_RG8: 303 case GL_RG8I: 304 case GL_RG8UI: 305 case GL_R32I: 306 case GL_R32UI: 307 case GL_R16I: 308 case GL_R16UI: 309 case GL_R8: 310 case GL_R8I: 311 case GL_R8UI: 312 case GL_DEPTH_COMPONENT32F: 313 case GL_DEPTH_COMPONENT24: 314 case GL_DEPTH_COMPONENT16: 315 case GL_DEPTH32F_STENCIL8: 316 case GL_DEPTH24_STENCIL8: 317 case GL_STENCIL_INDEX8: 318 return 4; 319 320 // GL_EXT_color_buffer_float 321 case GL_R11F_G11F_B10F: 322 case GL_RG16F: 323 case GL_R16F: 324 return 4; 325 326 case GL_RGBA32F: 327 case GL_RGBA16F: 328 case GL_RG32F: 329 case GL_R32F: 330 return 0; 331 332 // GL_EXT_color_buffer_half_float 333 case GL_RGB16F: 334 return 0; 335 336 default: 337 DE_FATAL("Unknown format"); 338 return 0; 339 } 340 } 341 342 static std::vector<int> querySampleCounts (const glw::Functions& gl, deUint32 format) 343 { 344 int numSampleCounts = 0; 345 std::vector<int> sampleCounts; 346 347 gl.getInternalformativ(GL_RENDERBUFFER, format, GL_NUM_SAMPLE_COUNTS, 1, &numSampleCounts); 348 349 if (numSampleCounts > 0) 350 { 351 sampleCounts.resize(numSampleCounts); 352 gl.getInternalformativ(GL_RENDERBUFFER, format, GL_SAMPLES, (glw::GLsizei)sampleCounts.size(), &sampleCounts[0]); 353 } 354 355 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query sample counts for format"); 356 357 return sampleCounts; 358 } 359 360 void FboTestCase::checkSampleCount (deUint32 sizedFormat, int numSamples) 361 { 362 const int minSampleCount = getMinimumSampleCount(sizedFormat); 363 364 if (numSamples > minSampleCount) 365 { 366 // Exceeds spec-mandated minimum - need to check. 367 const std::vector<int> supportedSampleCounts = querySampleCounts(m_context.getRenderContext().getFunctions(), sizedFormat); 368 369 if (std::find(supportedSampleCounts.begin(), supportedSampleCounts.end(), numSamples) == supportedSampleCounts.end()) 370 throw tcu::NotSupportedError("Sample count not supported"); 371 } 372 } 373 374 void FboTestCase::clearColorBuffer (const tcu::TextureFormat& format, const tcu::Vec4& value) 375 { 376 FboTestUtil::clearColorBuffer(*getCurrentContext(), format, value); 377 } 378 379 } // Functional 380 } // gles31 381 } // deqp 382