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