teglSwapBuffersWithDamageTests.cpp revision 47e4ec00e391faa4a310b7565f0f5c4853766917
1/*------------------------------------------------------------------------- 2 * drawElements Quality Program EGL Module 3 * --------------------------------------- 4 * 5 * Copyright 2015 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 KHR_swap_buffer_with_damage 22 *//*--------------------------------------------------------------------*/ 23 24#include "teglSwapBuffersWithDamageTests.hpp" 25 26#include "tcuImageCompare.hpp" 27#include "tcuSurface.hpp" 28#include "tcuTextureUtil.hpp" 29 30#include "egluNativeWindow.hpp" 31#include "egluUtil.hpp" 32#include "egluConfigFilter.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#include "deString.h" 47 48#include <string> 49#include <vector> 50#include <sstream> 51 52using std::string; 53using std::vector; 54using glw::GLubyte; 55using tcu::IVec2; 56 57using namespace eglw; 58 59namespace deqp 60{ 61namespace egl 62{ 63namespace 64{ 65 66typedef tcu::Vector<GLubyte, 3> Color; 67 68enum DrawType 69{ 70 DRAWTYPE_GLES2_CLEAR, 71 DRAWTYPE_GLES2_RENDER 72}; 73 74struct ColoredRect 75{ 76public: 77 ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_); 78 IVec2 bottomLeft; 79 IVec2 topRight; 80 Color color; 81}; 82 83ColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_) 84 : bottomLeft (bottomLeft_) 85 , topRight (topRight_) 86 , color (color_) 87{ 88} 89 90struct DrawCommand 91{ 92 DrawCommand (DrawType drawType_, const ColoredRect& rect_); 93 DrawType drawType; 94 ColoredRect rect; 95}; 96 97DrawCommand::DrawCommand (DrawType drawType_, const ColoredRect& rect_) 98 : drawType (drawType_) 99 , rect (rect_) 100{ 101} 102 103struct Frame 104{ 105 Frame (int width_, int height_); 106 int width; 107 int height; 108 vector<DrawCommand> draws; 109}; 110 111Frame::Frame (int width_, int height_) 112 : width (width_) 113 , height(height_) 114{ 115} 116 117typedef vector<Frame> FrameSequence; 118 119//helper function declaration 120EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer); 121void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor); 122float windowToDeviceCoordinates (int x, int length); 123 124class GLES2Renderer 125{ 126public: 127 GLES2Renderer (const glw::Functions& gl); 128 ~GLES2Renderer (void); 129 void render (int width, int height, const Frame& frame) const; 130 131private: 132 GLES2Renderer (const GLES2Renderer&); 133 GLES2Renderer& operator= (const GLES2Renderer&); 134 135 const glw::Functions& m_gl; 136 glu::ShaderProgram m_glProgram; 137 glw::GLuint m_coordLoc; 138 glw::GLuint m_colorLoc; 139}; 140 141// generate sources for vertex and fragment buffer 142glu::ProgramSources getSources (void) 143{ 144 const char* const vertexShaderSource = 145 "attribute mediump vec2 a_pos;\n" 146 "attribute mediump vec4 a_color;\n" 147 "varying mediump vec4 v_color;\n" 148 "void main(void)\n" 149 "{\n" 150 "\tv_color = a_color;\n" 151 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" 152 "}"; 153 154 const char* const fragmentShaderSource = 155 "varying mediump vec4 v_color;\n" 156 "void main(void)\n" 157 "{\n" 158 "\tgl_FragColor = v_color;\n" 159 "}"; 160 161 return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource); 162} 163 164GLES2Renderer::GLES2Renderer (const glw::Functions& gl) 165 : m_gl (gl) 166 , m_glProgram (gl, getSources()) 167 , m_coordLoc ((glw::GLuint)-1) 168 , m_colorLoc ((glw::GLuint)-1) 169{ 170 m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color"); 171 m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos"); 172 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations"); 173} 174 175GLES2Renderer::~GLES2Renderer (void) 176{ 177} 178 179void GLES2Renderer::render (int width, int height, const Frame& frame) const 180{ 181 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++) 182 { 183 const ColoredRect& coloredRect = frame.draws[drawNdx].rect; 184 185 if (frame.draws[drawNdx].drawType == DRAWTYPE_GLES2_RENDER) 186 { 187 const float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width); 188 const float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height); 189 const float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width); 190 const float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height); 191 192 const glw::GLfloat coords[] = 193 { 194 x1, y1, 195 x1, y2, 196 x2, y2, 197 198 x2, y2, 199 x2, y1, 200 x1, y1, 201 }; 202 203 const glw::GLubyte colors[] = 204 { 205 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 206 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 207 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 208 209 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 210 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 211 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 212 }; 213 214 m_gl.useProgram(m_glProgram.getProgram()); 215 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed"); 216 217 m_gl.enableVertexAttribArray(m_coordLoc); 218 m_gl.enableVertexAttribArray(m_colorLoc); 219 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes"); 220 221 m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords); 222 m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors); 223 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers"); 224 225 m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/2); 226 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed"); 227 228 m_gl.disableVertexAttribArray(m_coordLoc); 229 m_gl.disableVertexAttribArray(m_colorLoc); 230 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes"); 231 232 m_gl.useProgram(0); 233 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed"); 234 } 235 else if (frame.draws[drawNdx].drawType == DRAWTYPE_GLES2_CLEAR) 236 { 237 m_gl.enable(GL_SCISSOR_TEST); 238 m_gl.scissor(coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(), 239 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y()); 240 m_gl.clearColor(coloredRect.color.x()/255.0f, coloredRect.color.y()/255.0f, coloredRect.color.z()/255.0f, 1.0f); 241 m_gl.clear(GL_COLOR_BUFFER_BIT); 242 m_gl.disable(GL_SCISSOR_TEST); 243 } 244 else 245 DE_FATAL("Invalid drawtype"); 246 } 247} 248 249class SwapBuffersWithDamageTest : public TestCase 250{ 251public: 252 SwapBuffersWithDamageTest (EglTestContext& eglTestCtx, 253 const vector<DrawType>& frameDrawType, 254 int iterationTimes, 255 const char* name, 256 const char* description); 257 ~SwapBuffersWithDamageTest (void); 258 259 virtual void init (void); 260 void deinit (void); 261 virtual IterateResult iterate (void); 262 263protected: 264 virtual EGLConfig getConfig (const Library& egl, EGLDisplay eglDisplay); 265 virtual void checkExtension (const Library& egl, EGLDisplay eglDisplay); 266 void initEGLSurface (EGLConfig config); 267 void initEGLContext (EGLConfig config); 268 269 eglu::NativeWindow* m_window; 270 EGLConfig m_eglConfig; 271 EGLContext m_eglContext; 272 const int m_seed; 273 const int m_iterationTimes; 274 const vector<DrawType> m_frameDrawType; 275 EGLDisplay m_eglDisplay; 276 EGLSurface m_eglSurface; 277 glw::Functions m_gl; 278 GLES2Renderer* m_gles2Renderer; 279}; 280 281SwapBuffersWithDamageTest::SwapBuffersWithDamageTest (EglTestContext& eglTestCtx, const vector<DrawType>& frameDrawType, int iterationTimes, const char* name, const char* description) 282 : TestCase (eglTestCtx, name, description) 283 , m_window (DE_NULL) 284 , m_eglContext (EGL_NO_CONTEXT) 285 , m_seed (deStringHash(name)) 286 , m_iterationTimes(iterationTimes) 287 , m_frameDrawType (frameDrawType) 288 , m_eglDisplay (EGL_NO_DISPLAY) 289 , m_eglSurface (EGL_NO_SURFACE) 290 , m_gles2Renderer (DE_NULL) 291{ 292} 293 294SwapBuffersWithDamageTest::~SwapBuffersWithDamageTest (void) 295{ 296 deinit(); 297} 298 299EGLConfig SwapBuffersWithDamageTest::getConfig (const Library& egl, EGLDisplay eglDisplay) 300{ 301 return getEGLConfig(egl, eglDisplay, false); 302} 303 304void SwapBuffersWithDamageTest::checkExtension (const Library& egl, EGLDisplay eglDisplay) 305{ 306 if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage")) 307 TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported"); 308} 309 310void SwapBuffersWithDamageTest::init (void) 311{ 312 const Library& egl = m_eglTestCtx.getLibrary(); 313 314 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); 315 m_eglConfig = getConfig(egl, m_eglDisplay); 316 317 checkExtension(egl, m_eglDisplay); 318 319 initEGLSurface(m_eglConfig); 320 initEGLContext(m_eglConfig); 321 322 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0)); 323 m_gles2Renderer = new GLES2Renderer(m_gl); 324} 325 326void SwapBuffersWithDamageTest::deinit (void) 327{ 328 const Library& egl = m_eglTestCtx.getLibrary(); 329 330 delete m_gles2Renderer; 331 m_gles2Renderer = DE_NULL; 332 333 if (m_eglContext != EGL_NO_CONTEXT) 334 { 335 egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 336 egl.destroyContext(m_eglDisplay, m_eglContext); 337 m_eglContext = EGL_NO_CONTEXT; 338 } 339 340 if (m_eglSurface != EGL_NO_SURFACE) 341 { 342 egl.destroySurface(m_eglDisplay, m_eglSurface); 343 m_eglSurface = EGL_NO_SURFACE; 344 } 345 346 if (m_eglDisplay != EGL_NO_DISPLAY) 347 { 348 egl.terminate(m_eglDisplay); 349 m_eglDisplay = EGL_NO_DISPLAY; 350 } 351 352 delete m_window; 353 m_window = DE_NULL; 354} 355 356void SwapBuffersWithDamageTest::initEGLSurface (EGLConfig config) 357{ 358 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine()); 359 m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL, 360 eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))); 361 m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL); 362} 363 364void SwapBuffersWithDamageTest::initEGLContext (EGLConfig config) 365{ 366 const Library& egl = m_eglTestCtx.getLibrary(); 367 const EGLint attribList[] = 368 { 369 EGL_CONTEXT_CLIENT_VERSION, 2, 370 EGL_NONE 371 }; 372 373 egl.bindAPI(EGL_OPENGL_ES_API); 374 m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList); 375 EGLU_CHECK_MSG(egl, "eglCreateContext"); 376 TCU_CHECK(m_eglSurface != EGL_NO_SURFACE); 377 egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 378 EGLU_CHECK_MSG(egl, "eglMakeCurrent"); 379} 380 381FrameSequence generateFrameSequence (const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height); 382vector<EGLint> getDamageRegion (const Frame& frame); 383 384TestCase::IterateResult SwapBuffersWithDamageTest::iterate (void) 385{ 386 de::Random rnd (m_seed); 387 const Library& egl = m_eglTestCtx.getLibrary(); 388 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH); 389 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT); 390 const float clearRed = rnd.getFloat(); 391 const float clearGreen = rnd.getFloat(); 392 const float clearBlue = rnd.getFloat(); 393 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f); 394 const int numFrames = 24; // (width, height) = (480, 480) --> numFrame = 24, divisible 395 const FrameSequence frameSequence = generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height); 396 397 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 398 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED)); 399 400 for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++) 401 { 402 for (int currentFrameNdx = 0; currentFrameNdx < numFrames; currentFrameNdx++) 403 { 404 vector<EGLint> damageRegion = getDamageRegion(frameSequence[currentFrameNdx]); 405 406 clearColorScreen(m_gl, clearColor); 407 for (int ndx = 0; ndx <= currentFrameNdx; ndx++) 408 m_gles2Renderer->render(width, height, frameSequence[ndx]); 409 410 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4)); 411 } 412 } 413 return STOP; 414} 415 416class SwapBuffersWithDamageAndPreserveBufferTest : public SwapBuffersWithDamageTest 417{ 418public: 419 SwapBuffersWithDamageAndPreserveBufferTest (EglTestContext& eglTestCtx, 420 const vector<DrawType>& frameDrawType, 421 int itertionTimes, 422 const char* name, 423 const char* description); 424 IterateResult iterate (void); 425 426protected: 427 EGLConfig getConfig (const Library& egl, EGLDisplay eglDisplay); 428}; 429 430SwapBuffersWithDamageAndPreserveBufferTest::SwapBuffersWithDamageAndPreserveBufferTest (EglTestContext& eglTestCtx, 431 const vector<DrawType>& frameDrawType, 432 int iterationTimes, 433 const char* name, 434 const char* description) 435 : SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, name, description) 436{ 437} 438 439EGLConfig SwapBuffersWithDamageAndPreserveBufferTest::getConfig (const Library& egl, EGLDisplay eglDisplay) 440{ 441 return getEGLConfig(egl, eglDisplay, true); 442} 443 444TestCase::IterateResult SwapBuffersWithDamageAndPreserveBufferTest::iterate (void) 445{ 446 447 de::Random rnd (m_seed); 448 const Library& egl = m_eglTestCtx.getLibrary(); 449 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH); 450 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT); 451 const float clearRed = rnd.getFloat(); 452 const float clearGreen = rnd.getFloat(); 453 const float clearBlue = rnd.getFloat(); 454 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f); 455 const int numFrames = 24; // (width, height) = (480, 480) --> numFrame = 24, divisible 456 const FrameSequence frameSequence = generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height); 457 458 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 459 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)); 460 461 for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++) 462 { 463 clearColorScreen(m_gl, clearColor); 464 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0)); 465 466 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++) 467 { 468 const Frame& currentFrame = frameSequence[frameNdx]; 469 vector<EGLint> damageRegion = getDamageRegion(currentFrame); 470 471 m_gles2Renderer->render(width, height, currentFrame); 472 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4)); 473 } 474 } 475 476 return STOP; 477} 478 479class SwapBuffersWithDamageAndBufferAgeTest : public SwapBuffersWithDamageTest 480{ 481public: 482 SwapBuffersWithDamageAndBufferAgeTest (EglTestContext& eglTestCtx, 483 const vector<DrawType>& frameDrawType, 484 int iterationTimes, 485 const char* name, 486 const char* description); 487 IterateResult iterate (void); 488 489protected: 490 void checkExtension (const Library& egl, EGLDisplay eglDisplay); 491}; 492 493SwapBuffersWithDamageAndBufferAgeTest::SwapBuffersWithDamageAndBufferAgeTest (EglTestContext& eglTestCtx, 494 const vector<DrawType>& frameDrawType, 495 int iterationTimes, 496 const char* name, 497 const char* description) 498 : SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, name, description) 499{ 500} 501 502 503void SwapBuffersWithDamageAndBufferAgeTest::checkExtension (const Library& egl, EGLDisplay eglDisplay) 504{ 505 if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage")) 506 TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported"); 507 508 if (!eglu::hasExtension(egl, eglDisplay, "EGL_EXT_buffer_age")) 509 TCU_THROW(NotSupportedError, "EGL_EXT_buffer_age not supported"); 510} 511 512TestCase::IterateResult SwapBuffersWithDamageAndBufferAgeTest::iterate (void) 513{ 514 515 de::Random rnd (m_seed); 516 const Library& egl = m_eglTestCtx.getLibrary(); 517 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH); 518 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT); 519 const float clearRed = rnd.getFloat(); 520 const float clearGreen = rnd.getFloat(); 521 const float clearBlue = rnd.getFloat(); 522 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f); 523 const int numFrames = 24; // (width, height) = (480, 480) --> numFrame = 24, divisible 524 const FrameSequence frameSequence = generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height); 525 526 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 527 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED)); 528 529 for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++) 530 { 531 clearColorScreen(m_gl, clearColor); 532 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0)); 533 534 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++) 535 { 536 vector<EGLint> damageRegion; 537 int bufferAge = -1; 538 int startFrameNdx = -1; 539 int endFrameNdx = frameNdx; 540 541 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, &bufferAge)); 542 543 if (bufferAge < 0) // invalid buffer age 544 { 545 std::ostringstream stream; 546 stream << "Fail, the age is invalid. Age: " << bufferAge << ", frameNdx: " << frameNdx; 547 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str()); 548 return STOP; 549 } 550 551 if (bufferAge == 0 || bufferAge > frameNdx) 552 { 553 clearColorScreen(m_gl, clearColor); 554 startFrameNdx = 0; 555 } 556 else 557 startFrameNdx = frameNdx-bufferAge+1; 558 559 for (int ndx = startFrameNdx; ndx <= endFrameNdx; ndx++) 560 { 561 const vector<EGLint> partialDamageRegion = getDamageRegion(frameSequence[ndx]); 562 563 damageRegion.insert(damageRegion.end(), partialDamageRegion.begin(), partialDamageRegion.end()); 564 m_gles2Renderer->render(width, height, frameSequence[ndx]); 565 } 566 567 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4)); 568 } 569 } 570 return STOP; 571} 572 573// generate a frame sequence with certain frame for visual verification 574FrameSequence generateFrameSequence (const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height) 575{ 576 const int frameDiff = height / numFrames; 577 const GLubyte r = rnd.getUint8(); 578 const GLubyte g = rnd.getUint8(); 579 const GLubyte b = rnd.getUint8(); 580 const Color color (r, g, b); 581 FrameSequence frameSequence; 582 583 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++) 584 { 585 Frame frame (width, height); 586 587 for (int rectNdx = 0; rectNdx < (int)frameDrawType.size(); rectNdx++) 588 { 589 const int rectHeight = frameDiff / (int)frameDrawType.size(); 590 const ColoredRect rect (IVec2(0, frameNdx*frameDiff+rectNdx*rectHeight), IVec2(width, frameNdx*frameDiff+(rectNdx+1)*rectHeight), color); 591 const DrawCommand drawCommand (frameDrawType[rectNdx], rect); 592 593 frame.draws.push_back(drawCommand); 594 } 595 frameSequence.push_back(frame); 596 } 597 return frameSequence; 598} 599 600vector<EGLint> getDamageRegion (const Frame& frame) 601{ 602 vector<EGLint> damageRegion; 603 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++) 604 { 605 const ColoredRect& rect = frame.draws[drawNdx].rect; 606 damageRegion.push_back(rect.bottomLeft.x()); 607 damageRegion.push_back(rect.bottomLeft.y()); 608 damageRegion.push_back(rect.topRight.x() - rect.bottomLeft.x()); 609 damageRegion.push_back(rect.topRight.y() - rect.bottomLeft.y()); 610 } 611 612 DE_ASSERT(damageRegion.size() % 4 == 0); 613 return damageRegion; 614} 615 616string generateTestName (const vector<DrawType>& frameDrawType) 617{ 618 std::ostringstream stream; 619 620 for (size_t ndx = 0; ndx < frameDrawType.size(); ndx++) 621 { 622 if (frameDrawType[ndx] == DRAWTYPE_GLES2_RENDER) 623 stream << "render"; 624 else if (frameDrawType[ndx] == DRAWTYPE_GLES2_CLEAR) 625 stream << "clear"; 626 else 627 DE_ASSERT(false); 628 629 if (ndx < frameDrawType.size()-1) 630 stream << "_"; 631 } 632 633 return stream.str(); 634} 635 636bool isWindow (const eglu::CandidateConfig& c) 637{ 638 return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT; 639} 640 641bool isES2Renderable (const eglu::CandidateConfig& c) 642{ 643 return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT; 644} 645 646bool hasPreserveSwap (const eglu::CandidateConfig& c) 647{ 648 return (c.surfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 649} 650 651EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer) 652{ 653 eglu::FilterList filters; 654 655 filters << isWindow << isES2Renderable; 656 if (preserveBuffer) 657 filters << hasPreserveSwap; 658 659 return eglu::chooseSingleConfig(egl, eglDisplay, filters); 660} 661 662void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor) 663{ 664 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); 665 gl.clear(GL_COLOR_BUFFER_BIT); 666} 667 668float windowToDeviceCoordinates (int x, int length) 669{ 670 return (2.0f * float(x) / float(length)) - 1.0f; 671} 672 673} // anonymous 674 675SwapBuffersWithDamageTests::SwapBuffersWithDamageTests (EglTestContext& eglTestCtx) 676 : TestCaseGroup(eglTestCtx, "swap_buffers_with_damage", "Swap buffers with damages tests") 677{ 678} 679 680void SwapBuffersWithDamageTests::init (void) 681{ 682 const DrawType clearRender[2] = 683 { 684 DRAWTYPE_GLES2_CLEAR, 685 DRAWTYPE_GLES2_RENDER 686 }; 687 688 const DrawType renderClear[2] = 689 { 690 DRAWTYPE_GLES2_RENDER, 691 DRAWTYPE_GLES2_CLEAR 692 }; 693 694 vector< vector<DrawType> > frameDrawTypes; 695 frameDrawTypes.push_back(vector<DrawType> (1, DRAWTYPE_GLES2_CLEAR)); 696 frameDrawTypes.push_back(vector<DrawType> (1, DRAWTYPE_GLES2_RENDER)); 697 frameDrawTypes.push_back(vector<DrawType> (2, DRAWTYPE_GLES2_CLEAR)); 698 frameDrawTypes.push_back(vector<DrawType> (2, DRAWTYPE_GLES2_RENDER)); 699 frameDrawTypes.push_back(vector<DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender))); 700 frameDrawTypes.push_back(vector<DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear))); 701 702 for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++) 703 { 704 string name = generateTestName(frameDrawTypes[drawTypeNdx]); 705 addChild(new SwapBuffersWithDamageTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, name.c_str(), "")); 706 } 707 708 for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++) 709 { 710 string name = "preserve_buffer_" + generateTestName(frameDrawTypes[drawTypeNdx]); 711 addChild(new SwapBuffersWithDamageAndPreserveBufferTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, name.c_str(), "")); 712 } 713 714 for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++) 715 { 716 string name = "buffer_age_" + generateTestName(frameDrawTypes[drawTypeNdx]); 717 addChild(new SwapBuffersWithDamageAndBufferAgeTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, name.c_str(), "")); 718 } 719} 720 721} // egl 722} // deqp 723