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