1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program EGL 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 EGL image tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "teglImageFormatTests.hpp" 25 26 #include "deStringUtil.hpp" 27 #include "deSTLUtil.hpp" 28 29 #include "tcuTestLog.hpp" 30 #include "tcuSurface.hpp" 31 #include "tcuTexture.hpp" 32 #include "tcuTextureUtil.hpp" 33 #include "tcuImageCompare.hpp" 34 #include "tcuCommandLine.hpp" 35 36 #include "egluNativeDisplay.hpp" 37 #include "egluNativeWindow.hpp" 38 #include "egluNativePixmap.hpp" 39 #include "egluConfigFilter.hpp" 40 #include "egluUnique.hpp" 41 #include "egluUtil.hpp" 42 43 #include "eglwLibrary.hpp" 44 #include "eglwEnums.hpp" 45 46 #include "gluCallLogWrapper.hpp" 47 #include "gluShaderProgram.hpp" 48 #include "gluStrUtil.hpp" 49 #include "gluTexture.hpp" 50 #include "gluPixelTransfer.hpp" 51 #include "gluObjectWrapper.hpp" 52 #include "gluTextureUtil.hpp" 53 54 #include "glwEnums.hpp" 55 #include "glwFunctions.hpp" 56 57 #include "teglImageUtil.hpp" 58 #include "teglAndroidUtil.hpp" 59 60 #include <vector> 61 #include <string> 62 #include <set> 63 64 using std::vector; 65 using std::set; 66 using std::string; 67 68 using de::MovePtr; 69 using de::UniquePtr; 70 71 using glu::Framebuffer; 72 using glu::Renderbuffer; 73 using glu::Texture; 74 75 using eglu::UniqueImage; 76 77 using tcu::ConstPixelBufferAccess; 78 79 using namespace glw; 80 using namespace eglw; 81 82 namespace deqp 83 { 84 namespace egl 85 { 86 87 namespace 88 { 89 90 glu::ProgramSources programSources (const string& vertexSource, const string& fragmentSource) 91 { 92 glu::ProgramSources sources; 93 94 sources << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource); 95 96 return sources; 97 } 98 99 class Program : public glu::ShaderProgram 100 { 101 public: 102 Program (const glw::Functions& gl, const char* vertexSource, const char* fragmentSource) 103 : glu::ShaderProgram(gl, programSources(vertexSource, fragmentSource)) {} 104 }; 105 106 } // anonymous 107 108 namespace Image 109 { 110 111 class ImageApi; 112 113 class IllegalRendererException : public std::exception 114 { 115 }; 116 117 class Action 118 { 119 public: 120 virtual ~Action (void) {} 121 virtual bool invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& refImg) const = 0; 122 virtual string getRequiredExtension (void) const = 0; 123 }; 124 125 struct TestSpec 126 { 127 std::string name; 128 std::string desc; 129 130 enum ApiContext 131 { 132 API_GLES2 = 0, 133 //API_VG 134 //API_GLES1 135 136 API_LAST 137 }; 138 139 struct Operation 140 { 141 Operation (int apiIndex_, const Action& action_) : apiIndex(apiIndex_), action(&action_) {} 142 int apiIndex; 143 const Action* action; 144 }; 145 146 vector<ApiContext> contexts; 147 vector<Operation> operations; 148 149 }; 150 151 class ImageApi 152 { 153 public: 154 ImageApi (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface); 155 virtual ~ImageApi (void) {} 156 157 protected: 158 const Library& m_egl; 159 int m_contextId; 160 EGLDisplay m_display; 161 EGLSurface m_surface; 162 }; 163 164 ImageApi::ImageApi (const Library& egl, int contextId, EGLDisplay display, EGLSurface surface) 165 : m_egl (egl) 166 , m_contextId (contextId) 167 , m_display (display) 168 , m_surface (surface) 169 { 170 } 171 172 class GLES2ImageApi : public ImageApi, private glu::CallLogWrapper 173 { 174 public: 175 class GLES2Action : public Action 176 { 177 public: 178 bool invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; 179 virtual bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const = 0; 180 }; 181 182 class Create : public GLES2Action 183 { 184 public: 185 Create (MovePtr<ImageSource> imgSource) : m_imgSource(imgSource) {} 186 string getRequiredExtension (void) const { return m_imgSource->getRequiredExtension(); } 187 bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; 188 glw::GLenum getFormat (void) const { return m_imgSource->getFormat(); } 189 190 private: 191 UniquePtr<ImageSource> m_imgSource; 192 }; 193 194 class Render : public GLES2Action 195 { 196 public: 197 string getRequiredExtension (void) const { return "GL_OES_EGL_image"; } 198 }; 199 200 class RenderTexture2D : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; }; 201 class RenderTextureCubemap : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; }; 202 class RenderReadPixelsRenderbuffer : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; }; 203 class RenderDepthbuffer : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; }; 204 class RenderStencilbuffer : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; }; 205 class RenderTryAll : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; }; 206 207 class Modify : public GLES2Action 208 { 209 public: 210 string getRequiredExtension (void) const { return "GL_OES_EGL_image"; } 211 }; 212 213 class ModifyTexSubImage : public Modify 214 { 215 public: 216 ModifyTexSubImage (GLenum format, GLenum type) : m_format(format), m_type(type) {} 217 bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; 218 GLenum getFormat (void) const { return m_format; } 219 220 private: 221 GLenum m_format; 222 GLenum m_type; 223 }; 224 225 class ModifyRenderbuffer : public Modify 226 { 227 public: 228 bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; 229 230 protected: 231 virtual void initializeRbo (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const = 0; 232 }; 233 234 class ModifyRenderbufferClearColor : public ModifyRenderbuffer 235 { 236 public: 237 ModifyRenderbufferClearColor (tcu::Vec4 color) : m_color(color) {} 238 239 protected: 240 void initializeRbo (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const; 241 242 tcu::Vec4 m_color; 243 }; 244 245 class ModifyRenderbufferClearDepth : public ModifyRenderbuffer 246 { 247 public: 248 ModifyRenderbufferClearDepth (GLfloat depth) : m_depth(depth) {} 249 250 protected: 251 void initializeRbo (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const; 252 253 GLfloat m_depth; 254 }; 255 256 class ModifyRenderbufferClearStencil : public ModifyRenderbuffer 257 { 258 public: 259 ModifyRenderbufferClearStencil (GLint stencil) : m_stencil(stencil) {} 260 261 protected: 262 void initializeRbo (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const; 263 264 GLint m_stencil; 265 }; 266 267 GLES2ImageApi (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config); 268 ~GLES2ImageApi (void); 269 270 private: 271 EGLContext m_context; 272 const glw::Functions& m_gl; 273 274 MovePtr<UniqueImage> createImage (const ImageSource& source, const ClientBuffer& buffer) const; 275 }; 276 277 GLES2ImageApi::GLES2ImageApi (const Library& egl, const glw::Functions& gl, int contextId, tcu::TestLog& log, EGLDisplay display, EGLSurface surface, EGLConfig config) 278 : ImageApi (egl, contextId, display, surface) 279 , glu::CallLogWrapper (gl, log) 280 , m_context (DE_NULL) 281 , m_gl (gl) 282 { 283 const EGLint attriblist[] = 284 { 285 EGL_CONTEXT_CLIENT_VERSION, 2, 286 EGL_NONE 287 }; 288 289 EGLint configId = -1; 290 EGLU_CHECK_CALL(m_egl, getConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId)); 291 getLog() << tcu::TestLog::Message << "Creating gles2 context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage; 292 egl.bindAPI(EGL_OPENGL_ES_API); 293 m_context = m_egl.createContext(m_display, config, EGL_NO_CONTEXT, attriblist); 294 EGLU_CHECK_MSG(m_egl, "Failed to create GLES2 context"); 295 296 egl.makeCurrent(display, m_surface, m_surface, m_context); 297 EGLU_CHECK_MSG(m_egl, "Failed to make context current"); 298 } 299 300 GLES2ImageApi::~GLES2ImageApi (void) 301 { 302 m_egl.makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 303 m_egl.destroyContext(m_display, m_context); 304 } 305 306 bool GLES2ImageApi::GLES2Action::invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const 307 { 308 GLES2ImageApi& gles2Api = dynamic_cast<GLES2ImageApi&>(api); 309 310 gles2Api.m_egl.makeCurrent(gles2Api.m_display, gles2Api.m_surface, gles2Api.m_surface, gles2Api.m_context); 311 return invokeGLES2(gles2Api, image, ref); 312 } 313 314 315 bool GLES2ImageApi::Create::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const 316 { 317 de::UniquePtr<ClientBuffer> buffer (m_imgSource->createBuffer(api.m_gl, &ref)); 318 image = api.createImage(*m_imgSource, *buffer); 319 return true; 320 } 321 322 MovePtr<UniqueImage> GLES2ImageApi::createImage (const ImageSource& source, const ClientBuffer& buffer) const 323 { 324 const EGLImageKHR image = source.createImage(m_egl, m_display, m_context, buffer.get()); 325 return MovePtr<UniqueImage>(new UniqueImage(m_egl, m_display, image)); 326 } 327 328 static void imageTargetTexture2D (const Library& egl, const glw::Functions& gl, GLeglImageOES img) 329 { 330 gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, img); 331 { 332 const GLenum error = gl.getError(); 333 334 if (error == GL_INVALID_OPERATION) 335 TCU_THROW(NotSupportedError, "Creating texture2D from EGLImage type not supported"); 336 337 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()"); 338 EGLU_CHECK_MSG(egl, "glEGLImageTargetTexture2DOES()"); 339 } 340 } 341 342 static void imageTargetRenderbuffer (const Library& egl, const glw::Functions& gl, GLeglImageOES img) 343 { 344 gl.eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img); 345 { 346 const GLenum error = gl.getError(); 347 348 if (error == GL_INVALID_OPERATION) 349 TCU_THROW(NotSupportedError, "Creating renderbuffer from EGLImage type not supported"); 350 351 GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetRenderbufferStorageOES()"); 352 EGLU_CHECK_MSG(egl, "glEGLImageTargetRenderbufferStorageOES()"); 353 } 354 } 355 356 static void framebufferRenderbuffer (const glw::Functions& gl, GLenum attachment, GLuint rbo) 357 { 358 GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo)); 359 TCU_CHECK_AND_THROW(NotSupportedError, 360 gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, 361 ("EGLImage as " + string(glu::getFramebufferAttachmentName(attachment)) + " not supported").c_str()); 362 } 363 364 static const float squareTriangleCoords[] = 365 { 366 -1.0, -1.0, 367 1.0, -1.0, 368 1.0, 1.0, 369 370 1.0, 1.0, 371 -1.0, 1.0, 372 -1.0, -1.0 373 }; 374 375 bool GLES2ImageApi::RenderTexture2D::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 376 { 377 const glw::Functions& gl = api.m_gl; 378 tcu::TestLog& log = api.getLog(); 379 Texture srcTex (gl); 380 381 // Branch only taken in TryAll case 382 if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D) 383 throw IllegalRendererException(); // Skip, GLES2 does not support sampling depth textures 384 if (reference.getFormat().order == tcu::TextureFormat::S) 385 throw IllegalRendererException(); // Skip, GLES2 does not support sampling stencil textures 386 387 gl.clearColor(0.0, 0.0, 0.0, 0.0); 388 gl.viewport(0, 0, reference.getWidth(), reference.getHeight()); 389 gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 390 gl.disable(GL_DEPTH_TEST); 391 392 log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << api.m_contextId << tcu::TestLog::EndMessage; 393 TCU_CHECK(**img != EGL_NO_IMAGE_KHR); 394 395 GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex)); 396 imageTargetTexture2D(api.m_egl, gl, **img); 397 398 GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 399 GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 400 GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 401 GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 402 403 const char* const vertexShader = 404 "attribute highp vec2 a_coord;\n" 405 "varying mediump vec2 v_texCoord;\n" 406 "void main(void) {\n" 407 "\tv_texCoord = vec2((a_coord.x + 1.0) * 0.5, (a_coord.y + 1.0) * 0.5);\n" 408 "\tgl_Position = vec4(a_coord, -0.1, 1.0);\n" 409 "}\n"; 410 411 const char* const fragmentShader = 412 "varying mediump vec2 v_texCoord;\n" 413 "uniform sampler2D u_sampler;\n" 414 "void main(void) {\n" 415 "\tmediump vec4 texColor = texture2D(u_sampler, v_texCoord);\n" 416 "\tgl_FragColor = vec4(texColor);\n" 417 "}"; 418 419 Program program(gl, vertexShader, fragmentShader); 420 TCU_CHECK(program.isOk()); 421 422 GLuint glProgram = program.getProgram(); 423 GLU_CHECK_GLW_CALL(gl, useProgram(glProgram)); 424 425 GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord"); 426 TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord"); 427 428 GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler"); 429 TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler"); 430 431 GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex)); 432 GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0)); 433 GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc)); 434 GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords)); 435 436 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6)); 437 GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc)); 438 GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0)); 439 440 tcu::Surface refSurface (reference.getWidth(), reference.getHeight()); 441 tcu::Surface screen (reference.getWidth(), reference.getHeight()); 442 GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr())); 443 444 tcu::copy(refSurface.getAccess(), reference.getLevel(0)); 445 446 float threshold = 0.05f; 447 bool match = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT); 448 449 return match; 450 } 451 452 bool GLES2ImageApi::RenderDepthbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 453 { 454 const glw::Functions& gl = api.m_gl; 455 tcu::TestLog& log = api.getLog(); 456 Framebuffer framebuffer (gl); 457 Renderbuffer renderbufferColor (gl); 458 Renderbuffer renderbufferDepth (gl); 459 const tcu::RGBA compareThreshold (32, 32, 32, 32); // layer colors are far apart, large thresholds are ok 460 461 // Branch only taken in TryAll case 462 if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::D) 463 throw IllegalRendererException(); // Skip, interpreting non-depth data as depth data is not meaningful 464 465 log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage; 466 467 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer)); 468 469 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor)); 470 GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight())); 471 framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor); 472 473 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferDepth)); 474 imageTargetRenderbuffer(api.m_egl, gl, **img); 475 framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, *renderbufferDepth); 476 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0)); 477 478 GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight())); 479 480 // Render 481 const char* vertexShader = 482 "attribute highp vec2 a_coord;\n" 483 "uniform highp float u_depth;\n" 484 "void main(void) {\n" 485 "\tgl_Position = vec4(a_coord, u_depth, 1.0);\n" 486 "}\n"; 487 488 const char* fragmentShader = 489 "uniform mediump vec4 u_color;\n" 490 "void main(void) {\n" 491 "\tgl_FragColor = u_color;\n" 492 "}"; 493 494 Program program(gl, vertexShader, fragmentShader); 495 TCU_CHECK(program.isOk()); 496 497 GLuint glProgram = program.getProgram(); 498 GLU_CHECK_GLW_CALL(gl, useProgram(glProgram)); 499 500 GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord"); 501 TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord"); 502 503 GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color"); 504 TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color"); 505 506 GLuint depthLoc = gl.getUniformLocation(glProgram, "u_depth"); 507 TCU_CHECK_MSG((int)depthLoc != (int)-1, "Couldn't find uniform u_depth"); 508 509 GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f)); 510 GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT)); 511 512 tcu::Vec4 depthLevelColors[] = { 513 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), 514 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), 515 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), 516 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), 517 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), 518 519 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), 520 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 521 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), 522 tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), 523 tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f) 524 }; 525 526 GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc)); 527 GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords)); 528 529 GLU_CHECK_GLW_CALL(gl, enable(GL_DEPTH_TEST)); 530 GLU_CHECK_GLW_CALL(gl, depthFunc(GL_LESS)); 531 GLU_CHECK_GLW_CALL(gl, depthMask(GL_FALSE)); 532 533 for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++) 534 { 535 const tcu::Vec4 color = depthLevelColors[level]; 536 const float clipDepth = ((level + 1) * 0.1f) * 2.0f - 1.0f; // depth in clip coords 537 538 GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w())); 539 GLU_CHECK_GLW_CALL(gl, uniform1f(depthLoc, clipDepth)); 540 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6)); 541 } 542 543 GLU_CHECK_GLW_CALL(gl, depthMask(GL_TRUE)); 544 GLU_CHECK_GLW_CALL(gl, disable(GL_DEPTH_TEST)); 545 GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc)); 546 547 const ConstPixelBufferAccess& refAccess = reference.getLevel(0); 548 tcu::Surface screen (reference.getWidth(), reference.getHeight()); 549 tcu::Surface referenceScreen (reference.getWidth(), reference.getHeight()); 550 551 gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()); 552 553 for (int y = 0; y < reference.getHeight(); y++) 554 { 555 for (int x = 0; x < reference.getWidth(); x++) 556 { 557 tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f); 558 559 for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++) 560 { 561 if ((level + 1) * 0.1f < refAccess.getPixDepth(x, y)) 562 result = depthLevelColors[level]; 563 } 564 565 referenceScreen.getAccess().setPixel(result, x, y); 566 } 567 } 568 569 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0)); 570 GLU_CHECK_GLW_CALL(gl, finish()); 571 572 return tcu::pixelThresholdCompare(log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT); 573 } 574 575 bool GLES2ImageApi::RenderStencilbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 576 { 577 // Branch only taken in TryAll case 578 if (reference.getFormat().order != tcu::TextureFormat::DS && reference.getFormat().order != tcu::TextureFormat::S) 579 throw IllegalRendererException(); // Skip, interpreting non-stencil data as stencil data is not meaningful 580 581 const glw::Functions& gl = api.m_gl; 582 tcu::TestLog& log = api.getLog(); 583 Framebuffer framebuffer (gl); 584 Renderbuffer renderbufferColor (gl); 585 Renderbuffer renderbufferStencil (gl); 586 const tcu::RGBA compareThreshold (32, 32, 32, 32); // layer colors are far apart, large thresholds are ok 587 const deUint32 numStencilBits = tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(reference.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x(); 588 const deUint32 maxStencil = deBitMask32(0, numStencilBits); 589 590 log << tcu::TestLog::Message << "Rendering with stencil buffer" << tcu::TestLog::EndMessage; 591 592 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer)); 593 594 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor)); 595 GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight())); 596 framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor); 597 598 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferStencil)); 599 imageTargetRenderbuffer(api.m_egl, gl, **img); 600 framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, *renderbufferStencil); 601 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0)); 602 603 GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight())); 604 605 // Render 606 const char* vertexShader = 607 "attribute highp vec2 a_coord;\n" 608 "void main(void) {\n" 609 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n" 610 "}\n"; 611 612 const char* fragmentShader = 613 "uniform mediump vec4 u_color;\n" 614 "void main(void) {\n" 615 "\tgl_FragColor = u_color;\n" 616 "}"; 617 618 Program program(gl, vertexShader, fragmentShader); 619 TCU_CHECK(program.isOk()); 620 621 GLuint glProgram = program.getProgram(); 622 GLU_CHECK_GLW_CALL(gl, useProgram(glProgram)); 623 624 GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord"); 625 TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord"); 626 627 GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color"); 628 TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color"); 629 630 GLU_CHECK_GLW_CALL(gl, clearColor(0.5f, 1.0f, 0.5f, 1.0f)); 631 GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT)); 632 633 tcu::Vec4 stencilLevelColors[] = { 634 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), 635 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), 636 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), 637 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), 638 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), 639 640 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), 641 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 642 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), 643 tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), 644 tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f) 645 }; 646 647 GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc)); 648 GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords)); 649 650 GLU_CHECK_GLW_CALL(gl, enable(GL_STENCIL_TEST)); 651 GLU_CHECK_GLW_CALL(gl, stencilOp(GL_KEEP, GL_KEEP, GL_KEEP)); 652 653 for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++) 654 { 655 const tcu::Vec4 color = stencilLevelColors[level]; 656 const int stencil = (int)(((level + 1) * 0.1f) * maxStencil); 657 658 GLU_CHECK_GLW_CALL(gl, stencilFunc(GL_LESS, stencil, 0xFFFFFFFFu)); 659 GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w())); 660 GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, 6)); 661 } 662 663 GLU_CHECK_GLW_CALL(gl, disable(GL_STENCIL_TEST)); 664 GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc)); 665 666 const ConstPixelBufferAccess& refAccess = reference.getLevel(0); 667 tcu::Surface screen (reference.getWidth(), reference.getHeight()); 668 tcu::Surface referenceScreen (reference.getWidth(), reference.getHeight()); 669 670 gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()); 671 672 for (int y = 0; y < reference.getHeight(); y++) 673 for (int x = 0; x < reference.getWidth(); x++) 674 { 675 tcu::Vec4 result = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f); 676 677 for (int level = 0; level < DE_LENGTH_OF_ARRAY(stencilLevelColors); level++) 678 { 679 const int levelStencil = (int)(((level + 1) * 0.1f) * maxStencil); 680 if (levelStencil < refAccess.getPixStencil(x, y)) 681 result = stencilLevelColors[level]; 682 } 683 684 referenceScreen.getAccess().setPixel(result, x, y); 685 } 686 687 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0)); 688 GLU_CHECK_GLW_CALL(gl, finish()); 689 690 return tcu::pixelThresholdCompare(log, "StencilResult", "Result from rendering with stencil buffer", referenceScreen, screen, compareThreshold, tcu::COMPARE_LOG_RESULT); 691 } 692 693 bool GLES2ImageApi::RenderReadPixelsRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 694 { 695 const glw::Functions& gl = api.m_gl; 696 const tcu::IVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(reference.getFormat()); 697 const tcu::IVec4 threshold (2 * (tcu::IVec4(1) << (tcu::IVec4(8) - bitDepth))); 698 const tcu::RGBA threshold8 ((deUint8)(de::clamp(threshold[0], 0, 255)), (deUint8)(de::clamp(threshold[1], 0, 255)), (deUint8)(de::clamp(threshold[2], 0, 255)), (deUint8)(de::clamp(threshold[3], 0, 255))); 699 tcu::TestLog& log = api.getLog(); 700 Framebuffer framebuffer (gl); 701 Renderbuffer renderbuffer (gl); 702 tcu::Surface screen (reference.getWidth(), reference.getHeight()); 703 tcu::Surface refSurface (reference.getWidth(), reference.getHeight()); 704 705 // Branch only taken in TryAll case 706 if (reference.getFormat().order == tcu::TextureFormat::DS || reference.getFormat().order == tcu::TextureFormat::D) 707 throw IllegalRendererException(); // Skip, GLES2 does not support ReadPixels for depth attachments 708 if (reference.getFormat().order == tcu::TextureFormat::S) 709 throw IllegalRendererException(); // Skip, GLES2 does not support ReadPixels for stencil attachments 710 711 log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage; 712 713 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer)); 714 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer)); 715 imageTargetRenderbuffer(api.m_egl, gl, **img); 716 framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer); 717 718 GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight())); 719 720 gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()); 721 722 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0)); 723 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0)); 724 GLU_CHECK_GLW_CALL(gl, finish()); 725 726 tcu::copy(refSurface.getAccess(), reference.getLevel(0)); 727 728 return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT); 729 730 } 731 732 bool GLES2ImageApi::RenderTryAll::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 733 { 734 bool foundSupported = false; 735 tcu::TestLog& log = api.getLog(); 736 GLES2ImageApi::RenderTexture2D renderTex2D; 737 GLES2ImageApi::RenderReadPixelsRenderbuffer renderReadPixels; 738 GLES2ImageApi::RenderDepthbuffer renderDepth; 739 GLES2ImageApi::RenderStencilbuffer renderStencil; 740 Action* actions[] = { &renderTex2D, &renderReadPixels, &renderDepth, &renderStencil }; 741 742 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx) 743 { 744 try 745 { 746 if (!actions[ndx]->invoke(api, img, reference)) 747 return false; 748 749 foundSupported = true; 750 } 751 catch (const tcu::NotSupportedError& error) 752 { 753 log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage; 754 } 755 catch (const IllegalRendererException&) 756 { 757 // not valid renderer 758 } 759 } 760 761 if (!foundSupported) 762 throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__); 763 764 return true; 765 } 766 767 bool GLES2ImageApi::ModifyTexSubImage::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 768 { 769 const glw::Functions& gl = api.m_gl; 770 tcu::TestLog& log = api.getLog(); 771 glu::Texture srcTex (gl); 772 const int xOffset = 8; 773 const int yOffset = 16; 774 const int xSize = de::clamp(16, 0, reference.getWidth() - xOffset); 775 const int ySize = de::clamp(16, 0, reference.getHeight() - yOffset); 776 tcu::Texture2D src (glu::mapGLTransferFormat(m_format, m_type), xSize, ySize); 777 778 log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage; 779 780 src.allocLevel(0); 781 tcu::fillWithComponentGradients(src.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 782 783 GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex)); 784 imageTargetTexture2D(api.m_egl, gl, **img); 785 GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr())); 786 GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0)); 787 GLU_CHECK_GLW_CALL(gl, finish()); 788 789 tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0)); 790 791 return true; 792 } 793 794 bool GLES2ImageApi::ModifyRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const 795 { 796 const glw::Functions& gl = api.m_gl; 797 tcu::TestLog& log = api.getLog(); 798 glu::Framebuffer framebuffer (gl); 799 glu::Renderbuffer renderbuffer (gl); 800 801 log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage; 802 803 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer)); 804 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer)); 805 806 imageTargetRenderbuffer(api.m_egl, gl, **img); 807 808 initializeRbo(api, *renderbuffer, reference); 809 810 GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0)); 811 GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0)); 812 813 GLU_CHECK_GLW_CALL(gl, finish()); 814 815 return true; 816 } 817 818 void GLES2ImageApi::ModifyRenderbufferClearColor::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const 819 { 820 const glw::Functions& gl = api.m_gl; 821 822 framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer); 823 824 GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight())); 825 GLU_CHECK_GLW_CALL(gl, clearColor(m_color.x(), m_color.y(), m_color.z(), m_color.w())); 826 GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT)); 827 828 tcu::clear(reference.getLevel(0), m_color); 829 } 830 831 void GLES2ImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const 832 { 833 const glw::Functions& gl = api.m_gl; 834 835 framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer); 836 837 GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight())); 838 GLU_CHECK_GLW_CALL(gl, clearDepthf(m_depth)); 839 GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT)); 840 841 tcu::clearDepth(reference.getLevel(0), m_depth); 842 } 843 844 void GLES2ImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const 845 { 846 const glw::Functions& gl = api.m_gl; 847 848 framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer); 849 850 GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight())); 851 GLU_CHECK_GLW_CALL(gl, clearStencil(m_stencil)); 852 GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT)); 853 854 tcu::clearStencil(reference.getLevel(0), m_stencil); 855 } 856 857 class ImageFormatCase : public TestCase, private glu::CallLogWrapper 858 { 859 public: 860 ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec); 861 ~ImageFormatCase (void); 862 863 void init (void); 864 void deinit (void); 865 IterateResult iterate (void); 866 void checkExtensions (void); 867 868 private: 869 EGLConfig getConfig (void); 870 871 const TestSpec m_spec; 872 873 vector<ImageApi*> m_apiContexts; 874 875 EGLDisplay m_display; 876 eglu::NativeWindow* m_window; 877 EGLSurface m_surface; 878 EGLConfig m_config; 879 int m_curIter; 880 MovePtr<UniqueImage>m_img; 881 tcu::Texture2D m_refImg; 882 glw::Functions m_gl; 883 }; 884 885 EGLConfig ImageFormatCase::getConfig (void) 886 { 887 const EGLint attribList[] = 888 { 889 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 890 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 891 EGL_RED_SIZE, 8, 892 EGL_BLUE_SIZE, 8, 893 EGL_GREEN_SIZE, 8, 894 EGL_ALPHA_SIZE, 8, 895 EGL_DEPTH_SIZE, 8, 896 EGL_NONE 897 }; 898 899 return eglu::chooseSingleConfig(m_eglTestCtx.getLibrary(), m_display, attribList); 900 } 901 902 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec) 903 : TestCase (eglTestCtx, spec.name.c_str(), spec.desc.c_str()) 904 , glu::CallLogWrapper (m_gl, eglTestCtx.getTestContext().getLog()) 905 , m_spec (spec) 906 , m_display (EGL_NO_DISPLAY) 907 , m_window (DE_NULL) 908 , m_surface (EGL_NO_SURFACE) 909 , m_config (0) 910 , m_curIter (0) 911 , m_refImg (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1) 912 { 913 } 914 915 ImageFormatCase::~ImageFormatCase (void) 916 { 917 deinit(); 918 } 919 920 void ImageFormatCase::checkExtensions (void) 921 { 922 const Library& egl = m_eglTestCtx.getLibrary(); 923 const EGLDisplay dpy = m_display; 924 set<string> exts; 925 const vector<string> glExts = de::splitString((const char*) m_gl.getString(GL_EXTENSIONS)); 926 const vector<string> eglExts = eglu::getClientExtensions(egl, dpy); 927 928 exts.insert(glExts.begin(), glExts.end()); 929 exts.insert(eglExts.begin(), eglExts.end()); 930 931 if (eglu::getVersion(egl, dpy) >= eglu::Version(1, 5)) 932 { 933 // EGL 1.5 has built-in support for EGLImage and GL sources 934 exts.insert("EGL_KHR_image_base"); 935 exts.insert("EGL_KHR_gl_texture_2D_image"); 936 exts.insert("EGL_KHR_gl_texture_cubemap_image"); 937 exts.insert("EGL_KHR_gl_renderbuffer_image"); 938 } 939 940 if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image")) 941 { 942 getLog() << tcu::TestLog::Message 943 << "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported." 944 << "One should be supported." 945 << tcu::TestLog::EndMessage; 946 TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base"); 947 } 948 949 for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++) 950 { 951 const TestSpec::Operation& op = m_spec.operations[operationNdx]; 952 const string ext = op.action->getRequiredExtension(); 953 954 if (!de::contains(exts, ext)) 955 TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str()); 956 } 957 } 958 959 void ImageFormatCase::init (void) 960 { 961 const Library& egl = m_eglTestCtx.getLibrary(); 962 const eglu::NativeWindowFactory& windowFactory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine()); 963 964 try 965 { 966 m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); 967 m_config = getConfig(); 968 m_window = windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))); 969 m_surface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display, m_config, DE_NULL); 970 971 { 972 const char* extensions[] = { "GL_OES_EGL_image" }; 973 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0), DE_LENGTH_OF_ARRAY(extensions), &extensions[0]); 974 } 975 976 for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++) 977 { 978 ImageApi* api = DE_NULL; 979 switch (m_spec.contexts[contextNdx]) 980 { 981 case TestSpec::API_GLES2: 982 { 983 api = new GLES2ImageApi(egl, m_gl, contextNdx, getLog(), m_display, m_surface, m_config); 984 break; 985 } 986 987 default: 988 DE_ASSERT(false); 989 break; 990 } 991 m_apiContexts.push_back(api); 992 } 993 checkExtensions(); 994 } 995 catch (...) 996 { 997 deinit(); 998 throw; 999 } 1000 } 1001 1002 void ImageFormatCase::deinit (void) 1003 { 1004 const Library& egl = m_eglTestCtx.getLibrary(); 1005 1006 for (int contexNdx = 0 ; contexNdx < (int)m_apiContexts.size(); contexNdx++) 1007 delete m_apiContexts[contexNdx]; 1008 1009 m_apiContexts.clear(); 1010 1011 if (m_surface != EGL_NO_SURFACE) 1012 { 1013 egl.destroySurface(m_display, m_surface); 1014 m_surface = EGL_NO_SURFACE; 1015 } 1016 1017 delete m_window; 1018 m_window = DE_NULL; 1019 1020 if (m_display != EGL_NO_DISPLAY) 1021 { 1022 egl.terminate(m_display); 1023 m_display = EGL_NO_DISPLAY; 1024 } 1025 } 1026 1027 TestCase::IterateResult ImageFormatCase::iterate (void) 1028 { 1029 const TestSpec::Operation& op = m_spec.operations[m_curIter++]; 1030 ImageApi& api = *m_apiContexts[op.apiIndex]; 1031 const bool isOk = op.action->invoke(api, m_img, m_refImg); 1032 1033 if (isOk && m_curIter < (int)m_spec.operations.size()) 1034 return CONTINUE; 1035 else if (isOk) 1036 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1037 else 1038 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1039 1040 return STOP; 1041 } 1042 1043 struct LabeledAction 1044 { 1045 string label; 1046 MovePtr<Action> action; 1047 }; 1048 1049 // A simple vector mockup that we need because MovePtr isn't copy-constructible. 1050 struct LabeledActions 1051 { 1052 LabeledActions (void) : m_numActions(0){} 1053 LabeledAction& operator[] (int ndx) { DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; } 1054 void add (const string& label, MovePtr<Action> action); 1055 int size (void) const { return m_numActions; } 1056 private: 1057 LabeledAction m_actions[32]; 1058 int m_numActions; 1059 }; 1060 1061 void LabeledActions::add (const string& label, MovePtr<Action> action) 1062 { 1063 DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions)); 1064 m_actions[m_numActions].label = label; 1065 m_actions[m_numActions].action = action; 1066 ++m_numActions; 1067 } 1068 1069 class ImageTests : public TestCaseGroup 1070 { 1071 protected: 1072 ImageTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1073 : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {} 1074 1075 void addCreateTexture (const string& name, EGLenum source, GLenum format, GLenum type); 1076 void addCreateRenderbuffer (const string& name, GLenum format); 1077 void addCreateAndroidNative (const string& name, GLenum format); 1078 void addCreateTexture2DActions (const string& prefix); 1079 void addCreateTextureCubemapActions (const string& suffix, GLenum format, GLenum type); 1080 void addCreateRenderbufferActions (void); 1081 void addCreateAndroidNativeActions (void); 1082 1083 LabeledActions m_createActions; 1084 }; 1085 1086 void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum format, GLenum type) 1087 { 1088 m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createTextureImageSource(source, format, type)))); 1089 } 1090 1091 void ImageTests::addCreateRenderbuffer (const string& name, GLenum format) 1092 { 1093 m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createRenderbufferImageSource(format)))); 1094 } 1095 1096 void ImageTests::addCreateAndroidNative (const string& name, GLenum format) 1097 { 1098 m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createAndroidNativeImageSource(format)))); 1099 } 1100 1101 void ImageTests::addCreateTexture2DActions (const string& prefix) 1102 { 1103 addCreateTexture(prefix + "rgb8", EGL_GL_TEXTURE_2D_KHR, GL_RGB, GL_UNSIGNED_BYTE); 1104 addCreateTexture(prefix + "rgb565", EGL_GL_TEXTURE_2D_KHR, GL_RGB, GL_UNSIGNED_SHORT_5_6_5); 1105 addCreateTexture(prefix + "rgba8", EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_UNSIGNED_BYTE); 1106 addCreateTexture(prefix + "rgba5_a1", EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1); 1107 addCreateTexture(prefix + "rgba4", EGL_GL_TEXTURE_2D_KHR, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4); 1108 } 1109 1110 void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum format, GLenum type) 1111 { 1112 addCreateTexture("cubemap_positive_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, format, type); 1113 addCreateTexture("cubemap_positive_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, format, type); 1114 addCreateTexture("cubemap_positive_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, format, type); 1115 addCreateTexture("cubemap_negative_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, format, type); 1116 addCreateTexture("cubemap_negative_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, format, type); 1117 addCreateTexture("cubemap_negative_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, format, type); 1118 } 1119 1120 void ImageTests::addCreateRenderbufferActions (void) 1121 { 1122 addCreateRenderbuffer("renderbuffer_rgba4", GL_RGBA4); 1123 addCreateRenderbuffer("renderbuffer_rgb5_a1", GL_RGB5_A1); 1124 addCreateRenderbuffer("renderbuffer_rgb565", GL_RGB565); 1125 addCreateRenderbuffer("renderbuffer_depth16", GL_DEPTH_COMPONENT16); 1126 addCreateRenderbuffer("renderbuffer_stencil", GL_STENCIL_INDEX8); 1127 } 1128 1129 void ImageTests::addCreateAndroidNativeActions (void) 1130 { 1131 addCreateAndroidNative("android_native_rgb565", GL_RGB565); 1132 addCreateAndroidNative("android_native_rgb8", GL_RGB8); 1133 addCreateAndroidNative("android_native_rgba4", GL_RGBA4); 1134 addCreateAndroidNative("android_native_rgb5_a1", GL_RGB5_A1); 1135 addCreateAndroidNative("android_native_rgba8", GL_RGBA8); 1136 } 1137 1138 class RenderTests : public ImageTests 1139 { 1140 protected: 1141 RenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1142 : ImageTests (eglTestCtx, name, desc) {} 1143 1144 void addRenderActions (void); 1145 LabeledActions m_renderActions; 1146 }; 1147 1148 void RenderTests::addRenderActions (void) 1149 { 1150 m_renderActions.add("texture", MovePtr<Action>(new GLES2ImageApi::RenderTexture2D())); 1151 m_renderActions.add("read_pixels", MovePtr<Action>(new GLES2ImageApi::RenderReadPixelsRenderbuffer())); 1152 m_renderActions.add("depth_buffer", MovePtr<Action>(new GLES2ImageApi::RenderDepthbuffer())); 1153 m_renderActions.add("stencil_buffer", MovePtr<Action>(new GLES2ImageApi::RenderStencilbuffer())); 1154 } 1155 1156 class SimpleCreationTests : public RenderTests 1157 { 1158 public: 1159 SimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {} 1160 void init (void); 1161 }; 1162 1163 bool isDepthFormat (GLenum format) 1164 { 1165 switch (format) 1166 { 1167 case GL_RGB: 1168 case GL_RGB8: 1169 case GL_RGB565: 1170 case GL_RGBA: 1171 case GL_RGBA4: 1172 case GL_RGBA8: 1173 case GL_RGB5_A1: 1174 return false; 1175 1176 case GL_DEPTH_COMPONENT16: 1177 return true; 1178 1179 case GL_STENCIL_INDEX8: 1180 return false; 1181 1182 default: 1183 DE_ASSERT(false); 1184 return false; 1185 } 1186 } 1187 1188 bool isStencilFormat (GLenum format) 1189 { 1190 switch (format) 1191 { 1192 case GL_RGB: 1193 case GL_RGB8: 1194 case GL_RGB565: 1195 case GL_RGBA: 1196 case GL_RGBA4: 1197 case GL_RGBA8: 1198 case GL_RGB5_A1: 1199 return false; 1200 1201 case GL_DEPTH_COMPONENT16: 1202 return false; 1203 1204 case GL_STENCIL_INDEX8: 1205 return true; 1206 1207 default: 1208 DE_ASSERT(false); 1209 return false; 1210 } 1211 } 1212 1213 bool isCompatibleCreateAndRenderActions (const Action& create, const Action& render) 1214 { 1215 if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create)) 1216 { 1217 const GLenum createFormat = gles2Create->getFormat(); 1218 1219 if (dynamic_cast<const GLES2ImageApi::RenderTexture2D*>(&render)) 1220 { 1221 // GLES2 does not have depth or stencil textures 1222 if (isDepthFormat(createFormat) || isStencilFormat(createFormat)) 1223 return false; 1224 } 1225 1226 if (dynamic_cast<const GLES2ImageApi::RenderReadPixelsRenderbuffer*>(&render)) 1227 { 1228 // GLES2 does not support readPixels for depth or stencil 1229 if (isDepthFormat(createFormat) || isStencilFormat(createFormat)) 1230 return false; 1231 } 1232 1233 if (dynamic_cast<const GLES2ImageApi::RenderDepthbuffer*>(&render)) 1234 { 1235 // Copying non-depth data to depth renderbuffer and expecting meaningful 1236 // results just doesn't make any sense. 1237 if (!isDepthFormat(createFormat)) 1238 return false; 1239 } 1240 1241 if (dynamic_cast<const GLES2ImageApi::RenderStencilbuffer*>(&render)) 1242 { 1243 // Copying non-stencil data to stencil renderbuffer and expecting meaningful 1244 // results just doesn't make any sense. 1245 if (!isStencilFormat(createFormat)) 1246 return false; 1247 } 1248 1249 return true; 1250 } 1251 else 1252 DE_ASSERT(false); 1253 1254 return false; 1255 } 1256 1257 void SimpleCreationTests::init (void) 1258 { 1259 addCreateTexture2DActions("texture_"); 1260 addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_UNSIGNED_BYTE); 1261 addCreateTextureCubemapActions("_rgb", GL_RGB, GL_UNSIGNED_BYTE); 1262 addCreateRenderbufferActions(); 1263 addCreateAndroidNativeActions(); 1264 addRenderActions(); 1265 1266 for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++) 1267 { 1268 const LabeledAction& createAction = m_createActions[createNdx]; 1269 1270 for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++) 1271 { 1272 const LabeledAction& renderAction = m_renderActions[renderNdx]; 1273 TestSpec spec; 1274 1275 if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action)) 1276 continue; 1277 1278 spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label; 1279 spec.desc = spec.name; 1280 spec.contexts.push_back(TestSpec::API_GLES2); 1281 spec.operations.push_back(TestSpec::Operation(0, *createAction.action)); 1282 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action)); 1283 1284 addChild(new ImageFormatCase(m_eglTestCtx, spec)); 1285 } 1286 } 1287 } 1288 1289 TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1290 { 1291 return new SimpleCreationTests(eglTestCtx, name, desc); 1292 } 1293 1294 bool isCompatibleFormats (GLenum createFormat, GLenum modifyFormat) 1295 { 1296 switch (createFormat) 1297 { 1298 case GL_RGB: 1299 case GL_RGB8: 1300 case GL_RGB565: 1301 if (modifyFormat == GL_RGB 1302 || modifyFormat == GL_RGB8 1303 || modifyFormat == GL_RGB565) 1304 return true; 1305 else 1306 return false; 1307 1308 case GL_RGBA: 1309 case GL_RGBA4: 1310 case GL_RGBA8: 1311 case GL_RGB5_A1: 1312 if (modifyFormat == GL_RGBA 1313 || modifyFormat == GL_RGBA8 1314 || modifyFormat == GL_RGBA4 1315 || modifyFormat == GL_RGB5_A1) 1316 return true; 1317 else 1318 return false; 1319 1320 case GL_DEPTH_COMPONENT16: 1321 case GL_STENCIL_INDEX8: 1322 return false; 1323 1324 default: 1325 DE_ASSERT(false); 1326 return false; 1327 } 1328 } 1329 1330 bool isCompatibleCreateAndModifyActions (const Action& create, const Action& modify) 1331 { 1332 if (const GLES2ImageApi::Create* gles2Create = dynamic_cast<const GLES2ImageApi::Create*>(&create)) 1333 { 1334 const GLenum createFormat = gles2Create->getFormat(); 1335 1336 if (const GLES2ImageApi::ModifyTexSubImage* gles2TexSubImageModify = dynamic_cast<const GLES2ImageApi::ModifyTexSubImage*>(&modify)) 1337 { 1338 const GLenum modifyFormat = gles2TexSubImageModify->getFormat(); 1339 1340 return isCompatibleFormats(createFormat, modifyFormat); 1341 } 1342 1343 if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearColor*>(&modify)) 1344 { 1345 // reintepreting color as non-color is not meaningful 1346 if (isDepthFormat(createFormat) || isStencilFormat(createFormat)) 1347 return false; 1348 } 1349 1350 if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearDepth*>(&modify)) 1351 { 1352 // reintepreting depth as non-depth is not meaningful 1353 if (!isDepthFormat(createFormat)) 1354 return false; 1355 } 1356 1357 if (dynamic_cast<const GLES2ImageApi::ModifyRenderbufferClearStencil*>(&modify)) 1358 { 1359 // reintepreting stencil as non-stencil is not meaningful 1360 if (!isStencilFormat(createFormat)) 1361 return false; 1362 } 1363 1364 return true; 1365 } 1366 else 1367 DE_ASSERT(false); 1368 1369 return false; 1370 } 1371 1372 class MultiContextRenderTests : public RenderTests 1373 { 1374 public: 1375 MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc); 1376 void init (void); 1377 void addClearActions (void); 1378 private: 1379 LabeledActions m_clearActions; 1380 }; 1381 1382 MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1383 : RenderTests (eglTestCtx, name, desc) 1384 { 1385 } 1386 1387 void MultiContextRenderTests::addClearActions (void) 1388 { 1389 m_clearActions.add("renderbuffer_clear_color", MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.8f, 0.2f, 0.9f, 1.0f)))); 1390 m_clearActions.add("renderbuffer_clear_depth", MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.75f))); 1391 m_clearActions.add("renderbuffer_clear_stencil", MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(97))); 1392 } 1393 1394 void MultiContextRenderTests::init (void) 1395 { 1396 addCreateTexture2DActions("texture_"); 1397 addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_UNSIGNED_BYTE); 1398 addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_UNSIGNED_BYTE); 1399 addCreateRenderbufferActions(); 1400 addCreateAndroidNativeActions(); 1401 addRenderActions(); 1402 addClearActions(); 1403 1404 for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++) 1405 for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++) 1406 for (int clearNdx = 0; clearNdx < m_clearActions.size(); clearNdx++) 1407 { 1408 const LabeledAction& createAction = m_createActions[createNdx]; 1409 const LabeledAction& renderAction = m_renderActions[renderNdx]; 1410 const LabeledAction& clearAction = m_clearActions[clearNdx]; 1411 TestSpec spec; 1412 1413 if (!isCompatibleCreateAndRenderActions(*createAction.action, *renderAction.action)) 1414 continue; 1415 if (!isCompatibleCreateAndModifyActions(*createAction.action, *clearAction.action)) 1416 continue; 1417 1418 spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label; 1419 spec.desc = spec.name; 1420 1421 spec.contexts.push_back(TestSpec::API_GLES2); 1422 spec.contexts.push_back(TestSpec::API_GLES2); 1423 1424 spec.operations.push_back(TestSpec::Operation(0, *createAction.action)); 1425 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action)); 1426 spec.operations.push_back(TestSpec::Operation(0, *clearAction.action)); 1427 spec.operations.push_back(TestSpec::Operation(1, *createAction.action)); 1428 spec.operations.push_back(TestSpec::Operation(0, *renderAction.action)); 1429 spec.operations.push_back(TestSpec::Operation(1, *renderAction.action)); 1430 1431 addChild(new ImageFormatCase(m_eglTestCtx, spec)); 1432 } 1433 } 1434 1435 TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1436 { 1437 return new MultiContextRenderTests(eglTestCtx, name, desc); 1438 } 1439 1440 class ModifyTests : public ImageTests 1441 { 1442 public: 1443 ModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1444 : ImageTests(eglTestCtx, name, desc) {} 1445 1446 void init (void); 1447 1448 protected: 1449 void addModifyActions(void); 1450 1451 LabeledActions m_modifyActions; 1452 GLES2ImageApi::RenderTryAll m_renderAction; 1453 }; 1454 1455 void ModifyTests::addModifyActions (void) 1456 { 1457 m_modifyActions.add("tex_subimage_rgb8", MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB, GL_UNSIGNED_BYTE))); 1458 m_modifyActions.add("tex_subimage_rgb565", MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB, GL_UNSIGNED_SHORT_5_6_5))); 1459 m_modifyActions.add("tex_subimage_rgba8", MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA, GL_UNSIGNED_BYTE))); 1460 m_modifyActions.add("tex_subimage_rgba5_a1", MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1))); 1461 m_modifyActions.add("tex_subimage_rgba4", MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4))); 1462 1463 m_modifyActions.add("renderbuffer_clear_color", MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f)))); 1464 m_modifyActions.add("renderbuffer_clear_depth", MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.7f))); 1465 m_modifyActions.add("renderbuffer_clear_stencil", MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(78))); 1466 } 1467 1468 void ModifyTests::init (void) 1469 { 1470 addCreateTexture2DActions("tex_"); 1471 addCreateRenderbufferActions(); 1472 addCreateAndroidNativeActions(); 1473 addModifyActions(); 1474 1475 for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++) 1476 { 1477 LabeledAction& createAction = m_createActions[createNdx]; 1478 1479 for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++) 1480 { 1481 LabeledAction& modifyAction = m_modifyActions[modifyNdx]; 1482 1483 if (!isCompatibleCreateAndModifyActions(*createAction.action, *modifyAction.action)) 1484 continue; 1485 1486 TestSpec spec; 1487 spec.name = createAction.label + "_" + modifyAction.label; 1488 spec.desc = "gles2_tex_sub_image"; 1489 1490 spec.contexts.push_back(TestSpec::API_GLES2); 1491 1492 spec.operations.push_back(TestSpec::Operation(0, *createAction.action)); 1493 spec.operations.push_back(TestSpec::Operation(0, m_renderAction)); 1494 spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action)); 1495 spec.operations.push_back(TestSpec::Operation(0, m_renderAction)); 1496 1497 addChild(new ImageFormatCase(m_eglTestCtx, spec)); 1498 } 1499 } 1500 } 1501 1502 TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc) 1503 { 1504 return new ModifyTests(eglTestCtx, name, desc); 1505 } 1506 1507 } // Image 1508 } // egl 1509 } // deqp 1510