1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL Module
3 * ---------------------------------------
5 * Copyright 2015 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Test KHR_swap_buffer_with_damage
22 *//*--------------------------------------------------------------------*/
24 #include "teglSwapBuffersWithDamageTests.hpp"
26 #include "tcuImageCompare.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuTextureUtil.hpp"
30 #include "egluNativeWindow.hpp"
31 #include "egluUtil.hpp"
32 #include "egluConfigFilter.hpp"
34 #include "eglwLibrary.hpp"
35 #include "eglwEnums.hpp"
37 #include "gluDefs.hpp"
38 #include "gluRenderContext.hpp"
39 #include "gluShaderProgram.hpp"
41 #include "glwDefs.hpp"
42 #include "glwEnums.hpp"
43 #include "glwFunctions.hpp"
45 #include "deRandom.hpp"
66 typedef tcu::Vector<GLubyte, 3> Color;
77 RESIZETYPE_BEFORE_SWAP,
78 RESIZETYPE_AFTER_SWAP,
86 ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_);
92 ColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_)
93 : bottomLeft (bottomLeft_)
94 , topRight (topRight_)
101 DrawCommand (DrawType drawType_, const ColoredRect& rect_);
106 DrawCommand::DrawCommand (DrawType drawType_, const ColoredRect& rect_)
107 : drawType (drawType_)
114 Frame (int width_, int height_);
117 vector<DrawCommand> draws;
120 Frame::Frame (int width_, int height_)
126 typedef vector<Frame> FrameSequence;
128 //helper function declaration
129 EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer);
130 void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor);
131 float windowToDeviceCoordinates (int x, int length);
136 GLES2Renderer (const glw::Functions& gl);
137 ~GLES2Renderer (void);
138 void render (int width, int height, const Frame& frame) const;
141 GLES2Renderer (const GLES2Renderer&);
142 GLES2Renderer& operator= (const GLES2Renderer&);
144 const glw::Functions& m_gl;
145 glu::ShaderProgram m_glProgram;
146 glw::GLuint m_coordLoc;
147 glw::GLuint m_colorLoc;
150 // generate sources for vertex and fragment buffer
151 glu::ProgramSources getSources (void)
153 const char* const vertexShaderSource =
154 "attribute mediump vec2 a_pos;\n"
155 "attribute mediump vec4 a_color;\n"
156 "varying mediump vec4 v_color;\n"
159 "\tv_color = a_color;\n"
160 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
163 const char* const fragmentShaderSource =
164 "varying mediump vec4 v_color;\n"
167 "\tgl_FragColor = v_color;\n"
170 return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource);
173 GLES2Renderer::GLES2Renderer (const glw::Functions& gl)
175 , m_glProgram (gl, getSources())
176 , m_coordLoc ((glw::GLuint)-1)
177 , m_colorLoc ((glw::GLuint)-1)
179 m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color");
180 m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos");
181 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations");
184 GLES2Renderer::~GLES2Renderer (void)
188 void GLES2Renderer::render (int width, int height, const Frame& frame) const
190 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
192 const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
194 if (frame.draws[drawNdx].drawType == DRAWTYPE_GLES2_RENDER)
196 const float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width);
197 const float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height);
198 const float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width);
199 const float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height);
201 const glw::GLfloat coords[] =
212 const glw::GLubyte colors[] =
214 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
215 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
216 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
218 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
219 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
220 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
223 m_gl.useProgram(m_glProgram.getProgram());
224 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
226 m_gl.enableVertexAttribArray(m_coordLoc);
227 m_gl.enableVertexAttribArray(m_colorLoc);
228 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes");
230 m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords);
231 m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
232 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers");
234 m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/2);
235 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed");
237 m_gl.disableVertexAttribArray(m_coordLoc);
238 m_gl.disableVertexAttribArray(m_colorLoc);
239 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes");
242 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
244 else if (frame.draws[drawNdx].drawType == DRAWTYPE_GLES2_CLEAR)
246 m_gl.enable(GL_SCISSOR_TEST);
247 m_gl.scissor(coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(),
248 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y());
249 m_gl.clearColor(coloredRect.color.x()/255.0f, coloredRect.color.y()/255.0f, coloredRect.color.z()/255.0f, 1.0f);
250 m_gl.clear(GL_COLOR_BUFFER_BIT);
251 m_gl.disable(GL_SCISSOR_TEST);
254 DE_FATAL("Invalid drawtype");
258 class SwapBuffersWithDamageTest : public TestCase
261 SwapBuffersWithDamageTest (EglTestContext& eglTestCtx,
262 const vector<DrawType>& frameDrawType,
264 ResizeType resizeType,
266 const char* description);
268 ~SwapBuffersWithDamageTest (void);
270 virtual void init (void);
272 virtual IterateResult iterate (void);
275 virtual EGLConfig getConfig (const Library& egl, EGLDisplay eglDisplay);
276 virtual void checkExtension (const Library& egl, EGLDisplay eglDisplay);
277 void initEGLSurface (EGLConfig config);
278 void initEGLContext (EGLConfig config);
280 eglu::NativeWindow* m_window;
281 EGLConfig m_eglConfig;
282 EGLContext m_eglContext;
284 const int m_iterationTimes;
285 const vector<DrawType> m_frameDrawType;
286 const ResizeType m_resizeType;
287 EGLDisplay m_eglDisplay;
288 EGLSurface m_eglSurface;
290 GLES2Renderer* m_gles2Renderer;
293 SwapBuffersWithDamageTest::SwapBuffersWithDamageTest (EglTestContext& eglTestCtx, const vector<DrawType>& frameDrawType, int iterationTimes, ResizeType resizeType, const char* name, const char* description)
294 : TestCase (eglTestCtx, name, description)
296 , m_eglContext (EGL_NO_CONTEXT)
297 , m_seed (deStringHash(name))
298 , m_iterationTimes (iterationTimes)
299 , m_frameDrawType (frameDrawType)
300 , m_resizeType (resizeType)
301 , m_eglDisplay (EGL_NO_DISPLAY)
302 , m_eglSurface (EGL_NO_SURFACE)
303 , m_gles2Renderer (DE_NULL)
307 SwapBuffersWithDamageTest::~SwapBuffersWithDamageTest (void)
312 EGLConfig SwapBuffersWithDamageTest::getConfig (const Library& egl, EGLDisplay eglDisplay)
314 return getEGLConfig(egl, eglDisplay, false);
317 void SwapBuffersWithDamageTest::checkExtension (const Library& egl, EGLDisplay eglDisplay)
319 if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage"))
320 TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported");
323 void SwapBuffersWithDamageTest::init (void)
325 const Library& egl = m_eglTestCtx.getLibrary();
327 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
328 m_eglConfig = getConfig(egl, m_eglDisplay);
330 checkExtension(egl, m_eglDisplay);
332 initEGLSurface(m_eglConfig);
333 initEGLContext(m_eglConfig);
335 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
336 m_gles2Renderer = new GLES2Renderer(m_gl);
339 void SwapBuffersWithDamageTest::deinit (void)
341 const Library& egl = m_eglTestCtx.getLibrary();
343 delete m_gles2Renderer;
344 m_gles2Renderer = DE_NULL;
346 if (m_eglContext != EGL_NO_CONTEXT)
348 egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
349 egl.destroyContext(m_eglDisplay, m_eglContext);
350 m_eglContext = EGL_NO_CONTEXT;
353 if (m_eglSurface != EGL_NO_SURFACE)
355 egl.destroySurface(m_eglDisplay, m_eglSurface);
356 m_eglSurface = EGL_NO_SURFACE;
359 if (m_eglDisplay != EGL_NO_DISPLAY)
361 egl.terminate(m_eglDisplay);
362 m_eglDisplay = EGL_NO_DISPLAY;
369 void SwapBuffersWithDamageTest::initEGLSurface (EGLConfig config)
371 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
372 m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL,
373 eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
374 m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL);
377 void SwapBuffersWithDamageTest::initEGLContext (EGLConfig config)
379 const Library& egl = m_eglTestCtx.getLibrary();
380 const EGLint attribList[] =
382 EGL_CONTEXT_CLIENT_VERSION, 2,
386 egl.bindAPI(EGL_OPENGL_ES_API);
387 m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList);
388 EGLU_CHECK_MSG(egl, "eglCreateContext");
389 TCU_CHECK(m_eglSurface != EGL_NO_SURFACE);
390 egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
391 EGLU_CHECK_MSG(egl, "eglMakeCurrent");
394 FrameSequence generateFrameSequence (const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height);
395 vector<EGLint> getDamageRegion (const Frame& frame);
397 TestCase::IterateResult SwapBuffersWithDamageTest::iterate (void)
399 de::Random rnd (m_seed);
400 const Library& egl = m_eglTestCtx.getLibrary();
401 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
402 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
403 const float clearRed = rnd.getFloat();
404 const float clearGreen = rnd.getFloat();
405 const float clearBlue = rnd.getFloat();
406 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f);
407 const int numFrames = 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
408 const FrameSequence frameSequence = generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);
410 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
411 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
413 for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
415 for (int currentFrameNdx = 0; currentFrameNdx < numFrames; currentFrameNdx++)
417 vector<EGLint> damageRegion = getDamageRegion(frameSequence[currentFrameNdx]);
419 clearColorScreen(m_gl, clearColor);
420 for (int ndx = 0; ndx <= currentFrameNdx; ndx++)
421 m_gles2Renderer->render(width, height, frameSequence[ndx]);
423 if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
425 if (iterationNdx % 2 == 0)
426 m_window->setSurfaceSize(IVec2(width*2, height/2));
428 m_window->setSurfaceSize(IVec2(height/2, width*2));
431 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
433 if (m_resizeType == RESIZETYPE_AFTER_SWAP)
435 if (iterationNdx % 2 == 0)
436 m_window->setSurfaceSize(IVec2(width*2, height/2));
438 m_window->setSurfaceSize(IVec2(height/2, width*2));
445 class SwapBuffersWithDamageAndPreserveBufferTest : public SwapBuffersWithDamageTest
448 SwapBuffersWithDamageAndPreserveBufferTest (EglTestContext& eglTestCtx,
449 const vector<DrawType>& frameDrawType,
451 ResizeType resizeType,
453 const char* description);
455 IterateResult iterate (void);
458 EGLConfig getConfig (const Library& egl, EGLDisplay eglDisplay);
461 SwapBuffersWithDamageAndPreserveBufferTest::SwapBuffersWithDamageAndPreserveBufferTest (EglTestContext& eglTestCtx,
462 const vector<DrawType>& frameDrawType,
464 ResizeType resizeType,
466 const char* description)
467 : SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, resizeType, name, description)
471 EGLConfig SwapBuffersWithDamageAndPreserveBufferTest::getConfig (const Library& egl, EGLDisplay eglDisplay)
473 return getEGLConfig(egl, eglDisplay, true);
476 TestCase::IterateResult SwapBuffersWithDamageAndPreserveBufferTest::iterate (void)
479 de::Random rnd (m_seed);
480 const Library& egl = m_eglTestCtx.getLibrary();
481 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
482 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
483 const float clearRed = rnd.getFloat();
484 const float clearGreen = rnd.getFloat();
485 const float clearBlue = rnd.getFloat();
486 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f);
487 const int numFrames = 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
488 const FrameSequence frameSequence = generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);
490 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
491 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));
493 for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
495 clearColorScreen(m_gl, clearColor);
496 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));
498 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
500 const Frame& currentFrame = frameSequence[frameNdx];
501 vector<EGLint> damageRegion = getDamageRegion(currentFrame);
503 m_gles2Renderer->render(width, height, currentFrame);
505 if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
507 if (iterationNdx % 2 == 0)
508 m_window->setSurfaceSize(IVec2(width*2, height/2));
510 m_window->setSurfaceSize(IVec2(height/2, width*2));
513 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
515 if (m_resizeType == RESIZETYPE_AFTER_SWAP)
517 if (iterationNdx % 2 == 0)
518 m_window->setSurfaceSize(IVec2(width*2, height/2));
520 m_window->setSurfaceSize(IVec2(height/2, width*2));
528 class SwapBuffersWithDamageAndBufferAgeTest : public SwapBuffersWithDamageTest
531 SwapBuffersWithDamageAndBufferAgeTest (EglTestContext& eglTestCtx,
532 const vector<DrawType>& frameDrawType,
534 ResizeType resizeType,
536 const char* description);
538 IterateResult iterate (void);
541 void checkExtension (const Library& egl, EGLDisplay eglDisplay);
544 SwapBuffersWithDamageAndBufferAgeTest::SwapBuffersWithDamageAndBufferAgeTest (EglTestContext& eglTestCtx,
545 const vector<DrawType>& frameDrawType,
547 ResizeType resizeType,
549 const char* description)
550 : SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, resizeType, name, description)
555 void SwapBuffersWithDamageAndBufferAgeTest::checkExtension (const Library& egl, EGLDisplay eglDisplay)
557 if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage"))
558 TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported");
560 if (!eglu::hasExtension(egl, eglDisplay, "EGL_EXT_buffer_age"))
561 TCU_THROW(NotSupportedError, "EGL_EXT_buffer_age not supported");
564 TestCase::IterateResult SwapBuffersWithDamageAndBufferAgeTest::iterate (void)
567 de::Random rnd (m_seed);
568 const Library& egl = m_eglTestCtx.getLibrary();
569 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
570 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
571 const float clearRed = rnd.getFloat();
572 const float clearGreen = rnd.getFloat();
573 const float clearBlue = rnd.getFloat();
574 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f);
575 const int numFrames = 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
576 const FrameSequence frameSequence = generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);
578 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
579 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
581 for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
583 clearColorScreen(m_gl, clearColor);
584 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));
586 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
588 vector<EGLint> damageRegion;
590 int startFrameNdx = -1;
591 int endFrameNdx = frameNdx;
593 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, &bufferAge));
595 if (bufferAge < 0) // invalid buffer age
597 std::ostringstream stream;
598 stream << "Fail, the age is invalid. Age: " << bufferAge << ", frameNdx: " << frameNdx;
599 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
603 if (bufferAge == 0 || bufferAge > frameNdx)
605 clearColorScreen(m_gl, clearColor);
609 startFrameNdx = frameNdx-bufferAge+1;
611 for (int ndx = startFrameNdx; ndx <= endFrameNdx; ndx++)
613 const vector<EGLint> partialDamageRegion = getDamageRegion(frameSequence[ndx]);
615 damageRegion.insert(damageRegion.end(), partialDamageRegion.begin(), partialDamageRegion.end());
616 m_gles2Renderer->render(width, height, frameSequence[ndx]);
619 if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
621 if (iterationNdx % 2 == 0)
622 m_window->setSurfaceSize(IVec2(width*2, height/2));
624 m_window->setSurfaceSize(IVec2(height/2, width*2));
627 EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
629 if (m_resizeType == RESIZETYPE_AFTER_SWAP)
631 if (iterationNdx % 2 == 0)
632 m_window->setSurfaceSize(IVec2(width*2, height/2));
634 m_window->setSurfaceSize(IVec2(height/2, width*2));
641 // generate a frame sequence with certain frame for visual verification
642 FrameSequence generateFrameSequence (const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height)
644 const int frameDiff = height / numFrames;
645 const GLubyte r = rnd.getUint8();
646 const GLubyte g = rnd.getUint8();
647 const GLubyte b = rnd.getUint8();
648 const Color color (r, g, b);
649 FrameSequence frameSequence;
651 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
653 Frame frame (width, height);
655 for (int rectNdx = 0; rectNdx < (int)frameDrawType.size(); rectNdx++)
657 const int rectHeight = frameDiff / (int)frameDrawType.size();
658 const ColoredRect rect (IVec2(0, frameNdx*frameDiff+rectNdx*rectHeight), IVec2(width, frameNdx*frameDiff+(rectNdx+1)*rectHeight), color);
659 const DrawCommand drawCommand (frameDrawType[rectNdx], rect);
661 frame.draws.push_back(drawCommand);
663 frameSequence.push_back(frame);
665 return frameSequence;
668 vector<EGLint> getDamageRegion (const Frame& frame)
670 vector<EGLint> damageRegion;
671 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
673 const ColoredRect& rect = frame.draws[drawNdx].rect;
674 damageRegion.push_back(rect.bottomLeft.x());
675 damageRegion.push_back(rect.bottomLeft.y());
676 damageRegion.push_back(rect.topRight.x() - rect.bottomLeft.x());
677 damageRegion.push_back(rect.topRight.y() - rect.bottomLeft.y());
680 DE_ASSERT(damageRegion.size() % 4 == 0);
684 string generateTestName (const vector<DrawType>& frameDrawType)
686 std::ostringstream stream;
688 for (size_t ndx = 0; ndx < frameDrawType.size(); ndx++)
690 if (frameDrawType[ndx] == DRAWTYPE_GLES2_RENDER)
692 else if (frameDrawType[ndx] == DRAWTYPE_GLES2_CLEAR)
697 if (ndx < frameDrawType.size()-1)
704 string generateResizeGroupName (ResizeType resizeType)
708 case RESIZETYPE_NONE:
711 case RESIZETYPE_AFTER_SWAP:
712 return "resize_after_swap";
714 case RESIZETYPE_BEFORE_SWAP:
715 return "resize_before_swap";
718 DE_FATAL("Unknown resize type");
723 bool isWindow (const eglu::CandidateConfig& c)
725 return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
728 bool isES2Renderable (const eglu::CandidateConfig& c)
730 return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
733 bool hasPreserveSwap (const eglu::CandidateConfig& c)
735 return (c.surfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
738 EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer)
740 eglu::FilterList filters;
742 filters << isWindow << isES2Renderable;
744 filters << hasPreserveSwap;
746 return eglu::chooseSingleConfig(egl, eglDisplay, filters);
749 void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor)
751 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
752 gl.clear(GL_COLOR_BUFFER_BIT);
755 float windowToDeviceCoordinates (int x, int length)
757 return (2.0f * float(x) / float(length)) - 1.0f;
762 SwapBuffersWithDamageTests::SwapBuffersWithDamageTests (EglTestContext& eglTestCtx)
763 : TestCaseGroup(eglTestCtx, "swap_buffers_with_damage", "Swap buffers with damages tests")
767 void SwapBuffersWithDamageTests::init (void)
769 const DrawType clearRender[2] =
771 DRAWTYPE_GLES2_CLEAR,
772 DRAWTYPE_GLES2_RENDER
775 const DrawType renderClear[2] =
777 DRAWTYPE_GLES2_RENDER,
781 const ResizeType resizeTypes[] =
784 RESIZETYPE_BEFORE_SWAP,
785 RESIZETYPE_AFTER_SWAP
788 vector< vector<DrawType> > frameDrawTypes;
789 frameDrawTypes.push_back(vector<DrawType> (1, DRAWTYPE_GLES2_CLEAR));
790 frameDrawTypes.push_back(vector<DrawType> (1, DRAWTYPE_GLES2_RENDER));
791 frameDrawTypes.push_back(vector<DrawType> (2, DRAWTYPE_GLES2_CLEAR));
792 frameDrawTypes.push_back(vector<DrawType> (2, DRAWTYPE_GLES2_RENDER));
793 frameDrawTypes.push_back(vector<DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender)));
794 frameDrawTypes.push_back(vector<DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear)));
796 for (size_t resizeTypeNdx = 0; resizeTypeNdx < DE_LENGTH_OF_ARRAY(resizeTypes); resizeTypeNdx++)
798 const ResizeType resizeType = resizeTypes[resizeTypeNdx];
799 TestCaseGroup* const resizeGroup = new TestCaseGroup(m_eglTestCtx, generateResizeGroupName(resizeType).c_str(), "");
801 for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
803 string name = generateTestName(frameDrawTypes[drawTypeNdx]);
804 resizeGroup->addChild(new SwapBuffersWithDamageTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, resizeType, name.c_str(), ""));
807 for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
809 string name = "preserve_buffer_" + generateTestName(frameDrawTypes[drawTypeNdx]);
810 resizeGroup->addChild(new SwapBuffersWithDamageAndPreserveBufferTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, resizeType, name.c_str(), ""));
813 for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
815 string name = "buffer_age_" + generateTestName(frameDrawTypes[drawTypeNdx]);
816 resizeGroup->addChild(new SwapBuffersWithDamageAndBufferAgeTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, resizeType, name.c_str(), ""));
819 addChild(resizeGroup);