teglPartialUpdateTests.cpp revision 5bf751a02c12f55bb28e4d8da785d3e7338436d0
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_partial_update 22 *//*--------------------------------------------------------------------*/ 23 24#include "teglPartialUpdateTests.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#include "egluConfigFilter.hpp" 34 35#include "eglwLibrary.hpp" 36#include "eglwEnums.hpp" 37 38#include "gluDefs.hpp" 39#include "gluRenderContext.hpp" 40#include "gluShaderProgram.hpp" 41 42#include "glwDefs.hpp" 43#include "glwEnums.hpp" 44#include "glwFunctions.hpp" 45 46#include "deRandom.hpp" 47#include "deString.h" 48 49#include <string> 50#include <vector> 51#include <sstream> 52 53using std::string; 54using std::vector; 55using glw::GLubyte; 56using tcu::IVec2; 57 58using namespace eglw; 59 60namespace deqp 61{ 62namespace egl 63{ 64namespace 65{ 66 67typedef tcu::Vector<GLubyte, 3> Color; 68 69class GLES2Renderer; 70 71class ReferenceRenderer; 72 73class PartialUpdateTest : public TestCase 74{ 75public: 76 enum DrawType 77 { 78 DRAWTYPE_GLES2_CLEAR, 79 DRAWTYPE_GLES2_RENDER 80 }; 81 82 PartialUpdateTest (EglTestContext& eglTestCtx, 83 const vector<DrawType>& oddFrameDrawType, 84 const vector<DrawType>& evenFrameDrawType, 85 const char* name, 86 const char* description); 87 ~PartialUpdateTest (void); 88 89 void init (void); 90 void deinit (void); 91 IterateResult iterate (void); 92 93private: 94 void initEGLSurface (EGLConfig config); 95 void initEGLContext (EGLConfig config); 96 97 const int m_seed; 98 const vector<DrawType> m_oddFrameDrawType; 99 const vector<DrawType> m_evenFrameDrawType; 100 101 bool m_supportBufferAge; 102 EGLDisplay m_eglDisplay; 103 eglu::NativeWindow* m_window; 104 EGLSurface m_eglSurface; 105 EGLConfig m_eglConfig; 106 EGLContext m_eglContext; 107 glw::Functions m_gl; 108 109 GLES2Renderer* m_gles2Renderer; 110 ReferenceRenderer* m_refRenderer; 111 112}; 113 114struct ColoredRect 115{ 116public: 117 ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_); 118 IVec2 bottomLeft; 119 IVec2 topRight; 120 Color color; 121}; 122 123ColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_) 124 : bottomLeft (bottomLeft_) 125 , topRight (topRight_) 126 , color (color_) 127{ 128} 129 130struct DrawCommand 131{ 132 DrawCommand (const PartialUpdateTest::DrawType drawType_, const ColoredRect& rect_); 133 PartialUpdateTest::DrawType drawType; 134 ColoredRect rect; 135}; 136 137DrawCommand::DrawCommand (const PartialUpdateTest::DrawType drawType_, const ColoredRect& rect_) 138 : drawType (drawType_) 139 , rect (rect_) 140{ 141} 142 143struct Frame 144{ 145 Frame (int width_, int height_); 146 int width; 147 int height; 148 vector<DrawCommand> draws; 149}; 150 151Frame::Frame (int width_, int height_) 152 : width (width_) 153 , height(height_) 154{ 155} 156 157 158// (x1,y1) lie in the lower-left quadrant while (x2,y2) lie in the upper-right. 159// the coords are multiplied by 4 to amplify the minimial difference between coords to 4 (if not zero) 160// to avoid the situation where two edges are too close to each other which makes the rounding error 161// intoleratable by compareToReference() 162void generateRandomFrame (Frame& dst, const vector<PartialUpdateTest::DrawType>& drawTypes, de::Random& rnd) 163{ 164 for (size_t ndx = 0; ndx < drawTypes.size(); ndx++) 165 { 166 const int x1 = rnd.getInt(0, (dst.width-1)/8) * 4; 167 const int y1 = rnd.getInt(0, (dst.height-1)/8) * 4; 168 const int x2 = rnd.getInt((dst.width-1)/8, (dst.width-1)/4) * 4; 169 const int y2 = rnd.getInt((dst.height-1)/8, (dst.height-1)/4) * 4; 170 const GLubyte r = rnd.getUint8(); 171 const GLubyte g = rnd.getUint8(); 172 const GLubyte b = rnd.getUint8(); 173 const ColoredRect coloredRect (IVec2(x1, y1), IVec2(x2, y2), Color(r, g, b)); 174 const DrawCommand drawCommand (drawTypes[ndx], coloredRect); 175 176 dst.draws.push_back(drawCommand); 177 } 178} 179 180typedef vector<Frame> FrameSequence; 181 182//helper function declaration 183EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay); 184void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor); 185void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor); 186void readPixels (const glw::Functions& gl, tcu::Surface* screen); 187float windowToDeviceCoordinates (int x, int length); 188bool compareToReference (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum); 189vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx); 190 191class GLES2Renderer 192{ 193public: 194 GLES2Renderer (const glw::Functions& gl); 195 ~GLES2Renderer (void); 196 void render (int width, int height, const Frame& frame) const; 197 198private: 199 GLES2Renderer (const GLES2Renderer&); 200 GLES2Renderer& operator= (const GLES2Renderer&); 201 202 const glw::Functions& m_gl; 203 glu::ShaderProgram m_glProgram; 204 glw::GLuint m_coordLoc; 205 glw::GLuint m_colorLoc; 206}; 207 208// generate sources for vertex and fragment buffer 209glu::ProgramSources getSources (void) 210{ 211 const char* const vertexShaderSource = 212 "attribute mediump vec2 a_pos;\n" 213 "attribute mediump vec4 a_color;\n" 214 "varying mediump vec4 v_color;\n" 215 "void main(void)\n" 216 "{\n" 217 "\tv_color = a_color;\n" 218 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" 219 "}"; 220 221 const char* const fragmentShaderSource = 222 "varying mediump vec4 v_color;\n" 223 "void main(void)\n" 224 "{\n" 225 "\tgl_FragColor = v_color;\n" 226 "}"; 227 228 return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource); 229} 230 231GLES2Renderer::GLES2Renderer (const glw::Functions& gl) 232 : m_gl (gl) 233 , m_glProgram (gl, getSources()) 234 , m_coordLoc ((glw::GLuint)-1) 235 , m_colorLoc ((glw::GLuint)-1) 236{ 237 m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color"); 238 m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos"); 239 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations"); 240} 241 242GLES2Renderer::~GLES2Renderer (void) 243{ 244} 245 246void GLES2Renderer::render (int width, int height, const Frame& frame) const 247{ 248 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++) 249 { 250 const ColoredRect& coloredRect = frame.draws[drawNdx].rect; 251 252 if (frame.draws[drawNdx].drawType == PartialUpdateTest::DRAWTYPE_GLES2_RENDER) 253 { 254 const float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width); 255 const float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height); 256 const float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width); 257 const float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height); 258 259 const glw::GLfloat coords[] = 260 { 261 x1, y1, 262 x1, y2, 263 x2, y2, 264 265 x2, y2, 266 x2, y1, 267 x1, y1, 268 }; 269 270 const glw::GLubyte colors[] = 271 { 272 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 273 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 274 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 275 276 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 277 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 278 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255, 279 }; 280 281 m_gl.useProgram(m_glProgram.getProgram()); 282 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed"); 283 284 m_gl.enableVertexAttribArray(m_coordLoc); 285 m_gl.enableVertexAttribArray(m_colorLoc); 286 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes"); 287 288 m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords); 289 m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors); 290 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers"); 291 292 m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/2); 293 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed"); 294 295 m_gl.disableVertexAttribArray(m_coordLoc); 296 m_gl.disableVertexAttribArray(m_colorLoc); 297 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes"); 298 299 m_gl.useProgram(0); 300 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed"); 301 } 302 else if (frame.draws[drawNdx].drawType == PartialUpdateTest::DRAWTYPE_GLES2_CLEAR) 303 { 304 m_gl.enable(GL_SCISSOR_TEST); 305 m_gl.scissor(coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(), 306 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y()); 307 m_gl.clearColor(coloredRect.color.x()/255.0f, coloredRect.color.y()/255.0f, coloredRect.color.z()/255.0f, 1.0f); 308 m_gl.clear(GL_COLOR_BUFFER_BIT); 309 m_gl.disable(GL_SCISSOR_TEST); 310 } 311 else 312 DE_FATAL("Invalid drawtype"); 313 } 314} 315 316class ReferenceRenderer 317{ 318public: 319 ReferenceRenderer (void); 320 void render (tcu::Surface* target, const Frame& frame) const; 321private: 322 ReferenceRenderer (const ReferenceRenderer&); 323 ReferenceRenderer& operator= (const ReferenceRenderer&); 324}; 325 326ReferenceRenderer::ReferenceRenderer(void) 327{ 328} 329 330void ReferenceRenderer::render (tcu::Surface* target, const Frame& frame) const 331{ 332 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++) 333 { 334 const ColoredRect& coloredRect = frame.draws[drawNdx].rect; 335 if (frame.draws[drawNdx].drawType == PartialUpdateTest::DRAWTYPE_GLES2_RENDER || frame.draws[drawNdx].drawType == PartialUpdateTest::DRAWTYPE_GLES2_CLEAR) 336 { 337 const tcu::UVec4 color(coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255); 338 tcu::clear(tcu::getSubregion(target->getAccess(), coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(), 339 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y()), color); 340 } 341 else 342 DE_FATAL("Invalid drawtype"); 343 } 344} 345 346PartialUpdateTest::PartialUpdateTest (EglTestContext& eglTestCtx, 347 const vector<DrawType>& oddFrameDrawType, 348 const vector<DrawType>& evenFrameDrawType, 349 const char* name, const char* description) 350 : TestCase (eglTestCtx, name, description) 351 , m_seed (deStringHash(name)) 352 , m_oddFrameDrawType (oddFrameDrawType) 353 , m_evenFrameDrawType (evenFrameDrawType) 354 , m_supportBufferAge (false) 355 , m_eglDisplay (EGL_NO_DISPLAY) 356 , m_window (DE_NULL) 357 , m_eglSurface (EGL_NO_SURFACE) 358 , m_eglContext (EGL_NO_CONTEXT) 359 , m_gles2Renderer (DE_NULL) 360 , m_refRenderer (DE_NULL) 361{ 362} 363 364PartialUpdateTest::~PartialUpdateTest (void) 365{ 366 deinit(); 367} 368 369void PartialUpdateTest::init (void) 370{ 371 const Library& egl = m_eglTestCtx.getLibrary(); 372 373 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); 374 m_eglConfig = getEGLConfig(m_eglTestCtx.getLibrary(), m_eglDisplay); 375 376 //create surface and context and make them current 377 initEGLSurface(m_eglConfig); 378 initEGLContext(m_eglConfig); 379 380 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0)); 381 382 m_supportBufferAge = eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_buffer_age"); 383 384 if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_KHR_partial_update")) 385 TCU_THROW(NotSupportedError, "EGL_KHR_partial_update is not supported"); 386 387 m_gles2Renderer = new GLES2Renderer(m_gl); 388 m_refRenderer = new ReferenceRenderer(); 389} 390 391void PartialUpdateTest::deinit (void) 392{ 393 const Library& egl = m_eglTestCtx.getLibrary(); 394 395 delete m_refRenderer; 396 m_refRenderer = DE_NULL; 397 398 delete m_gles2Renderer; 399 m_gles2Renderer = DE_NULL; 400 401 if (m_eglContext != EGL_NO_CONTEXT) 402 { 403 egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 404 egl.destroyContext(m_eglDisplay, m_eglContext); 405 m_eglContext = EGL_NO_CONTEXT; 406 } 407 408 if (m_eglSurface != EGL_NO_SURFACE) 409 { 410 egl.destroySurface(m_eglDisplay, m_eglSurface); 411 m_eglSurface = EGL_NO_SURFACE; 412 } 413 414 if (m_eglDisplay != EGL_NO_DISPLAY) 415 { 416 egl.terminate(m_eglDisplay); 417 m_eglDisplay = EGL_NO_DISPLAY; 418 } 419 420 delete m_window; 421 m_window = DE_NULL; 422} 423 424void PartialUpdateTest::initEGLSurface (EGLConfig config) 425{ 426 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine()); 427 m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL, 428 eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))); 429 m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL); 430} 431 432void PartialUpdateTest::initEGLContext (EGLConfig config) 433{ 434 const Library& egl = m_eglTestCtx.getLibrary(); 435 const EGLint attribList[] = 436 { 437 EGL_CONTEXT_CLIENT_VERSION, 2, 438 EGL_NONE 439 }; 440 441 egl.bindAPI(EGL_OPENGL_ES_API); 442 m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList); 443 EGLU_CHECK_MSG(egl, "eglCreateContext"); 444 TCU_CHECK(m_eglSurface != EGL_NO_SURFACE); 445 egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 446 EGLU_CHECK_MSG(egl, "eglMakeCurrent"); 447} 448 449// return indices of frames that have been written to the given buffer 450vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx) 451{ 452 DE_ASSERT(frameNdx < (int)bufferAges.size()); 453 vector<int> frameOnBuffer; 454 int age = bufferAges[frameNdx]; 455 while (age != 0) 456 { 457 frameNdx = frameNdx - age; 458 DE_ASSERT(frameNdx >= 0); 459 frameOnBuffer.push_back(frameNdx); 460 age = bufferAges[frameNdx]; 461 } 462 463 reverse(frameOnBuffer.begin(), frameOnBuffer.end()); 464 return frameOnBuffer; 465} 466 467vector<EGLint> getDamageRegion (const Frame& frame, int marginLeft, int marginBottom, int marginRight, int marginTop) 468{ 469 vector<EGLint> damageRegion; 470 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++) 471 { 472 const ColoredRect& rect = frame.draws[drawNdx].rect; 473 damageRegion.push_back(rect.bottomLeft.x() - marginLeft); 474 damageRegion.push_back(rect.bottomLeft.y() - marginBottom); 475 damageRegion.push_back(rect.topRight.x() - rect.bottomLeft.x() + marginLeft + marginRight); 476 damageRegion.push_back(rect.topRight.y() - rect.bottomLeft.y() + marginBottom + marginTop); 477 } 478 return damageRegion; 479} 480 481TestCase::IterateResult PartialUpdateTest::iterate (void) 482{ 483 de::Random rnd (m_seed); 484 const Library& egl = m_eglTestCtx.getLibrary(); 485 tcu::TestLog& log = m_testCtx.getLog(); 486 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH); 487 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT); 488 const float clearRed = rnd.getFloat(); 489 const float clearGreen = rnd.getFloat(); 490 const float clearBlue = rnd.getFloat(); 491 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f); 492 const int numFrames = 20; 493 FrameSequence frameSequence; 494 vector<int> bufferAges; 495 bool hasPositiveAge = false; 496 497 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++) 498 { 499 tcu::Surface currentBuffer (width, height); 500 tcu::Surface refBuffer (width, height); 501 Frame newFrame (width, height); 502 EGLint currentBufferAge = -1; 503 vector<EGLint> damageRegion; 504 505 if (frameNdx % 2 == 0) 506 generateRandomFrame(newFrame, m_evenFrameDrawType, rnd); 507 else 508 generateRandomFrame(newFrame, m_oddFrameDrawType, rnd); 509 510 frameSequence.push_back(newFrame); 511 512 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, ¤tBufferAge)); 513 514 if (currentBufferAge > frameNdx || currentBufferAge < 0) // invalid buffer age 515 { 516 std::ostringstream stream; 517 stream << "Fail, the age is invalid. Age: " << currentBufferAge << ", frameNdx: " << frameNdx; 518 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str()); 519 return STOP; 520 } 521 522 bufferAges.push_back(currentBufferAge); 523 DE_ASSERT((int)bufferAges.size() == frameNdx+1); 524 525 if (currentBufferAge > 0) 526 { 527 hasPositiveAge = true; 528 529 if (m_supportBufferAge) 530 damageRegion = getDamageRegion(newFrame, 10, 10, 10, 10); 531 else 532 damageRegion = getDamageRegion(newFrame, 0, 0, 0, 0); 533 534 EGLU_CHECK_CALL(egl, setDamageRegionKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size())); 535 } 536 else 537 { 538 EGLU_CHECK_CALL(egl, setDamageRegionKHR(m_eglDisplay, m_eglSurface, NULL, 0)); 539 clearColorScreen(m_gl, clearColor); 540 } 541 542 // during first half, just keep rendering without reading pixel back to mimic ordinary use case 543 if (frameNdx < numFrames/2) 544 m_gles2Renderer->render(width, height, newFrame); 545 else // do verification in the second half 546 { 547 const vector<int> framesOnBuffer = getFramesOnBuffer(bufferAges, frameNdx); 548 549 clearColorReference(&refBuffer, clearColor); 550 551 for (vector<int>::const_iterator it = framesOnBuffer.begin(); it != framesOnBuffer.end(); it++) 552 m_refRenderer->render(&refBuffer, frameSequence[*it]); 553 554 m_gles2Renderer->render(width, height, newFrame); 555 m_refRenderer->render(&refBuffer, newFrame); 556 557 readPixels(m_gl, ¤tBuffer); 558 559 if (!compareToReference(log, refBuffer, currentBuffer, frameNdx, frameNdx)) 560 { 561 string errorMessage("Fail, render result is wrong. Buffer age is "); 562 errorMessage += (m_supportBufferAge ? "supported" : "not supported"); 563 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, errorMessage.c_str()); 564 return STOP; 565 } 566 } 567 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface)); 568 } 569 570 if (!hasPositiveAge) // fraud behavior, pretend to support partial_update 571 { 572 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, claim to support partial_update but buffer age is always 0"); 573 return STOP; 574 } 575 576 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 577 return STOP; 578} 579 580string generateDrawTypeName (const vector<PartialUpdateTest::DrawType>& drawTypes) 581{ 582 std::ostringstream stream; 583 if (drawTypes.size() == 0) 584 return string("_none"); 585 586 for (size_t ndx = 0; ndx < drawTypes.size(); ndx++) 587 { 588 if (drawTypes[ndx] == PartialUpdateTest::DRAWTYPE_GLES2_RENDER) 589 stream << "_render"; 590 else if (drawTypes[ndx] == PartialUpdateTest::DRAWTYPE_GLES2_CLEAR) 591 stream << "_clear"; 592 else 593 DE_ASSERT(false); 594 } 595 return stream.str(); 596} 597 598string generateTestName (const vector<PartialUpdateTest::DrawType>& oddFrameDrawType, const vector<PartialUpdateTest::DrawType>& evenFrameDrawType) 599{ 600 return "odd" + generateDrawTypeName(oddFrameDrawType) + "_even" + generateDrawTypeName(evenFrameDrawType); 601} 602 603bool isWindow (const eglu::CandidateConfig& c) 604{ 605 return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT; 606} 607 608bool isES2Renderable (const eglu::CandidateConfig& c) 609{ 610 return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT; 611} 612 613EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay) 614{ 615 eglu::FilterList filters; 616 filters << isWindow << isES2Renderable; 617 return eglu::chooseSingleConfig(egl, eglDisplay, filters); 618} 619 620void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor) 621{ 622 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); 623 gl.clear(GL_COLOR_BUFFER_BIT); 624} 625 626void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor) 627{ 628 tcu::clear(ref->getAccess(), clearColor); 629} 630 631void readPixels (const glw::Functions& gl, tcu::Surface* screen) 632{ 633 gl.readPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr()); 634} 635 636float windowToDeviceCoordinates (int x, int length) 637{ 638 return (2.0f * float(x) / float(length)) - 1.0f; 639} 640 641bool compareToReference (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum) 642{ 643 std::ostringstream stream; 644 stream << "FrameNdx = " << frameNdx << ", compare current buffer (numbered: " << bufferNum << ") to reference"; 645 return tcu::intThresholdPositionDeviationCompare(log, "partial update test", stream.str().c_str(), reference.getAccess(), buffer.getAccess(), 646 tcu::UVec4(8, 8, 8, 0), tcu::IVec3(2,2,0), true, tcu::COMPARE_LOG_RESULT); 647} 648 649} // anonymous 650 651PartialUpdateTests::PartialUpdateTests (EglTestContext& eglTestCtx) 652 : TestCaseGroup(eglTestCtx, "partial_update", "Partial update tests") 653{ 654} 655 656void PartialUpdateTests::init (void) 657{ 658 const PartialUpdateTest::DrawType clearRender[2] = 659 { 660 PartialUpdateTest::DRAWTYPE_GLES2_CLEAR, 661 PartialUpdateTest::DRAWTYPE_GLES2_RENDER 662 }; 663 664 const PartialUpdateTest::DrawType renderClear[2] = 665 { 666 PartialUpdateTest::DRAWTYPE_GLES2_RENDER, 667 PartialUpdateTest::DRAWTYPE_GLES2_CLEAR 668 }; 669 670 vector< vector<PartialUpdateTest::DrawType> > frameDrawTypes; 671 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> ()); 672 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (1, PartialUpdateTest::DRAWTYPE_GLES2_CLEAR)); 673 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (1, PartialUpdateTest::DRAWTYPE_GLES2_RENDER)); 674 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (2, PartialUpdateTest::DRAWTYPE_GLES2_CLEAR)); 675 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (2, PartialUpdateTest::DRAWTYPE_GLES2_RENDER)); 676 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender))); 677 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear))); 678 679 for (size_t evenNdx = 0; evenNdx < frameDrawTypes.size(); evenNdx++) 680 { 681 const vector<PartialUpdateTest::DrawType>& evenFrameDrawType = frameDrawTypes[evenNdx]; 682 683 for (size_t oddNdx = evenNdx; oddNdx < frameDrawTypes.size(); oddNdx++) 684 { 685 const vector<PartialUpdateTest::DrawType>& oddFrameDrawType = frameDrawTypes[oddNdx]; 686 const std::string name = generateTestName(oddFrameDrawType, evenFrameDrawType); 687 if (oddFrameDrawType.size() == 0 && evenFrameDrawType.size() == 0) 688 continue; 689 690 addChild(new PartialUpdateTest(m_eglTestCtx, oddFrameDrawType, evenFrameDrawType, name.c_str(), "")); 691 } 692 } 693} 694 695} // egl 696} // deqp 697