blob: 523e8d8e2d9d428b640761206d3540b20697f785 [file] [log] [blame]
Hengyuan Hudb757542015-06-18 13:26:57 -07001/*-------------------------------------------------------------------------
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 EXT_buffer_age
22 *//*--------------------------------------------------------------------*/
23
24#include "teglBufferAgeTests.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 BufferAgeTest : public TestCase
74{
75public:
76 enum DrawType
77 {
78 DRAWTYPE_GLES2_CLEAR,
79 DRAWTYPE_GLES2_RENDER
80 };
81
Mika Isojärvi78d63422016-02-19 15:04:14 -080082 enum ResizeType
83 {
84 RESIZETYPE_NONE = 0,
85 RESIZETYPE_BEFORE_SWAP,
86 RESIZETYPE_AFTER_SWAP,
87
88 RESIZETYPE_LAST
89 };
90
91 BufferAgeTest (EglTestContext& eglTestCtx,
92 bool preserveColorBuffer,
93 const vector<DrawType>& oddFrameDrawType,
94 const vector<DrawType>& evenFrameDrawType,
95 ResizeType resizeType,
96 const char* name,
97 const char* description);
98
Hengyuan Hudb757542015-06-18 13:26:57 -070099 ~BufferAgeTest (void);
100
101 void init (void);
102 void deinit (void);
103 IterateResult iterate (void);
104
105private:
106 void initEGLSurface (EGLConfig config);
107 void initEGLContext (EGLConfig config);
108
109 const int m_seed;
110 const bool m_preserveColorBuffer;
111 const vector<DrawType> m_oddFrameDrawType;
112 const vector<DrawType> m_evenFrameDrawType;
Mika Isojärvi78d63422016-02-19 15:04:14 -0800113 const ResizeType m_resizeType;
Hengyuan Hudb757542015-06-18 13:26:57 -0700114
115 EGLDisplay m_eglDisplay;
116 eglu::NativeWindow* m_window;
117 EGLSurface m_eglSurface;
118 EGLConfig m_eglConfig;
119 EGLContext m_eglContext;
120 glw::Functions m_gl;
121
122 GLES2Renderer* m_gles2Renderer;
123 ReferenceRenderer* m_refRenderer;
124
125};
126
127struct ColoredRect
128{
129public:
130 ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_);
Mika Isojärvi78d63422016-02-19 15:04:14 -0800131 IVec2 bottomLeft;
Hengyuan Hudb757542015-06-18 13:26:57 -0700132 IVec2 topRight;
133 Color color;
134};
135
136ColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_)
137 : bottomLeft(bottomLeft_)
138 , topRight (topRight_)
139 , color (color_)
140{
141}
142
143struct DrawCommand
144{
145 DrawCommand (const BufferAgeTest::DrawType drawType_, const ColoredRect& rect_);
146 BufferAgeTest::DrawType drawType;
147 ColoredRect rect;
148};
149
150DrawCommand::DrawCommand (const BufferAgeTest::DrawType drawType_, const ColoredRect& rect_)
151 : drawType(drawType_)
152 , rect (rect_)
153{
154}
155
156struct Frame
157{
158 Frame (int width_, int height_);
159 int width;
160 int height;
161 vector<DrawCommand> draws;
162};
163
164Frame::Frame (int width_, int height_)
165 : width(width_)
166 , height(height_)
167{
168}
169
170
171// (x1,y1) lie in the lower-left quadrant while (x2,y2) lie in the upper-right.
172// the coords are multiplied by 4 to amplify the minimial difference between coords to 4 (if not zero)
173// to avoid the situation where two edges are too close to each other which makes the rounding error
174// intoleratable by compareToReference()
175void generateRandomFrame (Frame* dst, const vector<BufferAgeTest::DrawType>& drawTypes, de::Random& rnd)
176{
177 for (size_t ndx = 0; ndx < drawTypes.size(); ndx++)
178 {
179 const int x1 = rnd.getInt(0, (dst->width-1)/8) * 4;
180 const int y1 = rnd.getInt(0, (dst->height-1)/8) * 4;
181 const int x2 = rnd.getInt((dst->width-1)/8, (dst->width-1)/4) * 4;
182 const int y2 = rnd.getInt((dst->height-1)/8, (dst->height-1)/4) * 4;
183 const GLubyte r = rnd.getUint8();
184 const GLubyte g = rnd.getUint8();
185 const GLubyte b = rnd.getUint8();
186 const ColoredRect coloredRect (IVec2(x1, y1), IVec2(x2, y2), Color(r, g, b));
187 const DrawCommand drawCommand (drawTypes[ndx], coloredRect);
188 (*dst).draws.push_back(drawCommand);
189 }
190}
191
192typedef vector<Frame> FrameSequence;
193
194//helper function declaration
195EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveColorBuffer);
196void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor);
197void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor);
198void readPixels (const glw::Functions& gl, tcu::Surface* screen);
199float windowToDeviceCoordinates (int x, int length);
200bool compareToReference (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum);
201vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx);
202
203class GLES2Renderer
204{
205public:
206 GLES2Renderer (const glw::Functions& gl);
207 ~GLES2Renderer (void);
208 void render (int width, int height, const Frame& frame) const;
209
210private:
211 GLES2Renderer (const GLES2Renderer&);
212 GLES2Renderer& operator= (const GLES2Renderer&);
213
214 const glw::Functions& m_gl;
215 glu::ShaderProgram m_glProgram;
216 glw::GLuint m_coordLoc;
217 glw::GLuint m_colorLoc;
218};
219
220// generate sources for vertex and fragment buffer
221glu::ProgramSources getSources (void)
222{
223 const char* const vertexShaderSource =
224 "attribute mediump vec4 a_pos;\n"
225 "attribute mediump vec4 a_color;\n"
226 "varying mediump vec4 v_color;\n"
227 "void main(void)\n"
228 "{\n"
229 "\tv_color = a_color;\n"
230 "\tgl_Position = a_pos;\n"
231 "}";
232
233 const char* const fragmentShaderSource =
234 "varying mediump vec4 v_color;\n"
235 "void main(void)\n"
236 "{\n"
237 "\tgl_FragColor = v_color;\n"
238 "}";
239
240 return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource);
241}
242
243GLES2Renderer::GLES2Renderer (const glw::Functions& gl)
244 : m_gl (gl)
245 , m_glProgram (gl, getSources())
246 , m_coordLoc ((glw::GLuint)-1)
247 , m_colorLoc ((glw::GLuint)-1)
248{
249 m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color");
250 m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos");
251 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations");
252}
253
254GLES2Renderer::~GLES2Renderer (void)
255{
256}
257
258void GLES2Renderer::render (int width, int height, const Frame& frame) const
259{
260 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
261 {
262 const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
263 if (frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_RENDER)
264 {
265 float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width);
266 float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height);
267 float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width);
268 float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height);
269
270 const glw::GLfloat coords[] =
271 {
272 x1, y1, 0.0f, 1.0f,
273 x1, y2, 0.0f, 1.0f,
274 x2, y2, 0.0f, 1.0f,
275
276 x2, y2, 0.0f, 1.0f,
277 x2, y1, 0.0f, 1.0f,
278 x1, y1, 0.0f, 1.0f
279 };
280
281 const glw::GLubyte colors[] =
282 {
283 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
284 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
285 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
286
287 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
288 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
289 coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
290 };
291
292 m_gl.useProgram(m_glProgram.getProgram());
293 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
294
295 m_gl.enableVertexAttribArray(m_coordLoc);
296 m_gl.enableVertexAttribArray(m_colorLoc);
297 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes");
298
299 m_gl.vertexAttribPointer(m_coordLoc, 4, GL_FLOAT, GL_FALSE, 0, coords);
300 m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
301 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers");
302
303 m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/4);
304 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed");
305
306 m_gl.disableVertexAttribArray(m_coordLoc);
307 m_gl.disableVertexAttribArray(m_colorLoc);
308 GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes");
309
310 m_gl.useProgram(0);
311 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
312 }
313 else if (frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_CLEAR)
314 {
315 m_gl.enable(GL_SCISSOR_TEST);
316 m_gl.scissor(coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(),
317 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y());
318 m_gl.clearColor(coloredRect.color.x()/255.0f, coloredRect.color.y()/255.0f, coloredRect.color.z()/255.0f, 1.0f);
319 m_gl.clear(GL_COLOR_BUFFER_BIT);
320 m_gl.disable(GL_SCISSOR_TEST);
321 }
322 else
323 DE_ASSERT(false);
324 }
325}
326
327class ReferenceRenderer
328{
329public:
Mika Isojärvi78d63422016-02-19 15:04:14 -0800330 ReferenceRenderer (void);
331 void render (tcu::Surface* target, const Frame& frame) const;
Hengyuan Hudb757542015-06-18 13:26:57 -0700332private:
333 ReferenceRenderer (const ReferenceRenderer&);
Mika Isojärvi78d63422016-02-19 15:04:14 -0800334 ReferenceRenderer& operator= (const ReferenceRenderer&);
Hengyuan Hudb757542015-06-18 13:26:57 -0700335};
336
337ReferenceRenderer::ReferenceRenderer(void)
338{
339}
340
341void ReferenceRenderer::render (tcu::Surface* target, const Frame& frame) const
342{
343 for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
344 {
345 const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
346 if (frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_RENDER || frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_CLEAR)
347 {
348 const tcu::UVec4 color(coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255);
349 tcu::clear(tcu::getSubregion(target->getAccess(), coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(),
350 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y()), color);
351 }
352 else
353 DE_ASSERT(false);
354 }
355}
356
Mika Isojärvi78d63422016-02-19 15:04:14 -0800357BufferAgeTest::BufferAgeTest (EglTestContext& eglTestCtx,
358 bool preserveColorBuffer,
359 const vector<DrawType>& oddFrameDrawType,
360 const vector<DrawType>& evenFrameDrawType,
361 ResizeType resizeType,
362 const char* name,
363 const char* description)
Hengyuan Hudb757542015-06-18 13:26:57 -0700364 : TestCase (eglTestCtx, name, description)
365 , m_seed (deStringHash(name))
366 , m_preserveColorBuffer (preserveColorBuffer)
367 , m_oddFrameDrawType (oddFrameDrawType)
368 , m_evenFrameDrawType (evenFrameDrawType)
Mika Isojärvi78d63422016-02-19 15:04:14 -0800369 , m_resizeType (resizeType)
Hengyuan Hudb757542015-06-18 13:26:57 -0700370 , m_eglDisplay (EGL_NO_DISPLAY)
371 , m_window (DE_NULL)
372 , m_eglSurface (EGL_NO_SURFACE)
373 , m_eglContext (EGL_NO_CONTEXT)
374 , m_gles2Renderer (DE_NULL)
375 , m_refRenderer (DE_NULL)
376{
377}
378
379BufferAgeTest::~BufferAgeTest (void)
380{
381 deinit();
382}
383
384void BufferAgeTest::init (void)
385{
386 const Library& egl = m_eglTestCtx.getLibrary();
387
388 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
389 m_eglConfig = getEGLConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, m_preserveColorBuffer);
390
391 if (m_eglConfig == DE_NULL)
392 TCU_THROW(NotSupportedError, "No supported config found");
393
394 //create surface and context and make them current
395 initEGLSurface(m_eglConfig);
396 initEGLContext(m_eglConfig);
397
398 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
399
400 if (eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_buffer_age") == false)
401 TCU_THROW(NotSupportedError, "EGL_EXT_buffer_age is not supported");
402
403 m_gles2Renderer = new GLES2Renderer(m_gl);
404 m_refRenderer = new ReferenceRenderer();
405}
406
407void BufferAgeTest::deinit (void)
408{
409 const Library& egl = m_eglTestCtx.getLibrary();
410
411 delete m_refRenderer;
412 m_refRenderer = DE_NULL;
413
414 delete m_gles2Renderer;
415 m_gles2Renderer = DE_NULL;
416
417 if (m_eglContext != EGL_NO_CONTEXT)
418 {
419 egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
420 egl.destroyContext(m_eglDisplay, m_eglContext);
421 m_eglContext = EGL_NO_CONTEXT;
422 }
423
424 if (m_eglSurface != EGL_NO_SURFACE)
425 {
426 egl.destroySurface(m_eglDisplay, m_eglSurface);
427 m_eglSurface = EGL_NO_SURFACE;
428 }
429
430 if (m_eglDisplay != EGL_NO_DISPLAY)
431 {
432 egl.terminate(m_eglDisplay);
433 m_eglDisplay = EGL_NO_DISPLAY;
434 }
435
436 delete m_window;
437 m_window = DE_NULL;
438}
439
440void BufferAgeTest::initEGLSurface (EGLConfig config)
441{
442 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
443 m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL,
444 eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
445 m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL);
446}
447
448void BufferAgeTest::initEGLContext (EGLConfig config)
449{
450 const Library& egl = m_eglTestCtx.getLibrary();
451 const EGLint attribList[] =
452 {
453 EGL_CONTEXT_CLIENT_VERSION, 2,
454 EGL_NONE
455 };
456
457 egl.bindAPI(EGL_OPENGL_ES_API);
458 m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList);
459 EGLU_CHECK_MSG(egl, "eglCreateContext");
460 DE_ASSERT(m_eglSurface != EGL_NO_SURFACE);
461 egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
462 EGLU_CHECK_MSG(egl, "eglMakeCurrent");
463}
464
465// return indices of frames that have been written to the given buffer
466vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx)
467{
468 DE_ASSERT(frameNdx < (int)bufferAges.size());
469 vector<int> frameOnBuffer;
470 int age = bufferAges[frameNdx];
471 while (age != 0)
472 {
473 frameNdx = frameNdx - age;
474 DE_ASSERT(frameNdx >= 0);
475 frameOnBuffer.push_back(frameNdx);
476 age = bufferAges[frameNdx];
477 }
478
479 reverse(frameOnBuffer.begin(), frameOnBuffer.end());
480 return frameOnBuffer;
481}
482
483TestCase::IterateResult BufferAgeTest::iterate (void)
484{
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
498 if (m_preserveColorBuffer)
499 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));
Hengyuan Hu265a0ca2015-07-29 12:41:13 -0700500 else
501 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
Hengyuan Hudb757542015-06-18 13:26:57 -0700502
503 for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
504 {
505 tcu::Surface currentBuffer (width, height);
506 tcu::Surface refBuffer (width, height);
507 Frame newFrame (width, height);
508 EGLint currentBufferAge = -1;
509
510 if (frameNdx % 2 == 0)
511 generateRandomFrame(&newFrame, m_evenFrameDrawType, rnd);
512 else
513 generateRandomFrame(&newFrame, m_oddFrameDrawType, rnd);
514
515 frameSequence.push_back(newFrame);
516
517 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, &currentBufferAge));
518
519 if (currentBufferAge > frameNdx || currentBufferAge < 0) // invalid buffer age
520 {
521 std::ostringstream stream;
522 stream << "Fail, the age is invalid. Age: " << currentBufferAge << ", frameNdx: " << frameNdx;
523 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
524 return STOP;
525 }
526
527 if (frameNdx > 0 && m_preserveColorBuffer && currentBufferAge != 1)
528 {
529 std::ostringstream stream;
530 stream << "Fail, EGL_BUFFER_PRESERVED is set to true, but buffer age is: " << currentBufferAge << " (should be 1)";
531 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
532 return STOP;
533 }
534
535 bufferAges.push_back(currentBufferAge);
536 DE_ASSERT((int)bufferAges.size() == frameNdx+1);
537
538 // during first half, just keep rendering without reading pixel back to mimic ordinary use case
539 if (frameNdx < numFrames/2)
540 {
541 if (currentBufferAge == 0)
542 clearColorScreen(m_gl, clearColor);
543
544 m_gles2Renderer->render(width, height, newFrame);
Mika Isojärvi78d63422016-02-19 15:04:14 -0800545
546 if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
547 {
548 if (frameNdx % 2 == 0)
549 m_window->setSurfaceSize(IVec2(width*2, height/2));
550 else
551 m_window->setSurfaceSize(IVec2(height/2, width*2));
552 }
553
Hengyuan Hudb757542015-06-18 13:26:57 -0700554 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
Mika Isojärvi78d63422016-02-19 15:04:14 -0800555
556 if (m_resizeType == RESIZETYPE_AFTER_SWAP)
557 {
558 if (frameNdx % 2 == 0)
559 m_window->setSurfaceSize(IVec2(width*2, height/2));
560 else
561 m_window->setSurfaceSize(IVec2(height/2, width*2));
562 }
563
Hengyuan Hudb757542015-06-18 13:26:57 -0700564 continue;
565 }
566
567 // do verification in the second half
568 if (currentBufferAge > 0) //buffer contain previous content, need to verify
569 {
570 const vector<int> framesOnBuffer = getFramesOnBuffer(bufferAges, frameNdx);
571 readPixels(m_gl, &currentBuffer);
572 clearColorReference(&refBuffer, clearColor);
573
574 for (vector<int>::const_iterator it = framesOnBuffer.begin(); it != framesOnBuffer.end(); it++)
575 m_refRenderer->render(&refBuffer, frameSequence[*it]);
576
577 if (compareToReference(log, refBuffer, currentBuffer, frameNdx, frameNdx-currentBufferAge) == false)
578 {
579 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, buffer content is not well preserved when age > 0");
580 return STOP;
581 }
582 }
583 else // currentBufferAge == 0, content is undefined, clear the buffer, currentBufferAge < 0 is ruled out at the beginning
584 {
585 clearColorScreen(m_gl, clearColor);
586 clearColorReference(&refBuffer, clearColor);
587 }
588
589 m_gles2Renderer->render(width, height, newFrame);
590 m_refRenderer->render(&refBuffer, newFrame);
591
592 readPixels(m_gl, &currentBuffer);
593
594 if (compareToReference(log, refBuffer, currentBuffer, frameNdx, frameNdx) == false)
595 {
596 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, render result is wrong");
597 return STOP;
598 }
599
Mika Isojärvi78d63422016-02-19 15:04:14 -0800600 if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
601 {
602 if (frameNdx % 2 == 0)
603 m_window->setSurfaceSize(IVec2(width*2, height/2));
604 else
605 m_window->setSurfaceSize(IVec2(height/2, width*2));
606 }
607
Hengyuan Hudb757542015-06-18 13:26:57 -0700608 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
Mika Isojärvi78d63422016-02-19 15:04:14 -0800609
610 if (m_resizeType == RESIZETYPE_AFTER_SWAP)
611 {
612 if (frameNdx % 2 == 0)
613 m_window->setSurfaceSize(IVec2(width*2, height/2));
614 else
615 m_window->setSurfaceSize(IVec2(height/2, width*2));
616 }
Hengyuan Hudb757542015-06-18 13:26:57 -0700617 }
618
619 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
620 return STOP;
621}
622
623string generateDrawTypeName (const vector<BufferAgeTest::DrawType>& drawTypes)
624{
625 std::ostringstream stream;
626 if (drawTypes.size() == 0)
627 return string("_none");
628
629 for (size_t ndx = 0; ndx < drawTypes.size(); ndx++)
630 {
631 if (drawTypes[ndx] == BufferAgeTest::DRAWTYPE_GLES2_RENDER)
632 stream << "_render";
633 else if (drawTypes[ndx] == BufferAgeTest::DRAWTYPE_GLES2_CLEAR)
634 stream << "_clear";
635 else
636 DE_ASSERT(false);
637 }
638 return stream.str();
639}
640
641string generateTestName (const vector<BufferAgeTest::DrawType>& oddFrameDrawType, const vector<BufferAgeTest::DrawType>& evenFrameDrawType)
642{
643 return "odd" + generateDrawTypeName(oddFrameDrawType) + "_even" + generateDrawTypeName(evenFrameDrawType);
644}
645
Mika Isojärvi78d63422016-02-19 15:04:14 -0800646string generateResizeGroupName (BufferAgeTest::ResizeType resizeType)
647{
648 switch (resizeType)
649 {
650 case BufferAgeTest::RESIZETYPE_NONE:
651 return "no_resize";
652
653 case BufferAgeTest::RESIZETYPE_AFTER_SWAP:
654 return "resize_after_swap";
655
656 case BufferAgeTest::RESIZETYPE_BEFORE_SWAP:
657 return "resize_before_swap";
658
659 default:
660 DE_FATAL("Unknown resize type");
661 return "";
662 }
663}
664
Hengyuan Hudb757542015-06-18 13:26:57 -0700665bool isWindow (const eglu::CandidateConfig& c)
666{
667 return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
668}
669
670bool isES2Renderable (const eglu::CandidateConfig& c)
671{
672 return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
673}
674
675bool hasPreserveSwap (const eglu::CandidateConfig& c)
676{
677 return (c.surfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
678}
679
680EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveColorBuffer)
681{
682 eglu::FilterList filters;
683 filters << isWindow << isES2Renderable;
684 if (preserveColorBuffer)
685 filters << hasPreserveSwap;
686 return eglu::chooseSingleConfig(egl, eglDisplay, filters);
687}
688
689void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor)
690{
691 gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
692 gl.clear(GL_COLOR_BUFFER_BIT);
693}
694
695void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor)
696{
697 tcu::clear(ref->getAccess(), clearColor);
698}
699
700void readPixels (const glw::Functions& gl, tcu::Surface* screen)
701{
702 gl.readPixels(0, 0, screen->getWidth(), screen->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
703}
704
705float windowToDeviceCoordinates (int x, int length)
706{
707 return (2.0f * float(x) / float(length)) - 1.0f;
708}
709
710bool compareToReference (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum)
711{
712 std::ostringstream stream;
713 stream << "FrameNdx = " << frameNdx << ", compare current buffer (numbered: " << bufferNum << ") to reference";
714 return tcu::intThresholdPositionDeviationCompare(log, "buffer age test", stream.str().c_str(), reference.getAccess(), buffer.getAccess(),
715 tcu::UVec4(8, 8, 8, 0), tcu::IVec3(2,2,0), true, tcu::COMPARE_LOG_RESULT);
716}
717
718} // anonymous
719
720BufferAgeTests::BufferAgeTests (EglTestContext& eglTestCtx)
721 : TestCaseGroup(eglTestCtx, "buffer_age", "Color buffer age tests")
722{
723}
724
725void BufferAgeTests::init (void)
726{
Mika Isojärvi78d63422016-02-19 15:04:14 -0800727 const BufferAgeTest::DrawType clearRender[] =
Hengyuan Hudb757542015-06-18 13:26:57 -0700728 {
729 BufferAgeTest::DRAWTYPE_GLES2_CLEAR,
730 BufferAgeTest::DRAWTYPE_GLES2_RENDER
731 };
732
Mika Isojärvi78d63422016-02-19 15:04:14 -0800733 const BufferAgeTest::DrawType renderClear[] =
Hengyuan Hudb757542015-06-18 13:26:57 -0700734 {
735 BufferAgeTest::DRAWTYPE_GLES2_RENDER,
736 BufferAgeTest::DRAWTYPE_GLES2_CLEAR
737 };
738
Mika Isojärvi78d63422016-02-19 15:04:14 -0800739 const BufferAgeTest::ResizeType resizeTypes[] =
740 {
741 BufferAgeTest::RESIZETYPE_NONE,
742 BufferAgeTest::RESIZETYPE_BEFORE_SWAP,
743 BufferAgeTest::RESIZETYPE_AFTER_SWAP
744 };
745
Hengyuan Hudb757542015-06-18 13:26:57 -0700746 vector< vector<BufferAgeTest::DrawType> > frameDrawTypes;
747 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> ());
748 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (1, BufferAgeTest::DRAWTYPE_GLES2_CLEAR));
749 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (1, BufferAgeTest::DRAWTYPE_GLES2_RENDER));
750 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (2, BufferAgeTest::DRAWTYPE_GLES2_CLEAR));
751 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (2, BufferAgeTest::DRAWTYPE_GLES2_RENDER));
752 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender)));
753 frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear)));
754
755 for (int preserveNdx = 0; preserveNdx < 2; preserveNdx++)
756 {
Mika Isojärvi78d63422016-02-19 15:04:14 -0800757 const bool preserve = (preserveNdx == 0);
758 TestCaseGroup* const preserveGroup = new TestCaseGroup(m_eglTestCtx, (preserve ? "preserve" : "no_preserve"), "");
Hengyuan Hudb757542015-06-18 13:26:57 -0700759
Mika Isojärvi78d63422016-02-19 15:04:14 -0800760 for (size_t resizeTypeNdx = 0; resizeTypeNdx < DE_LENGTH_OF_ARRAY(resizeTypes); resizeTypeNdx++)
Hengyuan Hudb757542015-06-18 13:26:57 -0700761 {
Mika Isojärvi78d63422016-02-19 15:04:14 -0800762 const BufferAgeTest::ResizeType resizeType = resizeTypes[resizeTypeNdx];
763 TestCaseGroup* const resizeGroup = new TestCaseGroup(m_eglTestCtx, generateResizeGroupName(resizeType).c_str(), "");
Hengyuan Hudb757542015-06-18 13:26:57 -0700764
Mika Isojärvi78d63422016-02-19 15:04:14 -0800765 for (size_t evenNdx = 0; evenNdx < frameDrawTypes.size(); evenNdx++)
Hengyuan Hudb757542015-06-18 13:26:57 -0700766 {
Mika Isojärvi78d63422016-02-19 15:04:14 -0800767 const vector<BufferAgeTest::DrawType>& evenFrameDrawType = frameDrawTypes[evenNdx];
768
769 for (size_t oddNdx = evenNdx; oddNdx < frameDrawTypes.size(); oddNdx++)
770 {
771 const vector<BufferAgeTest::DrawType>& oddFrameDrawType = frameDrawTypes[oddNdx];
772 const std::string name = generateTestName(oddFrameDrawType, evenFrameDrawType);
773 resizeGroup->addChild(new BufferAgeTest(m_eglTestCtx, preserve, oddFrameDrawType, evenFrameDrawType, BufferAgeTest::RESIZETYPE_NONE, name.c_str(), ""));
774 }
Hengyuan Hudb757542015-06-18 13:26:57 -0700775 }
Mika Isojärvi78d63422016-02-19 15:04:14 -0800776
777 preserveGroup->addChild(resizeGroup);
Hengyuan Hudb757542015-06-18 13:26:57 -0700778 }
779 addChild(preserveGroup);
780 }
781}
782
783} // egl
784} // deqp