From 12963a9a9169a95da712837912cb780231d0f287 Mon Sep 17 00:00:00 2001 From: Pablo Ceballos Date: Tue, 12 Apr 2016 21:07:09 -0700 Subject: [PATCH] Add tests for EGL_KHR_mutable_render_buffer Change-Id: Idf4201dfdbb364736bc4b50ae3c61a98cb03fda5 --- Android.mk | 1 + android/cts/master/src/egl-new-tests.txt | 1 + modules/egl/CMakeLists.txt | 2 + modules/egl/teglMutableRenderBufferTests.cpp | 390 +++++++++++++++++++++++++++ modules/egl/teglMutableRenderBufferTests.hpp | 48 ++++ modules/egl/teglTestPackage.cpp | 2 + 6 files changed, 444 insertions(+) create mode 100644 modules/egl/teglMutableRenderBufferTests.cpp create mode 100644 modules/egl/teglMutableRenderBufferTests.hpp diff --git a/Android.mk b/Android.mk index 4e7765c..ea0e7db 100644 --- a/Android.mk +++ b/Android.mk @@ -273,6 +273,7 @@ LOCAL_SRC_FILES := \ modules/egl/teglMakeCurrentPerfTests.cpp \ modules/egl/teglMemoryStressTests.cpp \ modules/egl/teglMultiThreadTests.cpp \ + modules/egl/teglMutableRenderBufferTests.cpp \ modules/egl/teglNativeColorMappingTests.cpp \ modules/egl/teglNativeCoordMappingTests.cpp \ modules/egl/teglNegativeApiTests.cpp \ diff --git a/android/cts/master/src/egl-new-tests.txt b/android/cts/master/src/egl-new-tests.txt index 51cef91..6afa07c 100644 --- a/android/cts/master/src/egl-new-tests.txt +++ b/android/cts/master/src/egl-new-tests.txt @@ -1,2 +1,3 @@ # EGL thread clean up tests dEQP-EGL.functional.thread_cleanup.* +dEQP-EGL.functional.mutable_render_buffer.* diff --git a/modules/egl/CMakeLists.txt b/modules/egl/CMakeLists.txt index 98834e2..52e9fd9 100644 --- a/modules/egl/CMakeLists.txt +++ b/modules/egl/CMakeLists.txt @@ -39,6 +39,8 @@ set(DEQP_EGL_SRCS teglImageTests.hpp teglInfoTests.cpp teglInfoTests.hpp + teglMutableRenderBufferTests.cpp + teglMutableRenderBufferTests.hpp teglNegativeApiTests.cpp teglNegativeApiTests.hpp teglPartialUpdateTests.cpp diff --git a/modules/egl/teglMutableRenderBufferTests.cpp b/modules/egl/teglMutableRenderBufferTests.cpp new file mode 100644 index 0000000..2fd036b --- /dev/null +++ b/modules/egl/teglMutableRenderBufferTests.cpp @@ -0,0 +1,390 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program EGL Module + * --------------------------------------- + * + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *//*! + * \file + * \brief Test KHR_mutable_render_buffer + *//*--------------------------------------------------------------------*/ + +#include "teglMutableRenderBufferTests.hpp" + +#include "egluUtil.hpp" + +#include "eglwLibrary.hpp" +#include "eglwEnums.hpp" + +#include "gluDefs.hpp" +#include "gluRenderContext.hpp" + +#include "glwFunctions.hpp" +#include "glwEnums.hpp" + +using namespace eglw; + +namespace deqp +{ +namespace egl +{ +namespace +{ + +class MutableRenderBufferTest : public TestCase +{ +public: + MutableRenderBufferTest (EglTestContext& eglTestCtx, + const char* name, + const char* description, + bool enableConfigBit); + ~MutableRenderBufferTest (void); + void init (void); + void deinit (void); + IterateResult iterate (void); + +protected: + deUint32 drawAndSwap (const Library& egl, + deUint32 color, + bool flush); + bool m_enableConfigBit; + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + EGLConfig m_eglConfig; + eglu::NativeWindow* m_window; + EGLContext m_eglContext; + glw::Functions m_gl; +}; + +MutableRenderBufferTest::MutableRenderBufferTest (EglTestContext& eglTestCtx, + const char* name, const char* description, + bool enableConfigBit) + : TestCase (eglTestCtx, name, description) + , m_enableConfigBit (enableConfigBit) + , m_eglDisplay (EGL_NO_DISPLAY) + , m_eglSurface (EGL_NO_SURFACE) + , m_eglConfig (DE_NULL) + , m_window (DE_NULL) + , m_eglContext (EGL_NO_CONTEXT) +{ +} + +MutableRenderBufferTest::~MutableRenderBufferTest (void) +{ + deinit(); +} + +void MutableRenderBufferTest::init (void) +{ + const Library& egl = m_eglTestCtx.getLibrary(); + + // create display + m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); + + if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_KHR_mutable_render_buffer")) + { + TCU_THROW(NotSupportedError, "EGL_KHR_mutable_render_buffer is not supported"); + } + + // get mutable render buffer config + const EGLint attribs[] = + { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + const EGLint attribsNoBit[] = + { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + m_eglConfig = m_enableConfigBit ? + eglu::chooseSingleConfig(egl, m_eglDisplay, attribs) : + eglu::chooseSingleConfig(egl, m_eglDisplay, attribsNoBit); + + // create surface + const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine()); + m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL, + eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))); + m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL); + + // create context and make current + const EGLint contextAttribList[] = + { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + egl.bindAPI(EGL_OPENGL_ES_API); + m_eglContext = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttribList); + EGLU_CHECK_MSG(egl, "eglCreateContext"); + TCU_CHECK(m_eglSurface != EGL_NO_SURFACE); + egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + EGLU_CHECK_MSG(egl, "eglMakeCurrent"); + + m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0)); +} + +void MutableRenderBufferTest::deinit (void) +{ + const Library& egl = m_eglTestCtx.getLibrary(); + + if (m_eglContext != EGL_NO_CONTEXT) + { + egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + egl.destroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; + } + + if (m_eglSurface != EGL_NO_SURFACE) + { + egl.destroySurface(m_eglDisplay, m_eglSurface); + m_eglSurface = EGL_NO_SURFACE; + } + + if (m_eglDisplay != EGL_NO_DISPLAY) + { + egl.terminate(m_eglDisplay); + m_eglDisplay = EGL_NO_DISPLAY; + } + + if (m_window != DE_NULL) + { + delete m_window; + m_window = DE_NULL; + } +} + +deUint32 MutableRenderBufferTest::drawAndSwap (const Library& egl, deUint32 color, bool flush) +{ + DE_ASSERT(color < 256); + m_gl.clearColor(color/255.f, color/255.f, color/255.f, color/255.f); + m_gl.clear(GL_COLOR_BUFFER_BIT); + if (flush) + { + m_gl.flush(); + } + else + { + EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface)); + } + return (color | color << 8 | color << 16 | color << 24); +} + +TestCase::IterateResult MutableRenderBufferTest::iterate (void) +{ + const Library& egl = m_eglTestCtx.getLibrary(); + + int frameNumber = 1; + + // test a few back-buffered frames + for(; frameNumber < 5; frameNumber++) + { + deUint32 backBufferPixel = 0xFFFFFFFF; + deUint32 frontBufferPixel = drawAndSwap(egl, frameNumber, false); + m_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &backBufferPixel); + + // the front-buffer and the back-buffer should have different contents + if (backBufferPixel == frontBufferPixel) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface isn't being back-buffered"); + return STOP; + } + } + + // switch to single-buffer rendering + EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + + // test a few single-buffered frames + for (; frameNumber < 10; frameNumber++) + { + deUint32 backBufferPixel = 0xFFFFFFFF; + deUint32 frontBufferPixel = drawAndSwap(egl, frameNumber, frameNumber > 5); // only the first frame should eglSwapBuffers + m_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &backBufferPixel); + + // when single buffered, front-buffer == back-buffer + if (backBufferPixel != frontBufferPixel) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch to being single-buffered"); + return STOP; + } + } + + // switch back to back-buffer rendering + EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER)); + + // test a few back-buffered frames + for (; frameNumber < 15; frameNumber++) + { + deUint32 backBufferPixel = 0xFFFFFFFF; + deUint32 frontBufferPixel = drawAndSwap(egl, frameNumber, false); + m_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &backBufferPixel); + + // the front-buffer and the back-buffer should have different contents + if (backBufferPixel == frontBufferPixel) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch back to being back-buffered"); + return STOP; + } + } + + m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); + return STOP; +} + +class MutableRenderBufferQueryTest : public MutableRenderBufferTest +{ +public: + MutableRenderBufferQueryTest (EglTestContext& eglTestCtx, + const char* name, + const char* description); + ~MutableRenderBufferQueryTest (void); + IterateResult iterate (void); +}; + +MutableRenderBufferQueryTest::MutableRenderBufferQueryTest (EglTestContext& eglTestCtx, + const char* name, const char* description) + : MutableRenderBufferTest (eglTestCtx, name, description, true) +{ +} + +MutableRenderBufferQueryTest::~MutableRenderBufferQueryTest (void) +{ + deinit(); +} + +TestCase::IterateResult MutableRenderBufferQueryTest::iterate (void) +{ + const Library& egl = m_eglTestCtx.getLibrary(); + + // check that by default the query returns back buffered + EGLint curRenderBuffer = -1; + EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer)); + if (curRenderBuffer != EGL_BACK_BUFFER) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering"); + return STOP; + } + + // switch to single-buffer rendering and check that the query output changed + EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER)); + EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer)); + if (curRenderBuffer != EGL_SINGLE_BUFFER) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch to single-buffer rendering"); + return STOP; + } + + // switch back to back-buffer rendering and check the query again + EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER)); + EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer)); + if (curRenderBuffer != EGL_BACK_BUFFER) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch back to back-buffer rendering"); + return STOP; + } + m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); + return STOP; +} + +class MutableRenderBufferQueryNegativeTest : public MutableRenderBufferTest +{ +public: + MutableRenderBufferQueryNegativeTest (EglTestContext& eglTestCtx, + const char* name, + const char* description); + ~MutableRenderBufferQueryNegativeTest (void); + IterateResult iterate (void); +}; + +MutableRenderBufferQueryNegativeTest::MutableRenderBufferQueryNegativeTest (EglTestContext& eglTestCtx, + const char* name, const char* description) + : MutableRenderBufferTest (eglTestCtx, name, description, false) +{ +} + +MutableRenderBufferQueryNegativeTest::~MutableRenderBufferQueryNegativeTest (void) +{ + deinit(); +} + +TestCase::IterateResult MutableRenderBufferQueryNegativeTest::iterate (void) +{ + const Library& egl = m_eglTestCtx.getLibrary(); + + // check that by default the query returns back buffered + EGLint curRenderBuffer = -1; + EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer)); + if (curRenderBuffer != EGL_BACK_BUFFER) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering"); + return STOP; + } + + // check that trying to switch to single-buffer rendering fails when the config bit is not set + EGLBoolean ret = egl.surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); + EGLint err = egl.getError(); + if (ret != EGL_FALSE) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, + "eglSurfaceAttrib didn't return false when trying to enable single-buffering on a context without the mutable render buffer bit set"); + return STOP; + } + if (err != EGL_BAD_MATCH) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, + "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"); + return STOP; + } + + EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer)); + if (curRenderBuffer != EGL_BACK_BUFFER) + { + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't stay in back-buffered rendering after error"); + return STOP; + } + + m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); + return STOP; +} + +} // anonymous + +MutableRenderBufferTests::MutableRenderBufferTests (EglTestContext& eglTestCtx) + : TestCaseGroup(eglTestCtx, "mutable_render_buffer", "Mutable render buffer tests") +{ +} + +void MutableRenderBufferTests::init (void) +{ + addChild(new MutableRenderBufferQueryTest(m_eglTestCtx, "querySurface", + "Tests if querySurface returns the correct value after surfaceAttrib is called")); + addChild(new MutableRenderBufferQueryNegativeTest(m_eglTestCtx, "negativeConfigBit", + "Tests trying to enable single-buffering on a context without the mutable render buffer bit set")); + addChild(new MutableRenderBufferTest(m_eglTestCtx, "basic", + "Tests enabling/disabling single-buffer rendering and checks the buffering behavior", true)); +} + +} // egl +} // deqp diff --git a/modules/egl/teglMutableRenderBufferTests.hpp b/modules/egl/teglMutableRenderBufferTests.hpp new file mode 100644 index 0000000..611673a --- /dev/null +++ b/modules/egl/teglMutableRenderBufferTests.hpp @@ -0,0 +1,48 @@ +#ifndef _TEGLMUTABLERENDERBUFFERTESTS_HPP +#define _TEGLMUTABLERENDERBUFFERTESTS_HPP +/*------------------------------------------------------------------------- + * drawElements Quality Program EGL Module + * --------------------------------------- + * + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *//*! + * \file + * \brief Test KHR_mutable_render_buffer + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "teglTestCase.hpp" + +namespace deqp +{ +namespace egl +{ + +class MutableRenderBufferTests : public TestCaseGroup +{ +public: + MutableRenderBufferTests (EglTestContext& eglTestCtx); + void init (void); + +private: + MutableRenderBufferTests (const MutableRenderBufferTests&); + MutableRenderBufferTests& operator= (const MutableRenderBufferTests&); +}; + +} // egl +} // deqp + +#endif // _TEGLMUTABLERENDERBUFFERTESTS_HPP diff --git a/modules/egl/teglTestPackage.cpp b/modules/egl/teglTestPackage.cpp index d64ec87..443fad6 100644 --- a/modules/egl/teglTestPackage.cpp +++ b/modules/egl/teglTestPackage.cpp @@ -62,6 +62,7 @@ #include "teglSwapBuffersWithDamageTests.hpp" #include "teglMultiContextTests.hpp" #include "teglThreadCleanUpTests.hpp" +#include "teglMutableRenderBufferTests.hpp" namespace deqp { @@ -136,6 +137,7 @@ public: addChild(new SwapBuffersWithDamageTests (m_eglTestCtx)); addChild(createMultiContextTests (m_eglTestCtx)); addChild(createThreadCleanUpTest (m_eglTestCtx)); + addChild(new MutableRenderBufferTests (m_eglTestCtx)); } }; -- 2.7.4