eglGetFrameTimestamps: Consider timestamps of 0 as invalid.
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglMutableRenderBufferTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2016 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_mutable_render_buffer
22  *//*--------------------------------------------------------------------*/
23
24 #include "teglMutableRenderBufferTests.hpp"
25
26 #include "egluUtil.hpp"
27
28 #include "eglwLibrary.hpp"
29 #include "eglwEnums.hpp"
30
31 #include "gluDefs.hpp"
32 #include "gluRenderContext.hpp"
33
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36
37 using namespace eglw;
38
39 using std::vector;
40
41 namespace deqp
42 {
43 namespace egl
44 {
45 namespace
46 {
47
48 class MutableRenderBufferTest : public TestCase
49 {
50 public:
51                                                 MutableRenderBufferTest         (EglTestContext&        eglTestCtx,
52                                                                                                          const char*            name,
53                                                                                                          const char*            description,
54                                                                                                          bool                           enableConfigBit);
55                                                 ~MutableRenderBufferTest        (void);
56         void                            init                                            (void);
57         void                            deinit                                          (void);
58         IterateResult           iterate                                         (void);
59
60 protected:
61         deUint32                        drawAndSwap                                     (const Library&         egl,
62                                                                                                          deUint32                       color,
63                                                                                                          bool                           flush);
64         bool                            m_enableConfigBit;
65         EGLDisplay                      m_eglDisplay;
66         EGLSurface                      m_eglSurface;
67         EGLConfig                       m_eglConfig;
68         eglu::NativeWindow*     m_window;
69         EGLContext                      m_eglContext;
70         glw::Functions          m_gl;
71 };
72
73 MutableRenderBufferTest::MutableRenderBufferTest (EglTestContext& eglTestCtx,
74                                                                                                   const char* name, const char* description,
75                                                                                                   bool enableConfigBit)
76         : TestCase                      (eglTestCtx, name, description)
77         , m_enableConfigBit     (enableConfigBit)
78         , m_eglDisplay          (EGL_NO_DISPLAY)
79         , m_eglSurface          (EGL_NO_SURFACE)
80         , m_eglConfig           (DE_NULL)
81         , m_window                      (DE_NULL)
82         , m_eglContext          (EGL_NO_CONTEXT)
83 {
84 }
85
86 MutableRenderBufferTest::~MutableRenderBufferTest (void)
87 {
88         deinit();
89 }
90
91 void MutableRenderBufferTest::init (void)
92 {
93         const Library&  egl     = m_eglTestCtx.getLibrary();
94
95         // create display
96         m_eglDisplay            = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
97
98         if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_KHR_mutable_render_buffer"))
99         {
100                 TCU_THROW(NotSupportedError, "EGL_KHR_mutable_render_buffer is not supported");
101         }
102
103         // get mutable render buffer config
104         const EGLint    attribs[]       =
105         {
106         EGL_RED_SIZE,                   8,
107         EGL_GREEN_SIZE,                 8,
108         EGL_BLUE_SIZE,                  8,
109                 EGL_ALPHA_SIZE,                 8,
110                 EGL_SURFACE_TYPE,               EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR,
111                 EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
112                 EGL_NONE
113         };
114         const EGLint    attribsNoBit[]  =
115         {
116         EGL_RED_SIZE,                   8,
117         EGL_GREEN_SIZE,                 8,
118         EGL_BLUE_SIZE,                  8,
119                 EGL_ALPHA_SIZE,                 8,
120                 EGL_SURFACE_TYPE,               EGL_WINDOW_BIT,
121                 EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
122                 EGL_NONE
123         };
124
125         if (m_enableConfigBit)
126         {
127                 m_eglConfig = eglu::chooseSingleConfig(egl, m_eglDisplay, attribs);
128         }
129         else
130         {
131                 const vector<EGLConfig> configs = eglu::chooseConfigs(egl, m_eglDisplay, attribsNoBit);
132
133                 for (vector<EGLConfig>::const_iterator config = configs.begin(); config != configs.end(); ++config)
134                 {
135                         EGLint surfaceType = -1;
136                         EGLU_CHECK_CALL(egl, getConfigAttrib(m_eglDisplay, *config, EGL_SURFACE_TYPE, &surfaceType));
137
138                         if (!(surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR))
139                         {
140                                 m_eglConfig = *config;
141                                 break;
142                         }
143                 }
144
145                 if (m_eglConfig == DE_NULL)
146                         TCU_THROW(NotSupportedError, "No config without support for mutable_render_buffer found");
147         }
148
149         // create surface
150         const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
151         m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL,
152                                                                         eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
153         m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL);
154
155         // create context and make current
156         const EGLint    contextAttribList[]     =
157         {
158                 EGL_CONTEXT_CLIENT_VERSION, 2,
159                 EGL_NONE
160         };
161
162         egl.bindAPI(EGL_OPENGL_ES_API);
163         m_eglContext = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttribList);
164         EGLU_CHECK_MSG(egl, "eglCreateContext");
165         TCU_CHECK(m_eglSurface != EGL_NO_SURFACE);
166         egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
167         EGLU_CHECK_MSG(egl, "eglMakeCurrent");
168
169         m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
170 }
171
172 void MutableRenderBufferTest::deinit (void)
173 {
174         const Library&  egl     = m_eglTestCtx.getLibrary();
175
176         if (m_eglContext != EGL_NO_CONTEXT)
177         {
178                 egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
179                 egl.destroyContext(m_eglDisplay, m_eglContext);
180                 m_eglContext = EGL_NO_CONTEXT;
181         }
182
183         if (m_eglSurface != EGL_NO_SURFACE)
184         {
185                 egl.destroySurface(m_eglDisplay, m_eglSurface);
186                 m_eglSurface = EGL_NO_SURFACE;
187         }
188
189         if (m_eglDisplay != EGL_NO_DISPLAY)
190         {
191                 egl.terminate(m_eglDisplay);
192                 m_eglDisplay = EGL_NO_DISPLAY;
193         }
194
195         if (m_window != DE_NULL)
196         {
197                 delete m_window;
198                 m_window = DE_NULL;
199         }
200 }
201
202 deUint32 MutableRenderBufferTest::drawAndSwap (const Library& egl, deUint32 color, bool flush)
203 {
204         DE_ASSERT(color < 256);
205         m_gl.clearColor((float)color/255.f, (float)color/255.f, (float)color/255.f, (float)color/255.f);
206         m_gl.clear(GL_COLOR_BUFFER_BIT);
207         if (flush)
208         {
209                 m_gl.flush();
210         }
211         else
212         {
213                 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
214         }
215         return (color | color << 8 | color << 16 | color << 24);
216 }
217
218 TestCase::IterateResult MutableRenderBufferTest::iterate (void)
219 {
220         const Library&  egl     = m_eglTestCtx.getLibrary();
221
222         int frameNumber = 1;
223
224         // run a few back-buffered frames even if we can't verify their contents
225         for (; frameNumber < 5; frameNumber++)
226         {
227                 drawAndSwap(egl, frameNumber, false);
228         }
229
230         // switch to single-buffer rendering
231         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
232
233         // Use eglSwapBuffers for the first frame
234         drawAndSwap(egl, frameNumber, false);
235         frameNumber++;
236
237         // test a few single-buffered frames
238         for (; frameNumber < 10; frameNumber++)
239         {
240                 deUint32 backBufferPixel = 0xFFFFFFFF;
241                 deUint32 frontBufferPixel = drawAndSwap(egl, frameNumber, true);
242                 m_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &backBufferPixel);
243
244                 // when single buffered, front-buffer == back-buffer
245                 if (backBufferPixel != frontBufferPixel)
246                 {
247                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface isn't single-buffered");
248                         return STOP;
249                 }
250         }
251
252         // switch back to back-buffer rendering
253         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
254
255         // run a few back-buffered frames even if we can't verify their contents
256         for (; frameNumber < 14; frameNumber++)
257         {
258                 drawAndSwap(egl, frameNumber, false);
259         }
260
261         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
262         return STOP;
263 }
264
265 class MutableRenderBufferQueryTest : public MutableRenderBufferTest
266 {
267 public:
268                                                 MutableRenderBufferQueryTest    (EglTestContext&        eglTestCtx,
269                                                                                                                  const char*            name,
270                                                                                                                  const char*            description);
271                                                 ~MutableRenderBufferQueryTest   (void);
272         IterateResult           iterate                                                 (void);
273 };
274
275 MutableRenderBufferQueryTest::MutableRenderBufferQueryTest (EglTestContext& eglTestCtx,
276                                                                                                                         const char* name, const char* description)
277         : MutableRenderBufferTest       (eglTestCtx, name, description, true)
278 {
279 }
280
281 MutableRenderBufferQueryTest::~MutableRenderBufferQueryTest (void)
282 {
283         deinit();
284 }
285
286 TestCase::IterateResult MutableRenderBufferQueryTest::iterate (void)
287 {
288         const Library&  egl     = m_eglTestCtx.getLibrary();
289
290         // check that by default the query returns back buffered
291         EGLint curRenderBuffer = -1;
292         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
293         if (curRenderBuffer != EGL_BACK_BUFFER)
294         {
295                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering");
296                 return STOP;
297         }
298
299         // switch to single-buffer rendering and check that the query output changed
300         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
301         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
302         if (curRenderBuffer != EGL_SINGLE_BUFFER)
303         {
304                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch to single-buffer rendering");
305                 return STOP;
306         }
307
308         // switch back to back-buffer rendering and check the query again
309         EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
310         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
311         if (curRenderBuffer != EGL_BACK_BUFFER)
312         {
313                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch back to back-buffer rendering");
314                 return STOP;
315         }
316         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
317         return STOP;
318 }
319
320 class MutableRenderBufferQueryNegativeTest : public MutableRenderBufferTest
321 {
322 public:
323                                                 MutableRenderBufferQueryNegativeTest    (EglTestContext&        eglTestCtx,
324                                                                                                                                  const char*            name,
325                                                                                                                                  const char*            description);
326                                                 ~MutableRenderBufferQueryNegativeTest   (void);
327         IterateResult           iterate                                                                 (void);
328 };
329
330 MutableRenderBufferQueryNegativeTest::MutableRenderBufferQueryNegativeTest (EglTestContext& eglTestCtx,
331                                                                                                                         const char* name, const char* description)
332         : MutableRenderBufferTest       (eglTestCtx, name, description, false)
333 {
334 }
335
336 MutableRenderBufferQueryNegativeTest::~MutableRenderBufferQueryNegativeTest (void)
337 {
338         deinit();
339 }
340
341 TestCase::IterateResult MutableRenderBufferQueryNegativeTest::iterate (void)
342 {
343         const Library&  egl     = m_eglTestCtx.getLibrary();
344
345         // check that by default the query returns back buffered
346         EGLint curRenderBuffer = -1;
347         EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
348         if (curRenderBuffer != EGL_BACK_BUFFER)
349         {
350                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering");
351                 return STOP;
352         }
353
354         // check that trying to switch to single-buffer rendering fails when the config bit is not set
355         EGLBoolean ret = egl.surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
356         EGLint err = egl.getError();
357         if (ret != EGL_FALSE)
358         {
359                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
360                         "eglSurfaceAttrib didn't return false when trying to enable single-buffering on a context without the mutable render buffer bit set");
361                 return STOP;
362         }
363         if (err != EGL_BAD_MATCH)
364         {
365                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
366                         "eglSurfaceAttrib didn't set the EGL_BAD_MATCH error when trying to enable single-buffering on a context without the mutable render buffer bit set");
367                 return STOP;
368         }
369
370     EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
371     if (curRenderBuffer != EGL_BACK_BUFFER)
372     {
373         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't stay in back-buffered rendering after error");
374         return STOP;
375     }
376
377         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
378         return STOP;
379 }
380
381 } // anonymous
382
383 MutableRenderBufferTests::MutableRenderBufferTests (EglTestContext& eglTestCtx)
384         : TestCaseGroup(eglTestCtx, "mutable_render_buffer", "Mutable render buffer tests")
385 {
386 }
387
388 void MutableRenderBufferTests::init (void)
389 {
390         addChild(new MutableRenderBufferQueryTest(m_eglTestCtx, "querySurface",
391                 "Tests if querySurface returns the correct value after surfaceAttrib is called"));
392         addChild(new MutableRenderBufferQueryNegativeTest(m_eglTestCtx, "negativeConfigBit",
393                 "Tests trying to enable single-buffering on a context without the mutable render buffer bit set"));
394         addChild(new MutableRenderBufferTest(m_eglTestCtx, "basic",
395                 "Tests enabling/disabling single-buffer rendering and checks the buffering behavior", true));
396 }
397
398 } // egl
399 } // deqp