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 Test EGL_SWAP_BEHAVIOR_PRESERVED_BIT. 22 *//*--------------------------------------------------------------------*/ 23 24#include "teglPreservingSwapTests.hpp" 25 26#include "tcuImageCompare.hpp" 27#include "tcuTestLog.hpp" 28#include "tcuSurface.hpp" 29#include "tcuTextureUtil.hpp" 30 31#include "egluNativeWindow.hpp" 32#include "egluUtil.hpp" 33 34#include "eglwLibrary.hpp" 35#include "eglwEnums.hpp" 36 37#include "gluDefs.hpp" 38#include "gluRenderContext.hpp" 39#include "gluShaderProgram.hpp" 40 41#include "glwDefs.hpp" 42#include "glwEnums.hpp" 43#include "glwFunctions.hpp" 44 45#include "deRandom.hpp" 46 47#include "deString.h" 48 49#include <vector> 50#include <string> 51 52using std::vector; 53using std::string; 54 55using namespace eglw; 56 57namespace deqp 58{ 59namespace egl 60{ 61 62namespace 63{ 64class GLES2Program; 65class ReferenceProgram; 66 67class PreservingSwapTest : public TestCase 68{ 69public: 70 enum DrawType 71 { 72 DRAWTYPE_NONE = 0, 73 DRAWTYPE_GLES2_CLEAR, 74 DRAWTYPE_GLES2_RENDER 75 }; 76 77 PreservingSwapTest (EglTestContext& eglTestCtx, bool preserveColorbuffer, bool readPixelsBeforeSwap, DrawType preSwapDrawType, DrawType postSwapDrawType, const char* name, const char* description); 78 ~PreservingSwapTest (void); 79 80 void init (void); 81 void deinit (void); 82 IterateResult iterate (void); 83 84private: 85 const int m_seed; 86 const bool m_preserveColorbuffer; 87 const bool m_readPixelsBeforeSwap; 88 const DrawType m_preSwapDrawType; 89 const DrawType m_postSwapDrawType; 90 91 EGLDisplay m_eglDisplay; 92 eglu::NativeWindow* m_window; 93 EGLSurface m_eglSurface; 94 EGLConfig m_eglConfig; 95 EGLContext m_eglContext; 96 glw::Functions m_gl; 97 98 GLES2Program* m_gles2Program; 99 ReferenceProgram* m_refProgram; 100 101 void initEGLSurface (EGLConfig config); 102 void initEGLContext (EGLConfig config); 103}; 104 105class GLES2Program 106{ 107public: 108 GLES2Program (const glw::Functions& gl); 109 ~GLES2Program (void); 110 111 void render (int width, int height, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType); 112 113private: 114 const glw::Functions& m_gl; 115 glu::ShaderProgram m_glProgram; 116 glw::GLuint m_coordLoc; 117 glw::GLuint m_colorLoc; 118 119 GLES2Program& operator= (const GLES2Program&); 120 GLES2Program (const GLES2Program&); 121}; 122 123static glu::ProgramSources getSources (void) 124{ 125 const char* const vertexShaderSource = 126 "attribute mediump vec4 a_pos;\n" 127 "attribute mediump vec4 a_color;\n" 128 "varying mediump vec4 v_color;\n" 129 "void main(void)\n" 130 "{\n" 131 "\tv_color = a_color;\n" 132 "\tgl_Position = a_pos;\n" 133 "}"; 134 135 const char* const fragmentShaderSource = 136 "varying mediump vec4 v_color;\n" 137 "void main(void)\n" 138 "{\n" 139 "\tgl_FragColor = v_color;\n" 140 "}"; 141 142 return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource); 143} 144 145GLES2Program::GLES2Program (const glw::Functions& gl) 146 : m_gl (gl) 147 , m_glProgram (gl, getSources()) 148 , m_coordLoc ((glw::GLuint)-1) 149 , m_colorLoc ((glw::GLuint)-1) 150{ 151 m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color"); 152 m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos"); 153 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations"); 154} 155 156GLES2Program::~GLES2Program (void) 157{ 158} 159 160void GLES2Program::render (int width, int height, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType) 161{ 162 if (drawType == PreservingSwapTest::DRAWTYPE_GLES2_RENDER) 163 { 164 const glw::GLfloat coords[] = 165 { 166 x1, y1, 0.0f, 1.0f, 167 x1, y2, 0.0f, 1.0f, 168 x2, y2, 0.0f, 1.0f, 169 170 x2, y2, 0.0f, 1.0f, 171 x2, y1, 0.0f, 1.0f, 172 x1, y1, 0.0f, 1.0f 173 }; 174 175 const glw::GLubyte colors[] = 176 { 177 127, 127, 127, 255, 178 127, 127, 127, 255, 179 127, 127, 127, 255, 180 181 127, 127, 127, 255, 182 127, 127, 127, 255, 183 127, 127, 127, 255 184 }; 185 186 m_gl.useProgram(m_glProgram.getProgram()); 187 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed"); 188 189 m_gl.enableVertexAttribArray(m_coordLoc); 190 m_gl.enableVertexAttribArray(m_colorLoc); 191 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes"); 192 193 m_gl.vertexAttribPointer(m_coordLoc, 4, GL_FLOAT, GL_FALSE, 0, coords); 194 m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors); 195 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers"); 196 197 m_gl.drawArrays(GL_TRIANGLES, 0, 6); 198 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() failed"); 199 200 m_gl.disableVertexAttribArray(m_coordLoc); 201 m_gl.disableVertexAttribArray(m_colorLoc); 202 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes"); 203 204 m_gl.useProgram(0); 205 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed"); 206 } 207 else if (drawType == PreservingSwapTest::DRAWTYPE_GLES2_CLEAR) 208 { 209 const int ox = width/2; 210 const int oy = height/2; 211 212 const int px = width; 213 const int py = height; 214 215 const int x1i = (int)((px/2.0f) * x1 + ox); 216 const int y1i = (int)((py/2.0f) * y1 + oy); 217 218 const int x2i = (int)((px/2.0f) * x2 + ox); 219 const int y2i = (int)((py/2.0f) * y2 + oy); 220 221 m_gl.enable(GL_SCISSOR_TEST); 222 m_gl.scissor(x1i, y1i, x2i-x1i, y2i-y1i); 223 m_gl.clearColor(0.5f, 0.5f, 0.5f, 1.0f); 224 m_gl.clear(GL_COLOR_BUFFER_BIT); 225 m_gl.disable(GL_SCISSOR_TEST); 226 } 227 else 228 DE_ASSERT(false); 229} 230 231class ReferenceProgram 232{ 233public: 234 ReferenceProgram (void); 235 ~ReferenceProgram (void); 236 237 void render (tcu::Surface* target, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType); 238 239private: 240 ReferenceProgram (const ReferenceProgram&); 241 ReferenceProgram& operator= (const ReferenceProgram&); 242}; 243 244ReferenceProgram::ReferenceProgram (void) 245{ 246} 247 248ReferenceProgram::~ReferenceProgram (void) 249{ 250} 251 252void ReferenceProgram::render (tcu::Surface* target, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType) 253{ 254 if (drawType == PreservingSwapTest::DRAWTYPE_GLES2_RENDER || drawType == PreservingSwapTest::DRAWTYPE_GLES2_CLEAR) 255 { 256 const int ox = target->getWidth()/2; 257 const int oy = target->getHeight()/2; 258 259 const int px = target->getWidth(); 260 const int py = target->getHeight(); 261 262 const int x1i = (int)((px/2.0) * x1 + ox); 263 const int y1i = (int)((py/2.0) * y1 + oy); 264 265 const int x2i = (int)((px/2.0) * x2 + ox); 266 const int y2i = (int)((py/2.0) * y2 + oy); 267 268 const tcu::RGBA color(127, 127, 127, 255); 269 270 for (int y = y1i; y <= y2i; y++) 271 { 272 for (int x = x1i; x <= x2i; x++) 273 target->setPixel(x, y, color); 274 } 275 } 276 else 277 DE_ASSERT(false); 278} 279 280PreservingSwapTest::PreservingSwapTest (EglTestContext& eglTestCtx, bool preserveColorbuffer, bool readPixelsBeforeSwap, DrawType preSwapDrawType, DrawType postSwapDrawType, const char* name, const char* description) 281 : TestCase (eglTestCtx, name, description) 282 , m_seed (deStringHash(name)) 283 , m_preserveColorbuffer (preserveColorbuffer) 284 , m_readPixelsBeforeSwap (readPixelsBeforeSwap) 285 , m_preSwapDrawType (preSwapDrawType) 286 , m_postSwapDrawType (postSwapDrawType) 287 , m_eglDisplay (EGL_NO_DISPLAY) 288 , m_window (DE_NULL) 289 , m_eglSurface (EGL_NO_SURFACE) 290 , m_eglContext (EGL_NO_CONTEXT) 291 , m_gles2Program (DE_NULL) 292 , m_refProgram (DE_NULL) 293{ 294} 295 296PreservingSwapTest::~PreservingSwapTest (void) 297{ 298 deinit(); 299} 300 301EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveColorbuffer) 302{ 303 const EGLint attribList[] = 304 { 305 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | (preserveColorbuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), 306 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 307 EGL_NONE 308 }; 309 310 return eglu::chooseSingleConfig(egl, eglDisplay, &attribList[0]); 311} 312 313void clearColorScreen (const glw::Functions& gl, float red, float green, float blue, float alpha) 314{ 315 gl.clearColor(red, green, blue, alpha); 316 gl.clear(GL_COLOR_BUFFER_BIT); 317} 318 319void clearColorReference (tcu::Surface* ref, float red, float green, float blue, float alpha) 320{ 321 tcu::clear(ref->getAccess(), tcu::Vec4(red, green, blue, alpha)); 322} 323 324void readPixels (const glw::Functions& gl, tcu::Surface* screen) 325{ 326 gl.readPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr()); 327} 328 329void PreservingSwapTest::initEGLSurface (EGLConfig config) 330{ 331 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine()); 332 333 m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))); 334 m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL); 335} 336 337void PreservingSwapTest::initEGLContext (EGLConfig config) 338{ 339 const Library& egl = m_eglTestCtx.getLibrary(); 340 const EGLint attribList[] = 341 { 342 EGL_CONTEXT_CLIENT_VERSION, 2, 343 EGL_NONE 344 }; 345 346 egl.bindAPI(EGL_OPENGL_ES_API); 347 m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList); 348 EGLU_CHECK_MSG(egl, "eglCreateContext"); 349 350 DE_ASSERT(m_eglSurface != EGL_NO_SURFACE); 351 egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 352 EGLU_CHECK_MSG(egl, "eglMakeCurrent"); 353} 354 355void PreservingSwapTest::init (void) 356{ 357 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); 358 m_eglConfig = getEGLConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, m_preserveColorbuffer); 359 360 if (m_eglConfig == DE_NULL) 361 TCU_THROW(NotSupportedError, "No supported config found"); 362 363 initEGLSurface(m_eglConfig); 364 initEGLContext(m_eglConfig); 365 366 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0)); 367 368 m_gles2Program = new GLES2Program(m_gl); 369 m_refProgram = new ReferenceProgram(); 370} 371 372void PreservingSwapTest::deinit (void) 373{ 374 const Library& egl = m_eglTestCtx.getLibrary(); 375 376 delete m_refProgram; 377 m_refProgram = DE_NULL; 378 379 delete m_gles2Program; 380 m_gles2Program = DE_NULL; 381 382 if (m_eglContext != EGL_NO_CONTEXT) 383 { 384 egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 385 egl.destroyContext(m_eglDisplay, m_eglContext); 386 m_eglContext = EGL_NO_CONTEXT; 387 } 388 389 if (m_eglSurface != EGL_NO_SURFACE) 390 { 391 egl.destroySurface(m_eglDisplay, m_eglSurface); 392 m_eglSurface = EGL_NO_SURFACE; 393 } 394 395 if (m_eglDisplay != EGL_NO_DISPLAY) 396 { 397 egl.terminate(m_eglDisplay); 398 m_eglDisplay = EGL_NO_DISPLAY; 399 } 400 401 delete m_window; 402 m_window = DE_NULL; 403} 404 405bool compareToReference (tcu::TestLog& log, const char* name, const char* description, const tcu::Surface& reference, const tcu::Surface& screen, int x, int y, int width, int height) 406{ 407 return tcu::fuzzyCompare(log, name, description, 408 getSubregion(reference.getAccess(), x, y, width, height), 409 getSubregion(screen.getAccess(), x, y, width, height), 410 0.05f, tcu::COMPARE_LOG_RESULT); 411} 412 413bool comparePreAndPostSwapFramebuffers (tcu::TestLog& log, const tcu::Surface& preSwap, const tcu::Surface& postSwap) 414{ 415 return tcu::pixelThresholdCompare(log, "Pre- / Post framebuffer compare", "Compare pre- and post-swap framebuffers", preSwap, postSwap, tcu::RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT); 416} 417 418TestCase::IterateResult PreservingSwapTest::iterate (void) 419{ 420 const Library& egl = m_eglTestCtx.getLibrary(); 421 tcu::TestLog& log = m_testCtx.getLog(); 422 de::Random rnd(m_seed); 423 424 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH); 425 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT); 426 427 const float clearRed = rnd.getFloat(); 428 const float clearGreen = rnd.getFloat(); 429 const float clearBlue = rnd.getFloat(); 430 const float clearAlpha = 1.0f; 431 432 const float preSwapX1 = -0.9f * rnd.getFloat(); 433 const float preSwapY1 = -0.9f * rnd.getFloat(); 434 const float preSwapX2 = 0.9f * rnd.getFloat(); 435 const float preSwapY2 = 0.9f * rnd.getFloat(); 436 437 const float postSwapX1 = -0.9f * rnd.getFloat(); 438 const float postSwapY1 = -0.9f * rnd.getFloat(); 439 const float postSwapX2 = 0.9f * rnd.getFloat(); 440 const float postSwapY2 = 0.9f * rnd.getFloat(); 441 442 tcu::Surface postSwapFramebufferReference(width, height); 443 tcu::Surface preSwapFramebufferReference(width, height); 444 445 tcu::Surface postSwapFramebuffer(width, height); 446 tcu::Surface preSwapFramebuffer(width, height); 447 448 if (m_preserveColorbuffer) 449 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)); 450 451 EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)); 452 453 clearColorScreen(m_gl, clearRed, clearGreen, clearBlue, clearAlpha); 454 455 if (m_readPixelsBeforeSwap) 456 clearColorReference(&preSwapFramebufferReference, clearRed, clearGreen, clearBlue, clearAlpha); 457 458 clearColorReference(&postSwapFramebufferReference, clearRed, clearGreen, clearBlue, clearAlpha); 459 460 if (m_preSwapDrawType != DRAWTYPE_NONE) 461 { 462 m_gles2Program->render(width, height, preSwapX1, preSwapY1, preSwapX2, preSwapY2, m_preSwapDrawType); 463 m_refProgram->render(&postSwapFramebufferReference, preSwapX1, preSwapY1, preSwapX2, preSwapY2, m_preSwapDrawType); 464 } 465 466 if (m_readPixelsBeforeSwap) 467 { 468 if (m_preSwapDrawType != DRAWTYPE_NONE) 469 m_refProgram->render(&preSwapFramebufferReference, preSwapX1, preSwapY1, preSwapX2, preSwapY2, m_preSwapDrawType); 470 471 readPixels(m_gl, &preSwapFramebuffer); 472 } 473 474 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface)); 475 476 if (m_postSwapDrawType != DRAWTYPE_NONE) 477 { 478 m_refProgram->render(&postSwapFramebufferReference, postSwapX1, postSwapY1, postSwapX2, postSwapY2, m_postSwapDrawType); 479 m_gles2Program->render(width, height, postSwapX1, postSwapY1, postSwapX2, postSwapY2, m_postSwapDrawType); 480 } 481 482 readPixels(m_gl, &postSwapFramebuffer); 483 484 bool isOk = true; 485 486 if (m_preserveColorbuffer) 487 { 488 if (m_readPixelsBeforeSwap) 489 isOk = isOk && compareToReference(log, "Compare pre-swap framebuffer to reference", "Compare pre-swap framebuffer to reference", preSwapFramebufferReference, preSwapFramebuffer, 0, 0, width, height); 490 491 isOk = isOk && compareToReference(log, "Compare post-swap framebuffer to reference", "Compare post-swap framebuffer to reference", postSwapFramebufferReference, postSwapFramebuffer, 0, 0, width, height); 492 493 if (m_readPixelsBeforeSwap && m_postSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE) 494 isOk = isOk && comparePreAndPostSwapFramebuffers(log, preSwapFramebuffer, postSwapFramebuffer); 495 } 496 else 497 { 498 const int ox = width/2; 499 const int oy = height/2; 500 501 const int px = width; 502 const int py = height; 503 504 const int x1i = (int)((px/2.0f) * postSwapX1 + ox); 505 const int y1i = (int)((py/2.0f) * postSwapY1 + oy); 506 507 const int x2i = (int)((px/2.0f) * postSwapX2 + ox); 508 const int y2i = (int)((py/2.0f) * postSwapY2 + oy); 509 510 if (m_readPixelsBeforeSwap) 511 isOk = isOk && compareToReference(log, "Compare pre-swap framebuffer to reference", "Compare pre-swap framebuffer to reference", preSwapFramebufferReference, preSwapFramebuffer, 0, 0, width, height); 512 513 DE_ASSERT(m_postSwapDrawType != DRAWTYPE_NONE); 514 isOk = isOk && compareToReference(log, "Compare valid are of post-swap framebuffer to reference", "Compare valid area of post-swap framebuffer to reference", postSwapFramebufferReference, postSwapFramebuffer, x1i, y1i, x2i - x1i, y2i - y1i); 515 } 516 517 if (isOk) 518 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 519 else 520 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 521 522 return STOP; 523} 524 525string generateTestName (PreservingSwapTest::DrawType preSwapDrawType, PreservingSwapTest::DrawType postSwapDrawType) 526{ 527 std::ostringstream stream; 528 529 if (preSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE && postSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE) 530 stream << "no_draw"; 531 else 532 { 533 switch (preSwapDrawType) 534 { 535 case PreservingSwapTest::DRAWTYPE_NONE: 536 // Do nothing 537 break; 538 539 case PreservingSwapTest::DRAWTYPE_GLES2_RENDER: 540 stream << "pre_render"; 541 break; 542 543 case PreservingSwapTest::DRAWTYPE_GLES2_CLEAR: 544 stream << "pre_clear"; 545 break; 546 547 default: 548 DE_ASSERT(false); 549 } 550 551 if (preSwapDrawType != PreservingSwapTest::DRAWTYPE_NONE && postSwapDrawType != PreservingSwapTest::DRAWTYPE_NONE) 552 stream << "_"; 553 554 switch (postSwapDrawType) 555 { 556 case PreservingSwapTest::DRAWTYPE_NONE: 557 // Do nothing 558 break; 559 560 case PreservingSwapTest::DRAWTYPE_GLES2_RENDER: 561 stream << "post_render"; 562 break; 563 564 case PreservingSwapTest::DRAWTYPE_GLES2_CLEAR: 565 stream << "post_clear"; 566 break; 567 568 default: 569 DE_ASSERT(false); 570 } 571 } 572 573 return stream.str(); 574} 575 576} // anonymous 577 578PreservingSwapTests::PreservingSwapTests (EglTestContext& eglTestCtx) 579 : TestCaseGroup(eglTestCtx, "preserve_swap", "Color buffer preserving swap tests") 580{ 581} 582 583void PreservingSwapTests::init (void) 584{ 585 const PreservingSwapTest::DrawType preSwapDrawTypes[] = 586 { 587 PreservingSwapTest::DRAWTYPE_NONE, 588 PreservingSwapTest::DRAWTYPE_GLES2_CLEAR, 589 PreservingSwapTest::DRAWTYPE_GLES2_RENDER 590 }; 591 592 const PreservingSwapTest::DrawType postSwapDrawTypes[] = 593 { 594 PreservingSwapTest::DRAWTYPE_NONE, 595 PreservingSwapTest::DRAWTYPE_GLES2_CLEAR, 596 PreservingSwapTest::DRAWTYPE_GLES2_RENDER 597 }; 598 599 for (int preserveNdx = 0; preserveNdx < 2; preserveNdx++) 600 { 601 const bool preserve = (preserveNdx == 0); 602 TestCaseGroup* const preserveGroup = new TestCaseGroup(m_eglTestCtx, (preserve ? "preserve" : "no_preserve"), ""); 603 604 for (int readPixelsNdx = 0; readPixelsNdx < 2; readPixelsNdx++) 605 { 606 const bool readPixelsBeforeSwap = (readPixelsNdx == 1); 607 TestCaseGroup* const readPixelsBeforeSwapGroup = new TestCaseGroup(m_eglTestCtx, (readPixelsBeforeSwap ? "read_before_swap" : "no_read_before_swap"), ""); 608 609 for (int preSwapDrawTypeNdx = 0; preSwapDrawTypeNdx < DE_LENGTH_OF_ARRAY(preSwapDrawTypes); preSwapDrawTypeNdx++) 610 { 611 const PreservingSwapTest::DrawType preSwapDrawType = preSwapDrawTypes[preSwapDrawTypeNdx]; 612 613 for (int postSwapDrawTypeNdx = 0; postSwapDrawTypeNdx < DE_LENGTH_OF_ARRAY(postSwapDrawTypes); postSwapDrawTypeNdx++) 614 { 615 const PreservingSwapTest::DrawType postSwapDrawType = postSwapDrawTypes[postSwapDrawTypeNdx]; 616 617 // If not preserving and rendering after swap, then there is nothing to verify 618 if (!preserve && postSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE) 619 continue; 620 621 const std::string name = generateTestName(preSwapDrawType, postSwapDrawType); 622 623 readPixelsBeforeSwapGroup->addChild(new PreservingSwapTest(m_eglTestCtx, preserve, readPixelsBeforeSwap, preSwapDrawType, postSwapDrawType, name.c_str(), "")); 624 } 625 } 626 627 preserveGroup->addChild(readPixelsBeforeSwapGroup); 628 } 629 630 addChild(preserveGroup); 631 } 632} 633 634} // egl 635} // deqp 636