Add EGL thread clean up tests
authorMika Isojärvi <misojarvi@google.com>
Mon, 25 Apr 2016 23:37:55 +0000 (16:37 -0700)
committerMika Isojärvi <misojarvi@google.com>
Wed, 27 Apr 2016 18:53:26 +0000 (11:53 -0700)
Change-Id: Iccbfb32ab106eeedd9d98527188fe2f395cfec54

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

index 3e6aad1..4e7765c 100644 (file)
@@ -295,6 +295,7 @@ LOCAL_SRC_FILES := \
        modules/egl/teglTestPackageEntry.cpp \
        modules/egl/teglVGRenderUtil.cpp \
        modules/egl/teglMultiContextTests.cpp \
+       modules/egl/teglThreadCleanUpTests.cpp \
     modules/gles2/tes2CapabilityTests.cpp \
        modules/gles2/tes2Context.cpp \
        modules/gles2/tes2InfoTests.cpp \
diff --git a/android/cts/master/src/egl-new-tests.txt b/android/cts/master/src/egl-new-tests.txt
new file mode 100644 (file)
index 0000000..51cef91
--- /dev/null
@@ -0,0 +1,2 @@
+# EGL thread clean up tests
+dEQP-EGL.functional.thread_cleanup.*
index 4f80477..98834e2 100644 (file)
@@ -93,6 +93,8 @@ set(DEQP_EGL_SRCS
        teglSwapBuffersWithDamageTests.cpp
        teglMultiContextTests.hpp
        teglMultiContextTests.cpp
+       teglThreadCleanUpTests.hpp
+       teglThreadCleanUpTests.cpp
        )
 
 set(DEQP_EGL_LIBS
index 10627b8..d64ec87 100644 (file)
@@ -61,6 +61,7 @@
 #include "teglNegativePartialUpdateTests.hpp"
 #include "teglSwapBuffersWithDamageTests.hpp"
 #include "teglMultiContextTests.hpp"
+#include "teglThreadCleanUpTests.hpp"
 
 namespace deqp
 {
@@ -134,6 +135,7 @@ public:
                addChild(new NegativePartialUpdateTests (m_eglTestCtx));
                addChild(new SwapBuffersWithDamageTests (m_eglTestCtx));
                addChild(createMultiContextTests                (m_eglTestCtx));
+               addChild(createThreadCleanUpTest                (m_eglTestCtx));
        }
 };
 
