Add DeqpPlatformCapabilityQueryInstrumentation.
authorJarkko Pöyry <jpoyry@google.com>
Fri, 9 Jan 2015 22:33:57 +0000 (14:33 -0800)
committerJarkko Pöyry <jpoyry@google.com>
Thu, 22 Jan 2015 19:45:11 +0000 (11:45 -0800)
- Add Instrumentation for querying if the described render target is supported.
- Move chooseConfig() from egluGLContextFactory to egluGLUtil

Change-Id: I5f55d0d7c2c1f6c70de9333e42298deb32f19953

Android.mk
CMakeLists.txt
android/package/AndroidManifest.xml
android/package/src/com/drawelements/deqp/platformutil/DeqpPlatformCapabilityQueryInstrumentation.java [new file with mode: 0644]
framework/common/tcuCommandLine.cpp
framework/common/tcuCommandLine.hpp
framework/egl/egluGLContextFactory.cpp
framework/egl/egluGLUtil.cpp
framework/egl/egluGLUtil.hpp
framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp [new file with mode: 0644]

index 3e7c45f..05e5d3b 100644 (file)
@@ -186,6 +186,7 @@ LOCAL_SRC_FILES := \
        framework/platform/android/tcuAndroidMain.cpp \
        framework/platform/android/tcuAndroidNativeActivity.cpp \
        framework/platform/android/tcuAndroidPlatform.cpp \
+       framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp \
        framework/platform/android/tcuAndroidRenderActivity.cpp \
        framework/platform/android/tcuAndroidTestActivity.cpp \
        framework/platform/android/tcuAndroidUtil.cpp \
index e4e55b4..2453628 100644 (file)
@@ -296,7 +296,7 @@ add_subdirectory(modules)
 if (DE_OS_IS_ANDROID)
        include_directories(executor)
 
-       add_library(deqp SHARED framework/platform/android/tcuAndroidMain.cpp framework/platform/android/tcuAndroidJNI.cpp framework/platform/android/tcuTestLogParserJNI.cpp ${DEQP_MODULE_ENTRY_POINTS})
+       add_library(deqp SHARED framework/platform/android/tcuAndroidMain.cpp framework/platform/android/tcuAndroidJNI.cpp framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp framework/platform/android/tcuTestLogParserJNI.cpp ${DEQP_MODULE_ENTRY_POINTS})
        target_link_libraries(deqp tcutil-platform xecore ${DEQP_MODULE_LIBRARIES})
 
 elseif (DE_OS_IS_IOS)
index 4da88a1..4bc0d4b 100644 (file)
@@ -50,4 +50,7 @@
        <instrumentation android:label="dEQP-Instrumentation"
                                         android:name="com.drawelements.deqp.testercore.DeqpInstrumentation"
                                         android:targetPackage="com.drawelements.deqp" />
+       <instrumentation android:label="dEQP-PlatformCapabilityQueryInstrumentation"
+                                        android:name="com.drawelements.deqp.platformutil.DeqpPlatformCapabilityQueryInstrumentation"
+                                        android:targetPackage="com.drawelements.deqp" />
 </manifest>
