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_partial_update
22 *//*--------------------------------------------------------------------*/
24 #include "teglPartialUpdateTests.hpp"
26 #include "tcuImageCompare.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuTextureUtil.hpp"
31 #include "egluNativeWindow.hpp"
32 #include "egluUtil.hpp"
33 #include "egluConfigFilter.hpp"
35 #include "eglwLibrary.hpp"
36 #include "eglwEnums.hpp"
38 #include "gluDefs.hpp"
39 #include "gluRenderContext.hpp"
40 #include "gluShaderProgram.hpp"
42 #include "glwDefs.hpp"
43 #include "glwEnums.hpp"
44 #include "glwFunctions.hpp"
46 #include "deRandom.hpp"
67 typedef tcu::Vector<GLubyte, 3> Color;
71 class ReferenceRenderer;
73 class PartialUpdateTest : public TestCase
82 PartialUpdateTest (EglTestContext& eglTestCtx,
83 const vector<DrawType>& oddFrameDrawType,
84 const vector<DrawType>& evenFrameDrawType,
86 const char* description);
87 ~PartialUpdateTest (void);
91 IterateResult iterate (void);
94 eglu::NativeWindow* m_window;
95 EGLConfig m_eglConfig;
96 EGLContext m_eglContext;
99 void initEGLSurface (EGLConfig config);
100 void initEGLContext (EGLConfig config);
103 const vector<DrawType> m_oddFrameDrawType;
104 const vector<DrawType> m_evenFrameDrawType;
106 bool m_supportBufferAge;
107 EGLDisplay m_eglDisplay;
108 EGLSurface m_eglSurface;
111 GLES2Renderer* m_gles2Renderer;
112 ReferenceRenderer* m_refRenderer;
118 ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_);
124 ColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_)
125 : bottomLeft (bottomLeft_)
126 , topRight (topRight_)
133 DrawCommand (const PartialUpdateTest::DrawType drawType_, const ColoredRect& rect_);
134 PartialUpdateTest::DrawType drawType;
138 DrawCommand::DrawCommand (const PartialUpdateTest::DrawType drawType_, const ColoredRect& rect_)
139 : drawType (drawType_)
146 Frame (int width_, int height_);
149 vector<DrawCommand> draws;
152 Frame::Frame (int width_, int height_)
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()
162 void generateRandomFrame (Frame& dst, const vector<PartialUpdateTest::DrawType>& drawTypes, de::Random& rnd)
164 for (size_t ndx = 0; ndx < drawTypes.size(); ndx++)
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);
176 dst.draws.push_back(drawCommand);
180 typedef vector<Frame> FrameSequence;
182 //helper function declaration
183 EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay);
184 void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor);
185 void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor);
186 void readPixels (const glw::Functions& gl, tcu::Surface* screen);
187 float windowToDeviceCoordinates (int x, int length);
188 bool compareToReference (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum);
189 vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx);
194 GLES2Renderer (const glw::Functions& gl);
195 ~GLES2Renderer (void);
196 void render (int width, int height, const Frame& frame) const;
199 GLES2Renderer (const GLES2Renderer&);
200 GLES2Renderer& operator= (const GLES2Renderer&);
202 const glw::Functions& m_gl;
203 glu::ShaderProgram m_glProgram;
204 glw::GLuint m_coordLoc;
205 glw::GLuint m_colorLoc;
208 // generate sources for vertex and fragment buffer
209 glu::ProgramSources getSources (void)
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"
217 "\tv_color = a_color;\n"
218 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
221 const char* const fragmentShaderSource =
222 "varying mediump vec4 v_color;\n"
225 "\tgl_FragColor = v_color;\n"
228 return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource);
231 GLES2Renderer::GLES2Renderer (const glw::Functions& gl)
233 , m_glProgram (gl, getSources())
234 , m_coordLoc ((glw::GLuint)-1)
235 , m_colorLoc ((glw::GLuint)-1)
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");
242 GLES2Renderer::~GLES2Renderer (void)
246 void GLES2Renderer::render (int width, int height, const Frame& frame) const
248 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
250 const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
252 if (frame.draws[drawNdx].drawType == PartialUpdateTest::DRAWTYPE_GLES2_RENDER)
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);
259 const glw::GLfloat coords[] =
270 const glw::GLubyte colors[] =
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,
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,
281 m_gl.useProgram(m_glProgram.getProgram());
282 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
284 m_gl.enableVertexAttribArray(m_coordLoc);
285 m_gl.enableVertexAttribArray(m_colorLoc);
286 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes");
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");
292 m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/2);
293 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed");
295 m_gl.disableVertexAttribArray(m_coordLoc);
296 m_gl.disableVertexAttribArray(m_colorLoc);
297 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes");
300 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
302 else if (frame.draws[drawNdx].drawType == PartialUpdateTest::DRAWTYPE_GLES2_CLEAR)
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);
312 DE_FATAL("Invalid drawtype");
316 class ReferenceRenderer
319 ReferenceRenderer (void);
320 void render (tcu::Surface* target, const Frame& frame) const;
322 ReferenceRenderer (const ReferenceRenderer&);
323 ReferenceRenderer& operator= (const ReferenceRenderer&);
326 ReferenceRenderer::ReferenceRenderer(void)
330 void ReferenceRenderer::render (tcu::Surface* target, const Frame& frame) const
332 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
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)
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);
342 DE_FATAL("Invalid drawtype");
346 PartialUpdateTest::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)
352 , m_eglContext (EGL_NO_CONTEXT)
353 , m_seed (deStringHash(name))
354 , m_oddFrameDrawType (oddFrameDrawType)
355 , m_evenFrameDrawType (evenFrameDrawType)
356 , m_supportBufferAge (false)
357 , m_eglDisplay (EGL_NO_DISPLAY)
358 , m_eglSurface (EGL_NO_SURFACE)
359 , m_gles2Renderer (DE_NULL)
360 , m_refRenderer (DE_NULL)
364 PartialUpdateTest::~PartialUpdateTest (void)
369 void PartialUpdateTest::init (void)
371 const Library& egl = m_eglTestCtx.getLibrary();
373 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
374 m_eglConfig = getEGLConfig(m_eglTestCtx.getLibrary(), m_eglDisplay);
376 //create surface and context and make them current
377 initEGLSurface(m_eglConfig);
378 initEGLContext(m_eglConfig);
380 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
382 m_supportBufferAge = eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_buffer_age");
384 if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_KHR_partial_update"))
385 TCU_THROW(NotSupportedError, "EGL_KHR_partial_update is not supported");
387 m_gles2Renderer = new GLES2Renderer(m_gl);
388 m_refRenderer = new ReferenceRenderer();
391 void PartialUpdateTest::deinit (void)
393 const Library& egl = m_eglTestCtx.getLibrary();
395 delete m_refRenderer;
396 m_refRenderer = DE_NULL;
398 delete m_gles2Renderer;
399 m_gles2Renderer = DE_NULL;
401 if (m_eglContext != EGL_NO_CONTEXT)
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;
408 if (m_eglSurface != EGL_NO_SURFACE)
410 egl.destroySurface(m_eglDisplay, m_eglSurface);
411 m_eglSurface = EGL_NO_SURFACE;
414 if (m_eglDisplay != EGL_NO_DISPLAY)
416 egl.terminate(m_eglDisplay);
417 m_eglDisplay = EGL_NO_DISPLAY;
424 void PartialUpdateTest::initEGLSurface (EGLConfig config)
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);
432 void PartialUpdateTest::initEGLContext (EGLConfig config)
434 const Library& egl = m_eglTestCtx.getLibrary();
435 const EGLint attribList[] =
437 EGL_CONTEXT_CLIENT_VERSION, 2,
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");
449 // return indices of frames that have been written to the given buffer
450 vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx)
452 DE_ASSERT(frameNdx < (int)bufferAges.size());
453 vector<int> frameOnBuffer;
454 int age = bufferAges[frameNdx];
457 frameNdx = frameNdx - age;
458 DE_ASSERT(frameNdx >= 0);
459 frameOnBuffer.push_back(frameNdx);
460 age = bufferAges[frameNdx];
463 reverse(frameOnBuffer.begin(), frameOnBuffer.end());
464 return frameOnBuffer;
467 vector<EGLint> getDamageRegion (const Frame& frame, int marginLeft, int marginBottom, int marginRight, int marginTop)
469 vector<EGLint> damageRegion;
470 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
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);
479 DE_ASSERT(damageRegion.size() % 4 == 0);
483 TestCase::IterateResult PartialUpdateTest::iterate (void)
485 de::Random rnd (m_seed);
486 const Library& egl = m_eglTestCtx.getLibrary();
487 tcu::TestLog& log = m_testCtx.getLog();
488 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
489 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
490 const float clearRed = rnd.getFloat();
491 const float clearGreen = rnd.getFloat();
492 const float clearBlue = rnd.getFloat();
493 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f);
494 const int numFrames = 20;
495 FrameSequence frameSequence;
496 vector<int> bufferAges;
497 bool hasPositiveAge = false;
499 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
501 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
503 tcu::Surface currentBuffer (width, height);
504 tcu::Surface refBuffer (width, height);
505 Frame newFrame (width, height);
506 EGLint currentBufferAge = -1;
507 vector<EGLint> damageRegion;
509 if (frameNdx % 2 == 0)
510 generateRandomFrame(newFrame, m_evenFrameDrawType, rnd);
512 generateRandomFrame(newFrame, m_oddFrameDrawType, rnd);
514 frameSequence.push_back(newFrame);
516 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, ¤tBufferAge));
518 if (currentBufferAge > frameNdx || currentBufferAge < 0) // invalid buffer age
520 std::ostringstream stream;
521 stream << "Fail, the age is invalid. Age: " << currentBufferAge << ", frameNdx: " << frameNdx;
522 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
526 bufferAges.push_back(currentBufferAge);
527 DE_ASSERT((int)bufferAges.size() == frameNdx+1);
529 if (currentBufferAge > 0)
531 hasPositiveAge = true;
533 if (m_supportBufferAge)
534 damageRegion = getDamageRegion(newFrame, 10, 10, 10, 10);
536 damageRegion = getDamageRegion(newFrame, 0, 0, 0, 0);
538 EGLU_CHECK_CALL(egl, setDamageRegionKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
542 EGLU_CHECK_CALL(egl, setDamageRegionKHR(m_eglDisplay, m_eglSurface, NULL, 0));
543 clearColorScreen(m_gl, clearColor);
546 // during first half, just keep rendering without reading pixel back to mimic ordinary use case
547 if (frameNdx < numFrames/2)
548 m_gles2Renderer->render(width, height, newFrame);
549 else // do verification in the second half
551 const vector<int> framesOnBuffer = getFramesOnBuffer(bufferAges, frameNdx);
553 clearColorReference(&refBuffer, clearColor);
555 for (vector<int>::const_iterator it = framesOnBuffer.begin(); it != framesOnBuffer.end(); it++)
556 m_refRenderer->render(&refBuffer, frameSequence[*it]);
558 m_gles2Renderer->render(width, height, newFrame);
559 m_refRenderer->render(&refBuffer, newFrame);
561 readPixels(m_gl, ¤tBuffer);
563 if (!compareToReference(log, refBuffer, currentBuffer, frameNdx, frameNdx))
565 string errorMessage("Fail, render result is wrong. Buffer age is ");
566 errorMessage += (m_supportBufferAge ? "supported" : "not supported");
567 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, errorMessage.c_str());
571 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
574 if (!hasPositiveAge) // fraud behavior, pretend to support partial_update
576 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, claim to support partial_update but buffer age is always 0");
580 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
584 string generateDrawTypeName (const vector<PartialUpdateTest::DrawType>& drawTypes)
586 std::ostringstream stream;
587 if (drawTypes.size() == 0)
588 return string("_none");
590 for (size_t ndx = 0; ndx < drawTypes.size(); ndx++)
592 if (drawTypes[ndx] == PartialUpdateTest::DRAWTYPE_GLES2_RENDER)
594 else if (drawTypes[ndx] == PartialUpdateTest::DRAWTYPE_GLES2_CLEAR)
602 string generateTestName (const vector<PartialUpdateTest::DrawType>& oddFrameDrawType, const vector<PartialUpdateTest::DrawType>& evenFrameDrawType)
604 return "odd" + generateDrawTypeName(oddFrameDrawType) + "_even" + generateDrawTypeName(evenFrameDrawType);
607 bool isWindow (const eglu::CandidateConfig& c)
609 return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
612 bool isES2Renderable (const eglu::CandidateConfig& c)
614 return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
617 EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay)
619 eglu::FilterList filters;
620 filters << isWindow << isES2Renderable;
621 return eglu::chooseSingleConfig(egl, eglDisplay, filters);
624 void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor)
626 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
627 gl.clear(GL_COLOR_BUFFER_BIT);
630 void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor)
632 tcu::clear(ref->getAccess(), clearColor);
635 void readPixels (const glw::Functions& gl, tcu::Surface* screen)
637 gl.readPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
640 float windowToDeviceCoordinates (int x, int length)
642 return (2.0f * float(x) / float(length)) - 1.0f;
645 bool compareToReference (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum)
647 std::ostringstream stream;
648 stream << "FrameNdx = " << frameNdx << ", compare current buffer (numbered: " << bufferNum << ") to reference";
649 return tcu::intThresholdPositionDeviationCompare(log, "partial update test", stream.str().c_str(), reference.getAccess(), buffer.getAccess(),
650 tcu::UVec4(8, 8, 8, 0), tcu::IVec3(2,2,0), true, tcu::COMPARE_LOG_RESULT);
653 class RenderOutsideDamageRegion : public PartialUpdateTest
656 RenderOutsideDamageRegion (EglTestContext& eglTestCtx);
657 TestCase::IterateResult iterate (void);
660 RenderOutsideDamageRegion::RenderOutsideDamageRegion (EglTestContext& eglTestCtx)
661 : PartialUpdateTest (eglTestCtx, vector<DrawType>(1, DRAWTYPE_GLES2_RENDER), vector<DrawType>(1, DRAWTYPE_GLES2_RENDER), "render_outside_damage_region", "")
665 TestCase::IterateResult RenderOutsideDamageRegion::iterate (void)
667 de::Random rnd (m_seed);
668 const Library& egl = m_eglTestCtx.getLibrary();
669 tcu::TestLog& log = m_testCtx.getLog();
670 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
671 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
672 const float clearRed = rnd.getFloat();
673 const float clearGreen = rnd.getFloat();
674 const float clearBlue = rnd.getFloat();
675 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f);
676 tcu::Surface currentBuffer (width, height);
677 tcu::Surface refBuffer (width, height);
678 Frame frame (width, height);
680 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
682 generateRandomFrame(frame, m_evenFrameDrawType, rnd);
685 // render outside the region
686 EGLint bufferAge = -1;
687 vector<EGLint> damageRegion = getDamageRegion(frame, 0, 0, 0, 0);
689 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
690 EGLU_CHECK_CALL(egl, setDamageRegionKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
691 clearColorScreen(m_gl, clearColor);
692 m_gles2Renderer->render(width, height, frame);
694 // next line will make the bug on Nexus 6 disappear
695 // readPixels(m_gl, ¤tBuffer);
698 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
700 // render a new frame
701 clearColorScreen(m_gl, clearColor);
702 m_gles2Renderer->render(width, height, frame);
703 clearColorReference(&refBuffer, clearColor);
704 m_refRenderer->render(&refBuffer, frame);
705 readPixels(m_gl, ¤tBuffer);
707 if (!compareToReference(log, refBuffer, currentBuffer, 0, 0))
708 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, fail to recover after rendering outside damageRegion");
710 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
715 class RenderBeforeSetDamageRegion : public PartialUpdateTest
718 RenderBeforeSetDamageRegion (EglTestContext& eglTestCtx);
719 TestCase::IterateResult iterate (void);
722 RenderBeforeSetDamageRegion::RenderBeforeSetDamageRegion (EglTestContext& eglTestCtx)
723 : PartialUpdateTest (eglTestCtx, vector<DrawType>(1, DRAWTYPE_GLES2_RENDER), vector<DrawType>(1, DRAWTYPE_GLES2_RENDER), "render_before_set_damage_region", "")
727 TestCase::IterateResult RenderBeforeSetDamageRegion::iterate (void)
729 de::Random rnd (m_seed);
730 const Library& egl = m_eglTestCtx.getLibrary();
731 tcu::TestLog& log = m_testCtx.getLog();
732 const int width = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
733 const int height = eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
734 const float clearRed = rnd.getFloat();
735 const float clearGreen = rnd.getFloat();
736 const float clearBlue = rnd.getFloat();
737 const tcu::Vec4 clearColor (clearRed, clearGreen, clearBlue, 1.0f);
738 tcu::Surface currentBuffer (width, height);
739 tcu::Surface refBuffer (width, height);
740 Frame frame (width, height);
742 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
744 generateRandomFrame(frame, m_evenFrameDrawType, rnd);
747 // render before setDamageRegion
748 EGLint bufferAge = -1;
749 vector<EGLint> damageRegion = getDamageRegion(frame, 0, 0, 0, 0);
751 m_gles2Renderer->render(width, height, frame);
752 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &bufferAge));
753 EGLU_CHECK_CALL(egl, setDamageRegionKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
755 // next line will make the bug on Nexus 6 disappear
756 // readPixels(m_gl, ¤tBuffer);
759 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
761 // render a new frame
762 clearColorScreen(m_gl, clearColor);
763 m_gles2Renderer->render(width, height, frame);
764 clearColorReference(&refBuffer, clearColor);
765 m_refRenderer->render(&refBuffer, frame);
766 readPixels(m_gl, ¤tBuffer);
768 if (!compareToReference(log, refBuffer, currentBuffer, 0, 0))
769 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
771 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
778 PartialUpdateTests::PartialUpdateTests (EglTestContext& eglTestCtx)
779 : TestCaseGroup(eglTestCtx, "partial_update", "Partial update tests")
783 void PartialUpdateTests::init (void)
785 const PartialUpdateTest::DrawType clearRender[2] =
787 PartialUpdateTest::DRAWTYPE_GLES2_CLEAR,
788 PartialUpdateTest::DRAWTYPE_GLES2_RENDER
791 const PartialUpdateTest::DrawType renderClear[2] =
793 PartialUpdateTest::DRAWTYPE_GLES2_RENDER,
794 PartialUpdateTest::DRAWTYPE_GLES2_CLEAR
797 vector< vector<PartialUpdateTest::DrawType> > frameDrawTypes;
798 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> ());
799 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (1, PartialUpdateTest::DRAWTYPE_GLES2_CLEAR));
800 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (1, PartialUpdateTest::DRAWTYPE_GLES2_RENDER));
801 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (2, PartialUpdateTest::DRAWTYPE_GLES2_CLEAR));
802 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (2, PartialUpdateTest::DRAWTYPE_GLES2_RENDER));
803 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender)));
804 frameDrawTypes.push_back(vector<PartialUpdateTest::DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear)));
806 for (size_t evenNdx = 0; evenNdx < frameDrawTypes.size(); evenNdx++)
808 const vector<PartialUpdateTest::DrawType>& evenFrameDrawType = frameDrawTypes[evenNdx];
810 for (size_t oddNdx = evenNdx; oddNdx < frameDrawTypes.size(); oddNdx++)
812 const vector<PartialUpdateTest::DrawType>& oddFrameDrawType = frameDrawTypes[oddNdx];
813 const std::string name = generateTestName(oddFrameDrawType, evenFrameDrawType);
814 if (oddFrameDrawType.size() == 0 && evenFrameDrawType.size() == 0)
817 addChild(new PartialUpdateTest(m_eglTestCtx, oddFrameDrawType, evenFrameDrawType, name.c_str(), ""));
820 addChild(new RenderOutsideDamageRegion(m_eglTestCtx));
821 addChild(new RenderBeforeSetDamageRegion(m_eglTestCtx));