1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL Module
3 * ---------------------------------------
5 * Copyright 2016 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_mutable_render_buffer
22 *//*--------------------------------------------------------------------*/
24 #include "teglMutableRenderBufferTests.hpp"
26 #include "egluUtil.hpp"
28 #include "eglwLibrary.hpp"
29 #include "eglwEnums.hpp"
31 #include "gluDefs.hpp"
32 #include "gluRenderContext.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
48 class MutableRenderBufferTest : public TestCase
51 MutableRenderBufferTest (EglTestContext& eglTestCtx,
53 const char* description,
54 bool enableConfigBit);
55 ~MutableRenderBufferTest (void);
58 IterateResult iterate (void);
61 deUint32 drawAndSwap (const Library& egl,
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;
73 MutableRenderBufferTest::MutableRenderBufferTest (EglTestContext& eglTestCtx,
74 const char* name, const char* description,
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)
82 , m_eglContext (EGL_NO_CONTEXT)
86 MutableRenderBufferTest::~MutableRenderBufferTest (void)
91 void MutableRenderBufferTest::init (void)
93 const Library& egl = m_eglTestCtx.getLibrary();
96 m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
98 if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_KHR_mutable_render_buffer"))
100 TCU_THROW(NotSupportedError, "EGL_KHR_mutable_render_buffer is not supported");
103 // get mutable render buffer config
104 const EGLint attribs[] =
110 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR,
111 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
114 const EGLint attribsNoBit[] =
120 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
121 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
125 if (m_enableConfigBit)
127 m_eglConfig = eglu::chooseSingleConfig(egl, m_eglDisplay, attribs);
131 const vector<EGLConfig> configs = eglu::chooseConfigs(egl, m_eglDisplay, attribsNoBit);
133 for (vector<EGLConfig>::const_iterator config = configs.begin(); config != configs.end(); ++config)
135 EGLint surfaceType = -1;
136 EGLU_CHECK_CALL(egl, getConfigAttrib(m_eglDisplay, *config, EGL_SURFACE_TYPE, &surfaceType));
138 if (!(surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR))
140 m_eglConfig = *config;
145 if (m_eglConfig == DE_NULL)
146 TCU_THROW(NotSupportedError, "No config without support for mutable_render_buffer found");
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);
155 // create context and make current
156 const EGLint contextAttribList[] =
158 EGL_CONTEXT_CLIENT_VERSION, 2,
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");
169 m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
172 void MutableRenderBufferTest::deinit (void)
174 const Library& egl = m_eglTestCtx.getLibrary();
176 if (m_eglContext != EGL_NO_CONTEXT)
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;
183 if (m_eglSurface != EGL_NO_SURFACE)
185 egl.destroySurface(m_eglDisplay, m_eglSurface);
186 m_eglSurface = EGL_NO_SURFACE;
189 if (m_eglDisplay != EGL_NO_DISPLAY)
191 egl.terminate(m_eglDisplay);
192 m_eglDisplay = EGL_NO_DISPLAY;
195 if (m_window != DE_NULL)
202 deUint32 MutableRenderBufferTest::drawAndSwap (const Library& egl, deUint32 color, bool flush)
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);
213 EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
215 return (color | color << 8 | color << 16 | color << 24);
218 TestCase::IterateResult MutableRenderBufferTest::iterate (void)
220 const Library& egl = m_eglTestCtx.getLibrary();
224 // run a few back-buffered frames even if we can't verify their contents
225 for (; frameNumber < 5; frameNumber++)
227 drawAndSwap(egl, frameNumber, false);
230 // switch to single-buffer rendering
231 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
233 // Use eglSwapBuffers for the first frame
234 drawAndSwap(egl, frameNumber, false);
237 // test a few single-buffered frames
238 for (; frameNumber < 10; frameNumber++)
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);
244 // when single buffered, front-buffer == back-buffer
245 if (backBufferPixel != frontBufferPixel)
247 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface isn't single-buffered");
252 // switch back to back-buffer rendering
253 EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
255 // run a few back-buffered frames even if we can't verify their contents
256 for (; frameNumber < 14; frameNumber++)
258 drawAndSwap(egl, frameNumber, false);
261 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
265 class MutableRenderBufferQueryTest : public MutableRenderBufferTest
268 MutableRenderBufferQueryTest (EglTestContext& eglTestCtx,
270 const char* description);
271 ~MutableRenderBufferQueryTest (void);
272 IterateResult iterate (void);
275 MutableRenderBufferQueryTest::MutableRenderBufferQueryTest (EglTestContext& eglTestCtx,
276 const char* name, const char* description)
277 : MutableRenderBufferTest (eglTestCtx, name, description, true)
281 MutableRenderBufferQueryTest::~MutableRenderBufferQueryTest (void)
286 TestCase::IterateResult MutableRenderBufferQueryTest::iterate (void)
288 const Library& egl = m_eglTestCtx.getLibrary();
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)
295 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering");
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)
304 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch to single-buffer rendering");
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)
313 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch back to back-buffer rendering");
316 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
320 class MutableRenderBufferQueryNegativeTest : public MutableRenderBufferTest
323 MutableRenderBufferQueryNegativeTest (EglTestContext& eglTestCtx,
325 const char* description);
326 ~MutableRenderBufferQueryNegativeTest (void);
327 IterateResult iterate (void);
330 MutableRenderBufferQueryNegativeTest::MutableRenderBufferQueryNegativeTest (EglTestContext& eglTestCtx,
331 const char* name, const char* description)
332 : MutableRenderBufferTest (eglTestCtx, name, description, false)
336 MutableRenderBufferQueryNegativeTest::~MutableRenderBufferQueryNegativeTest (void)
341 TestCase::IterateResult MutableRenderBufferQueryNegativeTest::iterate (void)
343 const Library& egl = m_eglTestCtx.getLibrary();
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)
350 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering");
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)
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");
363 if (err != EGL_BAD_MATCH)
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");
370 EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
371 if (curRenderBuffer != EGL_BACK_BUFFER)
373 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't stay in back-buffered rendering after error");
377 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
383 MutableRenderBufferTests::MutableRenderBufferTests (EglTestContext& eglTestCtx)
384 : TestCaseGroup(eglTestCtx, "mutable_render_buffer", "Mutable render buffer tests")
388 void MutableRenderBufferTests::init (void)
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));