diff --git a/android/package/src/com/drawelements/deqp/platformutil/DeqpPlatformCapabilityQueryInstrumentation.java b/android/package/src/com/drawelements/deqp/platformutil/DeqpPlatformCapabilityQueryInstrumentation.java
new file mode 100644 (file)
index 0000000..04e3c1c
--- /dev/null
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Platform Utilites
+ * ----------------------------------------------
+ *
+ * Copyright 2015 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 dEQP platform capability query instrumentation
+ *//*--------------------------------------------------------------------*/
+
+package com.drawelements.deqp.platformutil;
+
+import android.app.Instrumentation;
+
+import android.os.Bundle;
+
+public class DeqpPlatformCapabilityQueryInstrumentation extends Instrumentation
+{
+       static
+       {
+               System.loadLibrary("deqp");
+       }
+
+       private static final String     LOG_TAG                                                 = "dEQP/PlatformCapabilityQueryInstrumentation";
+       private static final int        CONFIGQUERYRESULT_SUPPORTED             = 0;
+       private static final int        CONFIGQUERYRESULT_NOT_SUPPORTED = 1;
+       private static final int        CONFIGQUERYRESULT_GENERIC_ERROR = -1;
+
+       private String                          m_cmdLine;
+       private String                          m_queryType;
+
+       @Override
+       public void onCreate (Bundle arguments) {
+               super.onCreate(arguments);
+               start();
+
+               m_queryType = arguments.getString("deqpQueryType");
+               m_cmdLine = arguments.getString("deqpCmdLine");
+       }
+
+       @Override
+       public void onStart () {
+               super.onStart();
+
+               Bundle resultInfo;
+               int resultCode = 0;
+
+               try
+               {
+                       if ("renderConfigSupported".equals(m_queryType))
+                               resultInfo = doRenderConfigSupportedQuery();
+                       else
+                       {
+                               resultInfo = new Bundle();
+                               resultInfo.putString("Error", "unknown query");
+                               resultCode = 2;
+                       }
+               }
+               catch (Exception e)
+               {
+                       resultInfo = new Bundle();
+                       resultInfo.putString("Error", e.getMessage());
+                       resultCode = 1;
+               }
+
+               finish(resultCode, resultInfo);
+       }
+
+       private Bundle doRenderConfigSupportedQuery ()
+       {
+               if (m_cmdLine == null)
+                       throw new RuntimeException("missing command line");
+
+               final int result = nativeRenderConfigSupportedQuery(m_cmdLine);
+
+               if (result == CONFIGQUERYRESULT_SUPPORTED)
+               {
+                       final Bundle resultInfo = new Bundle();
+                       resultInfo.putString("Supported", "Yes");
+                       return resultInfo;
+               }
+               else if (result == CONFIGQUERYRESULT_NOT_SUPPORTED)
+               {
+                       final Bundle resultInfo = new Bundle();
+                       resultInfo.putString("Supported", "No");
+                       return resultInfo;
+               }
+               else if (result == CONFIGQUERYRESULT_GENERIC_ERROR)
+                       throw new RuntimeException("platform query reported failure");
+               else
+                       throw new RuntimeException("platform query returned out-of-range result");
+       }
+
+       private static native int nativeRenderConfigSupportedQuery (String cmdLine);
+}
index 9c25f31..405d9bd 100644 (file)
@@ -675,6 +675,16 @@ void CommandLine::clear (void)
        m_caseTree = DE_NULL;
 }
 
