Add tests for EGL_KHR_mutable_render_buffer
authorPablo Ceballos <pceballos@google.com>
Wed, 13 Apr 2016 04:07:09 +0000 (21:07 -0700)
committerPablo Ceballos <pceballos@google.com>
Fri, 13 May 2016 23:37:51 +0000 (16:37 -0700)
Change-Id: Idf4201dfdbb364736bc4b50ae3c61a98cb03fda5

Android.mk
android/cts/master/src/egl-new-tests.txt
modules/egl/CMakeLists.txt
modules/egl/teglMutableRenderBufferTests.cpp [new file with mode: 0644]
modules/egl/teglMutableRenderBufferTests.hpp [new file with mode: 0644]
modules/egl/teglTestPackage.cpp

index 4e7765c..ea0e7db 100644 (file)
@@ -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 \
index 51cef91..6afa07c 100644 (file)
@@ -1,2 +1,3 @@
 # EGL thread clean up tests
 dEQP-EGL.functional.thread_cleanup.*
+dEQP-EGL.functional.mutable_render_buffer.*
index 98834e2..52e9fd9 100644 (file)
@@ -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 (file)
index 0000000..2fd036b
--- /dev/null
@@ -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 (file)
index 0000000..611673a
--- /dev/null
@@ -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
index d64ec87..443fad6 100644 (file)
@@ -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));
        }
 };