diff --git a/modules/egl/teglThreadCleanUpTests.cpp b/modules/egl/teglThreadCleanUpTests.cpp
new file mode 100644 (file)
index 0000000..17b1eb2
--- /dev/null
@@ -0,0 +1,302 @@
+/*-------------------------------------------------------------------------
+ * 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 EGL thread clean up tests
+ *//*--------------------------------------------------------------------*/
+
+#include "teglThreadCleanUpTests.hpp"
+
+#include "egluUtil.hpp"
+#include "egluUnique.hpp"
+#include "egluConfigFilter.hpp"
+
+#include "eglwLibrary.hpp"
+#include "eglwEnums.hpp"
+
+#include "tcuMaybe.hpp"
+#include "tcuTestLog.hpp"
+
+#include "deThread.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+namespace
+{
+
+using namespace eglw;
+using tcu::TestLog;
+
+bool isES2Renderable (const eglu::CandidateConfig& c)
+{
+       return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
+}
+
+bool isPBuffer (const eglu::CandidateConfig& c)
+{
+       return (c.surfaceType() & EGL_PBUFFER_BIT) == EGL_PBUFFER_BIT;
+}
+
+class Thread : public de::Thread
+{
+public:
+       Thread (const Library& egl, EGLDisplay display, EGLSurface surface, EGLContext context, EGLConfig config, tcu::Maybe<eglu::Error>& error)
+               : m_egl         (egl)
+               , m_display     (display)
+               , m_surface     (surface)
+               , m_context     (context)
+               , m_config      (config)
+               , m_error       (error)
+       {
+       }
+
+       void testContext (EGLContext context)
+       {
+               if (m_surface != EGL_NO_SURFACE)
+               {
+                       EGLU_CHECK_MSG(m_egl, "eglCreateContext");
+                       m_egl.makeCurrent(m_display, m_surface, m_surface, context);
+                       EGLU_CHECK_MSG(m_egl, "eglMakeCurrent");
+               }
+               else
+               {
+                       const EGLint attribs[] =
+                       {
+                               EGL_WIDTH, 32,
+                               EGL_HEIGHT, 32,
+                               EGL_NONE
+                       };
+                       const eglu::UniqueSurface surface (m_egl, m_display, m_egl.createPbufferSurface(m_display, m_config, attribs));
+
+                       EGLU_CHECK_MSG(m_egl, "eglCreateContext");
+                       m_egl.makeCurrent(m_display, *surface, *surface, context);
+                       EGLU_CHECK_MSG(m_egl, "eglMakeCurrent");
+               }
+       }
+
+       void run (void)
+       {
+               try
+               {
+                       const EGLint    attribList[] =
+                       {
+                               EGL_CONTEXT_CLIENT_VERSION, 2,
+                               EGL_NONE
+                       };
+
+                       m_egl.bindAPI(EGL_OPENGL_ES_API);
+
+                       if (m_context == EGL_NO_CONTEXT)
+                       {
+                               const eglu::UniqueContext context (m_egl, m_display, m_egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList));
+
+                               testContext(*context);
+                       }
+                       else
+                       {
+                               testContext(m_context);
+                       }
+
+               }
+               catch (const eglu::Error& error)
+               {
+                       m_error = error;
+               }
+       }
+
+private:
+       const Library&                          m_egl;
+       const EGLDisplay                        m_display;
+       const EGLSurface                        m_surface;
+       const EGLContext                        m_context;
+       const EGLConfig                         m_config;
+       tcu::Maybe<eglu::Error>&        m_error;
+};
+
+class ThreadCleanUpTest : public TestCase
+{
+public:
+       enum ContextType
+       {
+               CONTEXTTYPE_SINGLE = 0,
+               CONTEXTTYPE_MULTI
+       };
+
+       enum SurfaceType
+       {
+               SURFACETYPE_SINGLE = 0,
+               SURFACETYPE_MULTI
+       };
+
+       static std::string testCaseName (ContextType contextType, SurfaceType surfaceType)
+       {
+               std::string name;
+
+               if (contextType == CONTEXTTYPE_SINGLE)
+                       name += "single_context_";
+               else
+                       name += "multi_context_";
+
+               if (surfaceType ==SURFACETYPE_SINGLE)
+                       name += "single_surface";
+               else
+                       name += "multi_surface";
+
+               return name;
+       }
+
+
+       ThreadCleanUpTest (EglTestContext& eglTestCtx, ContextType contextType, SurfaceType surfaceType)
+               : TestCase                      (eglTestCtx, testCaseName(contextType, surfaceType).c_str(), "Simple thread context clean up test")
+               , m_contextType         (contextType)
+               , m_surfaceType         (surfaceType)
+               , m_iterCount           (250)
+               , m_iterNdx                     (0)
+               , m_display                     (EGL_NO_DISPLAY)
+               , m_config                      (0)
+               , m_surface                     (EGL_NO_SURFACE)
+       {
+       }
+
+       ~ThreadCleanUpTest (void)
+       {
+               deinit();
+       }
+
+       void init (void)
+       {
+               const Library&  egl     = m_eglTestCtx.getLibrary();
+
+               m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
+
+               {
+                       eglu::FilterList filters;
+                       filters << isES2Renderable << isPBuffer;
+                       m_config = eglu::chooseSingleConfig(egl, m_display, filters);
+               }
+
+               if (m_contextType == CONTEXTTYPE_SINGLE)
+               {
+                       const EGLint    attribList[] =
+                       {
+                               EGL_CONTEXT_CLIENT_VERSION, 2,
+                               EGL_NONE
+                       };
+
+                       egl.bindAPI(EGL_OPENGL_ES_API);
+
+                       m_context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList);
+                       EGLU_CHECK_MSG(egl, "Failed to create context");
+               }
+
+               if (m_surfaceType == SURFACETYPE_SINGLE)
+               {
+                       const EGLint attribs[] =
+                       {
+                               EGL_WIDTH, 32,
+                               EGL_HEIGHT, 32,
+                               EGL_NONE
+                       };
+
+                       m_surface = egl.createPbufferSurface(m_display, m_config, attribs);
+                       EGLU_CHECK_MSG(egl, "Failed to create surface");
+               }
+       }
+
+       void deinit (void)
+       {
+               const Library& egl = m_eglTestCtx.getLibrary();
+
+               if (m_surface != EGL_NO_SURFACE)
+               {
+                       egl.destroySurface(m_display, m_surface);
+                       m_surface = EGL_NO_SURFACE;
+               }
+
+               if (m_context != EGL_NO_CONTEXT)
+               {
+                       egl.destroyContext(m_display, m_context);
+                       m_context = EGL_NO_CONTEXT;
+               }
+
+               if (m_display != EGL_NO_DISPLAY)
+               {
+                       egl.terminate(m_display);
+                       m_display = EGL_NO_DISPLAY;
+               }
+       }
+
+       IterateResult iterate (void)
+       {
+               if (m_iterNdx < m_iterCount)
+               {
+                       tcu::Maybe<eglu::Error> error;
+
+                       Thread thread (m_eglTestCtx.getLibrary(), m_display, m_surface, m_context, m_config, error);
+
+                       thread.start();
+                       thread.join();
+
+                       if (error)
+                       {
+                               m_testCtx.getLog() << TestLog::Message << "Failed. Got error: " << error->getMessage() << TestLog::EndMessage;
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error->getMessage());
+                               return STOP;
+                       }
+
+                       m_iterNdx++;
+                       return CONTINUE;
+               }
+               else
+               {
+                       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+                       return STOP;
+               }
+       }
+
+private:
+       const ContextType       m_contextType;
+       const SurfaceType       m_surfaceType;
+       const size_t            m_iterCount;
+       size_t                          m_iterNdx;
+       EGLDisplay                      m_display;
+       EGLConfig                       m_config;
+       EGLSurface                      m_surface;
+       EGLContext                      m_context;
+};
+
+} // anonymous
+
+TestCaseGroup* createThreadCleanUpTest (EglTestContext& eglTestCtx)
+{
+       de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "thread_cleanup", "Thread cleanup tests"));
+
+       group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_SINGLE,        ThreadCleanUpTest::SURFACETYPE_SINGLE));
+       group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_MULTI,         ThreadCleanUpTest::SURFACETYPE_SINGLE));
+
+       group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_SINGLE,        ThreadCleanUpTest::SURFACETYPE_MULTI));
+       group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_MULTI,         ThreadCleanUpTest::SURFACETYPE_MULTI));
+
+       return group.release();
+}
+
+} // egl
+} // deqp
diff --git a/modules/egl/teglThreadCleanUpTests.hpp b/modules/egl/teglThreadCleanUpTests.hpp
new file mode 100644 (file)
index 0000000..2175735
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _TEGLTHREADCLEANUPTESTS_HPP
+#define _TEGLTHREADCLEANUPTESTS_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 EGL thread clean up tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "teglTestCase.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+
+TestCaseGroup* createThreadCleanUpTest (EglTestContext& eglTestCtx);
+
+} // egl
+} // deqp
+
+#endif // _TEGLTHREADCLEANUPTESTS_HPP
index a20da2c..3fae7b5 100644 (file)
@@ -201,7 +201,8 @@ MNC_GLES31_PKG                                      = Package(module = GLES31_MODULE, configurations = [
 
 MASTER_EGL_COMMON_FILTERS              = [include("egl-master.txt"),
                                                                   exclude("egl-test-issues.txt"),
-                                                                  exclude("egl-internal-api-tests.txt")]
+                                                                  exclude("egl-internal-api-tests.txt"),
+                                                                  exclude("egl-new-tests.txt")]
 MASTER_EGL_PKG                                 = Package(module = EGL_MODULE, configurations = [
                # Master
                Configuration(name                      = "master",