+const de::cmdline::CommandLine& CommandLine::getCommandLine (void) const
+{
+       return m_cmdLine;
+}
+
+void CommandLine::registerExtendedOptions (de::cmdline::Parser& parser)
+{
+       DE_UNREF(parser);
+}
+
 /*--------------------------------------------------------------------*//*!
  * \brief Parse command line from standard argc, argv pair.
  * \note parse() must be called exactly once.
@@ -689,6 +699,7 @@ bool CommandLine::parse (int argc, const char* const* argv)
 
        opt::registerOptions(parser);
        opt::registerLegacyOptions(parser);
+       registerExtendedOptions(parser);
 
        clear();
 
index 961b563..1685e90 100644 (file)
@@ -181,12 +181,17 @@ public:
        //! Check if test case is in supplied test case list.
        bool                                                    checkTestCaseName                       (const char* caseName) const;
 
+protected:
+       const de::cmdline::CommandLine& getCommandLine                          (void) const;
+
 private:
                                                                        CommandLine                                     (const CommandLine&);   // not allowed!
        CommandLine&                                    operator=                                       (const CommandLine&);   // not allowed!
 
        void                                                    clear                                           (void);
 
+       virtual void                                    registerExtendedOptions         (de::cmdline::Parser& parser);
+
        de::cmdline::CommandLine                m_cmdLine;
        deUint32                                                m_logFlags;
        CaseTreeNode*                                   m_caseTree;
index f192ee7..5885381 100644 (file)
@@ -202,85 +202,6 @@ RenderContext::~RenderContext(void)
        delete m_dynamicGLLibrary;
 }
 
-bool configMatches (const Library& egl, EGLDisplay display, EGLConfig eglConfig, const glu::RenderConfig& renderConfig)
-{
-       // \todo [2014-03-12 pyry] Check other attributes like double-buffer bit.
-
-       {
-               EGLint          renderableType          = 0;
-               EGLint          requiredRenderable      = apiRenderableType(renderConfig.type.getAPI());
-
-               EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
-
-               if ((renderableType & requiredRenderable) == 0)
-                       return false;
-       }
-
-       if (renderConfig.surfaceType != (glu::RenderConfig::SurfaceType)glu::RenderConfig::DONT_CARE)
-       {
-               EGLint          surfaceType             = 0;
-               EGLint          requiredSurface = 0;
-
-               switch (renderConfig.surfaceType)
-               {
-                       case glu::RenderConfig::SURFACETYPE_WINDOW:                             requiredSurface = EGL_WINDOW_BIT;       break;
-                       case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:   requiredSurface = EGL_PIXMAP_BIT;       break;
-                       case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:  requiredSurface = EGL_PBUFFER_BIT;      break;
-                       default:
-                               DE_ASSERT(false);
-               }
-
-               EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType));
-
-               if ((surfaceType & requiredSurface) == 0)
-                       return false;
-       }
-
-       {
-               static const struct
-               {
-                       int     glu::RenderConfig::*field;
-                       EGLint attrib;
-               } s_attribs[] =
-               {
-                       { &glu::RenderConfig::id,                       EGL_CONFIG_ID           },
-                       { &glu::RenderConfig::redBits,          EGL_RED_SIZE            },
-                       { &glu::RenderConfig::greenBits,        EGL_GREEN_SIZE          },
-                       { &glu::RenderConfig::blueBits,         EGL_BLUE_SIZE           },
-                       { &glu::RenderConfig::alphaBits,        EGL_ALPHA_SIZE          },
-                       { &glu::RenderConfig::depthBits,        EGL_DEPTH_SIZE          },
-                       { &glu::RenderConfig::stencilBits,      EGL_STENCIL_SIZE        },
-                       { &glu::RenderConfig::numSamples,       EGL_SAMPLES                     },
-               };
-
-               for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++)
-               {
-                       if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE)
-                       {
-                               EGLint value = 0;
-                               EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value));
-                               if (value != renderConfig.*s_attribs[attribNdx].field)
-                                       return false;
-                       }
-               }
-       }
-
-       return true;
-}
-
-EGLConfig chooseConfig (const Library& egl, EGLDisplay display, const glu::RenderConfig& config)
-{
-       const std::vector<EGLConfig> configs = eglu::getConfigs(egl, display);
-
-       for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter)
-       {
-               if (configMatches(egl, display, *iter, config))
-                       return *iter;
-       }
-
-       throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__);
-}
-
 static WindowParams::Visibility getNativeWindowVisibility (glu::RenderConfig::Visibility visibility)
 {
        using glu::RenderConfig;
index 18ec6d2..0f65b6d 100644 (file)
@@ -155,4 +155,83 @@ EGLContext createGLContext (const Library& egl, EGLDisplay display, EGLContext e
        return context;
 }
 
+static bool configMatches (const eglw::Library& egl, eglw::EGLDisplay display, eglw::EGLConfig eglConfig, const glu::RenderConfig& renderConfig)
+{
+       // \todo [2014-03-12 pyry] Check other attributes like double-buffer bit.
+
+       {
+               EGLint          renderableType          = 0;
+               EGLint          requiredRenderable      = apiRenderableType(renderConfig.type.getAPI());
+
+               EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
+
+               if ((renderableType & requiredRenderable) == 0)
+                       return false;
+       }
+
+       if (renderConfig.surfaceType != (glu::RenderConfig::SurfaceType)glu::RenderConfig::DONT_CARE)
+       {
+               EGLint          surfaceType             = 0;
+               EGLint          requiredSurface = 0;
+
+               switch (renderConfig.surfaceType)
+               {
+                       case glu::RenderConfig::SURFACETYPE_WINDOW:                             requiredSurface = EGL_WINDOW_BIT;       break;
+                       case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:   requiredSurface = EGL_PIXMAP_BIT;       break;
+                       case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:  requiredSurface = EGL_PBUFFER_BIT;      break;
+                       default:
+                               DE_ASSERT(false);
+               }
+
+               EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType));
+
+               if ((surfaceType & requiredSurface) == 0)
+                       return false;
+       }
+
+       {
+               static const struct
+               {
+                       int     glu::RenderConfig::*field;
+                       EGLint attrib;
+               } s_attribs[] =
+               {
+                       { &glu::RenderConfig::id,                       EGL_CONFIG_ID           },
+                       { &glu::RenderConfig::redBits,          EGL_RED_SIZE            },
+                       { &glu::RenderConfig::greenBits,        EGL_GREEN_SIZE          },
+                       { &glu::RenderConfig::blueBits,         EGL_BLUE_SIZE           },
+                       { &glu::RenderConfig::alphaBits,        EGL_ALPHA_SIZE          },
+                       { &glu::RenderConfig::depthBits,        EGL_DEPTH_SIZE          },
+                       { &glu::RenderConfig::stencilBits,      EGL_STENCIL_SIZE        },
+                       { &glu::RenderConfig::numSamples,       EGL_SAMPLES                     },
+               };
+
+               for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++)
+               {
+                       if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE)
+                       {
+                               EGLint value = 0;
+                               EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value));
+                               if (value != renderConfig.*s_attribs[attribNdx].field)
+                                       return false;
+                       }
+               }
+       }
+
+       return true;
+}
+
+EGLConfig chooseConfig (const Library& egl, EGLDisplay display, const glu::RenderConfig& config)
+{
+       const std::vector<EGLConfig> configs = eglu::getConfigs(egl, display);
+
+       for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter)
+       {
+               if (configMatches(egl, display, *iter, config))
+                       return *iter;
+       }
+
+       throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__);
+}
+
 }
index 395ea2e..e0db6ba 100644 (file)
@@ -40,6 +40,7 @@ namespace eglu
 glw::GLenum                    getImageGLTarget                (eglw::EGLenum source);
 eglw::EGLint           apiRenderableType               (glu::ApiType apiType);
 eglw::EGLContext       createGLContext                 (const eglw::Library& egl, eglw::EGLDisplay display, eglw::EGLConfig config, const glu::ContextType& contextType);
+eglw::EGLConfig                chooseConfig                    (const eglw::Library& egl, eglw::EGLDisplay display, const glu::RenderConfig& config);
 
 }
 
diff --git a/framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp b/framework/platform/android/tcuAndroidPlatformCapabilityQueryJNI.cpp
new file mode 100644 (file)
index 0000000..83e047d
--- /dev/null
@@ -0,0 +1,217 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Platform Utilites
+ * ----------------------------------------------
+ *
+ * Copyright 2015 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 Android platform capability query JNI component
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+
+#include "tcuCommandLine.hpp"
+#include "gluRenderConfig.hpp"
+#include "gluRenderContext.hpp"
+#include "eglwLibrary.hpp"
+#include "eglwEnums.hpp"
+#include "egluUtil.hpp"
+#include "egluGLUtil.hpp"
+
+#include <jni.h>
+
+namespace
+{
+namespace opt
+{
+
+DE_DECLARE_COMMAND_LINE_OPT(GLMajorVersion, int);
+DE_DECLARE_COMMAND_LINE_OPT(GLMinorVersion, int);
+
+} // opt
+
+class GLConfigParser : public tcu::CommandLine
+{
+public:
+                                       GLConfigParser                  (const std::string& argString);
+
+       bool                    hasGLMajorVersion               (void) const;
+       bool                    hasGLMinorVersion               (void) const;
+       int                             getGLMajorVersion               (void) const;
+       int                             getGLMinorVersion               (void) const;
+
+private:
+       virtual void    registerExtendedOptions (de::cmdline::Parser& parser);
+};
+
+GLConfigParser::GLConfigParser (const std::string& argString)
+{
+       const std::string execString = "fakebinaryname " + argString; // convert argument list to full command line
+
+       if (!parse(execString))
+       {
+               tcu::print("failed to parse command line");
+               TCU_THROW(Exception, "failed to parse command line");
+       }
+}
+
+bool GLConfigParser::hasGLMajorVersion (void) const
+{
+       return getCommandLine().hasOption<opt::GLMajorVersion>();
+}
+
+bool GLConfigParser::hasGLMinorVersion (void) const
+{
+       return getCommandLine().hasOption<opt::GLMinorVersion>();
+}
+
+int GLConfigParser::getGLMajorVersion (void) const
+{
+       DE_ASSERT(hasGLMajorVersion());
+       return getCommandLine().getOption<opt::GLMajorVersion>();
+}
+
+int GLConfigParser::getGLMinorVersion (void) const
+{
+       DE_ASSERT(hasGLMinorVersion());
+       return getCommandLine().getOption<opt::GLMinorVersion>();
+}
+
+void GLConfigParser::registerExtendedOptions (de::cmdline::Parser& parser)
+{
+       using de::cmdline::Option;
+
+       parser
+               << Option<opt::GLMajorVersion>  (DE_NULL, "deqp-gl-major-version", "OpenGL ES Major version")
+               << Option<opt::GLMinorVersion>  (DE_NULL, "deqp-gl-minor-version", "OpenGL ES Minor version");
+}
+
+glu::RenderConfig parseRenderConfig (const std::string& argsStr)
+{
+       const GLConfigParser parsedCommandLine (argsStr);
+
+       if (!parsedCommandLine.hasGLMajorVersion() ||
+               !parsedCommandLine.hasGLMinorVersion())
+       {
+               tcu::print("minor and major version must be supplied");
+               TCU_THROW(Exception, "minor and major version must be supplied");
+       }
+       else
+       {
+               const glu::ContextType  testContextType (glu::ApiType::es(parsedCommandLine.getGLMajorVersion(), parsedCommandLine.getGLMinorVersion()));
+               glu::RenderConfig               renderConfig    (testContextType);
+
+               glu::parseRenderConfig(&renderConfig, parsedCommandLine);
+
+               return renderConfig;
+       }
+}
+
+bool isRenderConfigSupported (const std::string& cmdLineStr)
+{
+       const glu::RenderConfig         renderConfig    = parseRenderConfig(cmdLineStr);
+       const eglw::DefaultLibrary      egl;
+       const eglw::EGLDisplay          display                 = egl.getDisplay(EGL_DEFAULT_DISPLAY);
+       eglw::EGLint                            eglMajor                = -1;
+       eglw::EGLint                            eglMinor                = -1;
+
+       if (display == EGL_NO_DISPLAY)
+       {
+               tcu::print("could not get default display");
+               TCU_THROW(Exception, "could not get default display");
+       }
+
+       if (egl.initialize(display, &eglMajor, &eglMinor) != EGL_TRUE)
+       {
+               tcu::print("failed to initialize egl");
+               TCU_THROW(Exception, "failed to initialize egl");
+       }
+       tcu::print("EGL initialized, major=%d, minor=%d", eglMajor, eglMinor);
+
+       try
+       {
+               // ignoring return value
+               (void)eglu::chooseConfig(egl, display, renderConfig);
+       }
+       catch (const tcu::NotSupportedError&)
+       {
+               tcu::print("No matching config");
+               egl.terminate(display);
+               return false;
+       }
+       catch (...)
+       {
+               egl.terminate(display);
+               throw;
+       }
+       egl.terminate(display);
+
+       return true;
+}
+
+} // anonymous
+
+
+DE_BEGIN_EXTERN_C
+
+JNIEXPORT jint JNICALL Java_com_drawelements_deqp_platformutil_DeqpPlatformCapabilityQueryInstrumentation_nativeRenderConfigSupportedQuery (JNIEnv* env, jclass, jstring jCmdLine)
+{
+       enum
+       {
+               CONFIGQUERYRESULT_SUPPORTED = 0,
+               CONFIGQUERYRESULT_NOT_SUPPORTED = 1,
+               CONFIGQUERYRESULT_GENERIC_ERROR = -1,
+       };
+
+       std::string                     cmdLine;
+       const char* const       cmdLineBytes = env->GetStringUTFChars(jCmdLine, DE_NULL);
+
+       if (cmdLineBytes == DE_NULL)
+       {
+               // no command line is not executable
+               tcu::print("no command line supplied");
+               return CONFIGQUERYRESULT_GENERIC_ERROR;
+       }
+
+       try
+       {
+               // try to copy to local buffer
+               cmdLine = std::string(cmdLineBytes);
+       }
+       catch (const std::bad_alloc&)
+       {
+               env->ReleaseStringUTFChars(jCmdLine, cmdLineBytes);
+               tcu::print("failed to copy cmdLine");
+               return CONFIGQUERYRESULT_GENERIC_ERROR;
+       }
+       env->ReleaseStringUTFChars(jCmdLine, cmdLineBytes);
+
+       try
+       {
+               const bool isSupported = isRenderConfigSupported(cmdLine);
+
+               return (isSupported) ? (CONFIGQUERYRESULT_SUPPORTED)
+                                    : (CONFIGQUERYRESULT_NOT_SUPPORTED);
+       }
+       catch (const std::exception& ex)
+       {
+               // don't bother forwarding the exception to the caller. They cannot do anything with the exception anyway.
+               tcu::print("Error: %s", ex.what());
+               return CONFIGQUERYRESULT_GENERIC_ERROR;
+       }
+}
+
+DE_END_EXTERN_C