Refactored EGLImage tests.
authorMika Isojärvi <misojarvi@google.com>
Wed, 29 Oct 2014 12:59:20 +0000 (14:59 +0200)
committerMika Isojärvi <misojarvi@google.com>
Mon, 10 Nov 2014 14:03:29 +0000 (16:03 +0200)
Refactor EGLImage tests and add more EGL utilities.

Change-Id: I3e7a1648b087316e7ae9ac85e52b88cbe89d33bf

25 files changed:
framework/egl/CMakeLists.txt
framework/egl/egluExtensions.cpp [new file with mode: 0644]
framework/egl/egluExtensions.hpp [new file with mode: 0644]
framework/egl/egluGLContextFactory.cpp
framework/egl/egluGLUtil.cpp [new file with mode: 0644]
framework/egl/egluGLUtil.hpp [new file with mode: 0644]
framework/egl/egluHeaderWrapper.hpp
framework/egl/egluUnique.cpp
framework/egl/egluUnique.hpp
framework/egl/egluUtil.cpp
framework/egl/egluUtil.hpp
framework/opengl/gluDefs.hpp
framework/opengl/gluObjectWrapper.cpp
framework/opengl/gluObjectWrapper.hpp
framework/opengl/gluShaderProgram.cpp
framework/opengl/gluShaderProgram.hpp
framework/opengl/wrapper/glwTypes.inl
modules/egl/CMakeLists.txt
modules/egl/teglImageFormatTests.cpp
modules/egl/teglImageFormatTests.hpp
modules/egl/teglImageTests.cpp
modules/egl/teglImageUtil.cpp [new file with mode: 0644]
modules/egl/teglImageUtil.hpp [new file with mode: 0644]
modules/egl/teglTestCase.cpp
modules/egl/teglTestCase.hpp

index 832bb98667c078012f798812bf690e511da0be39..5346e74056e3e1235dccae65e958727ae6e3f416 100644 (file)
@@ -12,10 +12,14 @@ set(EGLUTIL_SRCS
        egluConfigInfo.hpp
        egluDefs.cpp
        egluDefs.hpp
+       egluExtensions.cpp
+       egluExtensions.hpp
        egluGLContextFactory.cpp
        egluGLContextFactory.hpp
        egluGLFunctionLoader.cpp
        egluGLFunctionLoader.hpp
+       egluGLUtil.cpp
+       egluGLUtil.hpp
        egluHeaderWrapper.cpp
        egluHeaderWrapper.hpp
        egluNativeDisplay.cpp
diff --git a/framework/egl/egluExtensions.cpp b/framework/egl/egluExtensions.cpp
new file mode 100644 (file)
index 0000000..efd7fb9
--- /dev/null
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 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 extension resolving.
+ *//*--------------------------------------------------------------------*/
+
+#include "egluExtensions.hpp"
+
+#include "egluUtil.hpp"
+#include "tcuDefs.hpp"
+
+
+namespace eglu
+{
+
+deFunctionPtr getProcAddressChecked (const char* procName)
+{
+       const deFunctionPtr func = eglGetProcAddress(procName);
+
+       TCU_CHECK_AND_THROW(NotSupportedError, func, procName);
+
+       return func;
+}
+
+ImageFunctions getImageFunctions (EGLDisplay dpy)
+{
+       ImageFunctions ret;
+
+       if (getVersion(dpy) >= Version(1, 5))
+       {
+               ret.createImage = getFunction<PFNEGLCREATEIMAGEKHRPROC>("eglCreateImage");
+               ret.destroyImage = getFunction<PFNEGLDESTROYIMAGEKHRPROC>("eglDestroyImage");
+       }
+       else if (hasExtension(dpy, "EGL_KHR_image_base"))
+       {
+               ret.createImage = getFunction<PFNEGLCREATEIMAGEKHRPROC>("eglCreateImageKHR");
+               ret.destroyImage = getFunction<PFNEGLDESTROYIMAGEKHRPROC>("eglDestroyImageKHR");
+       }
+       else
+               TCU_THROW(NotSupportedError, "EGLImages are not supported");
+
+       return ret;
+}
+
+}
diff --git a/framework/egl/egluExtensions.hpp b/framework/egl/egluExtensions.hpp
new file mode 100644 (file)
index 0000000..1d28348
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _EGLUEXTENSIONS_HPP
+#define _EGLUEXTENSIONS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 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 extension resolving.
+ *//*--------------------------------------------------------------------*/
+
+#include "deDefs.hpp"
+#include "egluHeaderWrapper.hpp"
+
+namespace eglu
+{
+
+deFunctionPtr getProcAddressChecked (const char* procName);
+
+template <typename FUNC>
+inline FUNC getFunction (const char* procName)
+{
+       return reinterpret_cast<FUNC>(getProcAddressChecked(procName));
+}
+
+struct ImageFunctions
+{
+       PFNEGLCREATEIMAGEKHRPROC        createImage;
+       PFNEGLDESTROYIMAGEKHRPROC       destroyImage;
+};
+
+ImageFunctions getImageFunctions (EGLDisplay dpy);
+
+} // eglu
+
+#endif // _EGLUEXTENSIONS_HPP
index bf9c1c73c52d5d6a23fe773d811e7acbc3906e85..980e27eb308ae9966a0f11d387d9d044b9b655b3 100644 (file)
@@ -32,6 +32,7 @@
 #include "egluDefs.hpp"
 #include "egluHeaderWrapper.hpp"
 #include "egluUtil.hpp"
+#include "egluGLUtil.hpp"
 #include "egluNativeWindow.hpp"
 #include "egluNativePixmap.hpp"
 #include "egluStrUtil.hpp"
 using std::string;
 using std::vector;
 
-#if !defined(EGL_KHR_create_context)
-       #define EGL_KHR_create_context 1
-       #define EGL_CONTEXT_MAJOR_VERSION_KHR                                           0x3098
-       #define EGL_CONTEXT_MINOR_VERSION_KHR                                           0x30FB
-       #define EGL_CONTEXT_FLAGS_KHR                                                           0x30FC
-       #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR                                     0x30FD
-       #define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR      0x31BD
-       #define EGL_NO_RESET_NOTIFICATION_KHR                                           0x31BE
-       #define EGL_LOSE_CONTEXT_ON_RESET_KHR                                           0x31BF
-       #define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR                                        0x00000001
-       #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR           0x00000002
-       #define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR                        0x00000004
-       #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR                         0x00000001
-       #define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR        0x00000002
-       #define EGL_OPENGL_ES3_BIT_KHR                                                          0x00000040
-#endif // EGL_KHR_create_context
-
 // \todo [2014-03-12 pyry] Use command line arguments for libraries?
 
 // Default library names
@@ -212,22 +196,7 @@ bool configMatches (EGLDisplay display, EGLConfig eglConfig, const glu::RenderCo
 
        {
                EGLint          renderableType          = 0;
-               EGLint          requiredRenderable      = 0;
-
-               if (glu::isContextTypeES(renderConfig.type))
-               {
-                       if (renderConfig.type.getMajorVersion() == 2)
-                               requiredRenderable = EGL_OPENGL_ES2_BIT;
-                       else if (renderConfig.type.getMajorVersion() == 3)
-                               requiredRenderable = EGL_OPENGL_ES3_BIT_KHR;
-                       else
-                               throw tcu::NotSupportedError("Unsupported OpenGL ES version");
-               }
-               else
-               {
-                       DE_ASSERT(glu::isContextTypeGLCore(renderConfig.type) || glu::isContextTypeGLCompatibility(renderConfig.type));
-                       requiredRenderable = EGL_OPENGL_BIT;
-               }
+               EGLint          requiredRenderable      = apiRenderableType(renderConfig.type.getAPI());
 
                EGLU_CHECK_CALL(eglGetConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
 
@@ -383,91 +352,6 @@ EGLSurface createPBuffer (EGLDisplay display, EGLConfig eglConfig, const glu::Re
        return surface;
 }
 
-bool isClientExtensionSupported (EGLDisplay display, const std::string& extName)
-{
-       const vector<string> exts = getClientExtensions(display);
-       return de::contains(exts.begin(), exts.end(), extName);
-}
-
-EGLContext createContext (EGLDisplay display, EGLContext eglConfig, const glu::RenderConfig& config)
-{
-       const bool                      khrCreateContextSupported       = isClientExtensionSupported(display, "EGL_KHR_create_context");
-       EGLContext                      context                                         = EGL_NO_CONTEXT;
-       EGLenum                         api                                                     = EGL_NONE;
-       vector<EGLint>          attribList;
-
-       if (glu::isContextTypeES(config.type))
-       {
-               api = EGL_OPENGL_ES_API;
-
-               if (config.type.getMajorVersion() <= 2)
-               {
-                       attribList.push_back(EGL_CONTEXT_CLIENT_VERSION);
-                       attribList.push_back(config.type.getMajorVersion());
-               }
-               else
-               {
-                       if (!khrCreateContextSupported)
-                               throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL ES 3.0 and newer", DE_NULL, __FILE__, __LINE__);
-
-                       attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
-                       attribList.push_back(config.type.getMajorVersion());
-                       attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
-                       attribList.push_back(config.type.getMinorVersion());
-               }
-       }
-       else
-       {
-               DE_ASSERT(glu::isContextTypeGLCore(config.type) || glu::isContextTypeGLCompatibility(config.type));
-
-               if (!khrCreateContextSupported)
-                       throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL context creation", DE_NULL, __FILE__, __LINE__);
-
-               api = EGL_OPENGL_API;
-
-               attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
-               attribList.push_back(config.type.getMajorVersion());
-               attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
-               attribList.push_back(config.type.getMinorVersion());
-               attribList.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
-               attribList.push_back(glu::isContextTypeGLCore(config.type) ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
-                                                                                                                                  : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
-       }
-
-       if (config.type.getFlags() != glu::ContextFlags(0))
-       {
-               EGLint flags = 0;
-
-               if (!khrCreateContextSupported)
-                       throw tcu::NotSupportedError("EGL_KHR_create_context is required for creating robust/debug/forward-compatible contexts");
-
-               if ((config.type.getFlags() & glu::CONTEXT_DEBUG) != 0)
-                       flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
-
-               if ((config.type.getFlags() & glu::CONTEXT_ROBUST) != 0)
-                       flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
-
-               if ((config.type.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
-               {
-                       if (!glu::isContextTypeGLCore(config.type))
-                               throw tcu::NotSupportedError("Only OpenGL core contexts can be forward-compatible");
-
-                       flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
-               }
-
-               attribList.push_back(EGL_CONTEXT_FLAGS_KHR);
-               attribList.push_back(flags);
-       }
-
-       attribList.push_back(EGL_NONE);
-
-       EGLU_CHECK_CALL(eglBindAPI(api));
-       context = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT, &(attribList[0]));
-       EGLU_CHECK_MSG("eglCreateContext()");
-
-       return context;
-}
-
 void RenderContext::create (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
 {
        glu::RenderConfig::SurfaceType  surfaceType     = config.surfaceType;
@@ -536,13 +420,13 @@ void RenderContext::create (const NativeDisplayFactory* displayFactory, const Na
                        throw tcu::InternalError("Invalid surface type");
        }
 
-       m_eglContext = createContext(m_eglDisplay, m_eglConfig, config);
+       m_eglContext = createGLContext(m_eglDisplay, m_eglConfig, config.type);
 
        EGLU_CHECK_CALL(eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
 
        // Init core functions
 
-       if (isClientExtensionSupported(m_eglDisplay, "EGL_KHR_get_all_proc_addresses"))
+       if (hasExtension(m_eglDisplay, "EGL_KHR_get_all_proc_addresses"))
        {
                // Use eglGetProcAddress() for core functions
                GetProcFuncLoader funcLoader;
diff --git a/framework/egl/egluGLUtil.cpp b/framework/egl/egluGLUtil.cpp
new file mode 100644 (file)
index 0000000..ecd0cef
--- /dev/null
@@ -0,0 +1,154 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 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 utilities for interfacing with GL APIs.
+ *//*--------------------------------------------------------------------*/
+
+#include "egluGLUtil.hpp"
+
+#include "egluUtil.hpp"
+#include "glwEnums.hpp"
+
+#include <vector>
+
+using std::vector;
+
+namespace eglu
+{
+
+glw::GLenum getImageGLTarget (EGLenum source)
+{
+       switch (source)
+       {
+               case EGL_GL_TEXTURE_2D_KHR:                                             return GL_TEXTURE_2D;
+               case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:    return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+               case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:    return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+               case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:    return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
+               case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:    return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+               case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:    return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+               case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:    return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+               case EGL_GL_TEXTURE_3D_KHR:                                             return GL_TEXTURE_3D;
+               case EGL_GL_RENDERBUFFER_KHR:                                   return GL_RENDERBUFFER;
+               default:        DE_ASSERT(!"Impossible");                       return GL_NONE;
+       }
+}
+
+EGLint apiRenderableType (glu::ApiType apiType)
+{
+       switch (apiType.getProfile())
+       {
+               case glu::PROFILE_CORE:
+               case glu::PROFILE_COMPATIBILITY:
+                       return EGL_OPENGL_BIT;
+               case glu::PROFILE_ES:
+                       switch (apiType.getMajorVersion())
+                       {
+                               case 1:         return EGL_OPENGL_ES_BIT;
+                               case 2:         return EGL_OPENGL_ES2_BIT;
+                               case 3:         return EGL_OPENGL_ES3_BIT_KHR;
+                               default:        DE_ASSERT(!"Unknown OpenGL ES version");
+                       }
+               default:
+                       DE_ASSERT(!"Unknown GL API");
+       }
+
+       return 0;
+}
+
+EGLContext createGLContext (EGLDisplay display, EGLContext eglConfig, const glu::ContextType& contextType)
+{
+       const bool                      khrCreateContextSupported       = hasExtension(display, "EGL_KHR_create_context");
+       EGLContext                      context                                         = EGL_NO_CONTEXT;
+       EGLenum                         api                                                     = EGL_NONE;
+       vector<EGLint>          attribList;
+
+       if (glu::isContextTypeES(contextType))
+       {
+               api = EGL_OPENGL_ES_API;
+
+               if (contextType.getMajorVersion() <= 2)
+               {
+                       attribList.push_back(EGL_CONTEXT_CLIENT_VERSION);
+                       attribList.push_back(contextType.getMajorVersion());
+               }
+               else
+               {
+                       if (!khrCreateContextSupported)
+                               throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL ES 3.0 and newer", DE_NULL, __FILE__, __LINE__);
+
+                       attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
+                       attribList.push_back(contextType.getMajorVersion());
+                       attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
+                       attribList.push_back(contextType.getMinorVersion());
+               }
+       }
+       else
+       {
+               DE_ASSERT(glu::isContextTypeGLCore(contextType) || glu::isContextTypeGLCompatibility(contextType));
+
+               if (!khrCreateContextSupported)
+                       throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL context creation", DE_NULL, __FILE__, __LINE__);
+
+               api = EGL_OPENGL_API;
+
+               attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
+               attribList.push_back(contextType.getMajorVersion());
+               attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
+               attribList.push_back(contextType.getMinorVersion());
+               attribList.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
+               attribList.push_back(glu::isContextTypeGLCore(contextType) ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
+                                                                                                                                  : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
+       }
+
+       if (contextType.getFlags() != glu::ContextFlags(0))
+       {
+               EGLint flags = 0;
+
+               if (!khrCreateContextSupported)
+                       throw tcu::NotSupportedError("EGL_KHR_create_context is required for creating robust/debug/forward-compatible contexts");
+
+               if ((contextType.getFlags() & glu::CONTEXT_DEBUG) != 0)
+                       flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+
+               if ((contextType.getFlags() & glu::CONTEXT_ROBUST) != 0)
+                       flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+
+               if ((contextType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
+               {
+                       if (!glu::isContextTypeGLCore(contextType))
+                               throw tcu::NotSupportedError("Only OpenGL core contexts can be forward-compatible");
+
+                       flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+               }
+
+               attribList.push_back(EGL_CONTEXT_FLAGS_KHR);
+               attribList.push_back(flags);
+       }
+
+       attribList.push_back(EGL_NONE);
+
+       EGLU_CHECK_CALL(eglBindAPI(api));
+       context = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT, &(attribList[0]));
+       EGLU_CHECK_MSG("eglCreateContext()");
+
+       return context;
+}
+
+}
diff --git a/framework/egl/egluGLUtil.hpp b/framework/egl/egluGLUtil.hpp
new file mode 100644 (file)
index 0000000..0f2feed
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _EGLUGLUTIL_HPP
+#define _EGLUGLUTIL_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 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 utilities for interfacing with GL APIs.
+ *//*--------------------------------------------------------------------*/
+
+#include "egluDefs.hpp"
+#include "egluHeaderWrapper.hpp"
+
+#include "gluRenderConfig.hpp"
+#include "glwDefs.hpp"
+
+namespace eglu
+{
+
+glw::GLenum            getImageGLTarget                (EGLenum source);
+EGLint                 apiRenderableType               (glu::ApiType apiType);
+EGLContext             createGLContext                 (EGLDisplay display, EGLConfig config, const glu::ContextType& contextType);
+
+}
+
+#endif // _EGLUGLUTIL_HPP
index 70124a5ba1e8387eac6610a4ab3e16f74d405ddb..cdb8b89ad572175c267f3ca0be6d24bc8685779d 100644 (file)
 #endif
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 
 #if !defined(EGL_VERSION_1_5)
        typedef deIntptr EGLAttrib;
 #endif
 
+#if !defined(EGL_KHR_create_context)
+       #define EGL_KHR_create_context 1
+       #define EGL_CONTEXT_MAJOR_VERSION_KHR                                           0x3098
+       #define EGL_CONTEXT_MINOR_VERSION_KHR                                           0x30FB
+       #define EGL_CONTEXT_FLAGS_KHR                                                           0x30FC
+       #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR                                     0x30FD
+       #define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR      0x31BD
+       #define EGL_NO_RESET_NOTIFICATION_KHR                                           0x31BE
+       #define EGL_LOSE_CONTEXT_ON_RESET_KHR                                           0x31BF
+       #define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR                                        0x00000001
+       #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR           0x00000002
+       #define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR                        0x00000004
+       #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR                         0x00000001
+       #define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR        0x00000002
+       #define EGL_OPENGL_ES3_BIT_KHR                                                          0x00000040
+#endif // EGL_KHR_create_context
+
 #endif // _EGLUHEADERWRAPPER_HPP
index 3ef7bc3d1673f104e1fa4772b77800f53a2bf798..8b15fdfd2e37b7be52bb5cfc3237aec1d16b86d8 100644 (file)
@@ -63,4 +63,17 @@ ScopedCurrentContext::~ScopedCurrentContext (void)
        EGLU_CHECK_CALL(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
 }
 
+UniqueImage::UniqueImage (EGLDisplay display, EGLImageKHR image, const ImageFunctions& funcs)
+       : m_display     (display)
+       , m_image       (image)
+       , m_funcs       (funcs)
+{
+}
+
+UniqueImage::~UniqueImage (void)
+{
+       if (m_image != EGL_NO_IMAGE_KHR)
+               EGLU_CHECK_CALL(m_funcs.destroyImage(m_display, m_image));
+}
+
 } // eglu
index a88fb4163481583d58829fbdf1b67decdff83003..7db218a2163471abdf3c57fb58947f6fdb99fe4e 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "egluDefs.hpp"
 #include "egluHeaderWrapper.hpp"
+#include "egluExtensions.hpp"
 
 namespace eglu
 {
@@ -75,6 +76,25 @@ private:
        EGLDisplay              m_display;
 };
 
+class UniqueImage
+{
+public:
+                                                       UniqueImage             (EGLDisplay display, EGLImageKHR image, const ImageFunctions& funcs);
+                                                       ~UniqueImage    (void);
+
+       EGLImageKHR                             operator*               (void) { return m_image; }
+       operator                                bool                    (void) const { return m_image != EGL_NO_IMAGE_KHR; }
+
+private:
+       EGLDisplay                              m_display;
+       EGLImageKHR                             m_image;
+       const ImageFunctions&   m_funcs;
+
+       // Disabled
+       UniqueImage             operator=               (const UniqueImage&);
+                                       UniqueImage             (const UniqueImage&);
+};
+
 } // eglu
 
 #endif // _EGLUUNIQUE_HPP
index 428223410d8a837c8bd655b754dec7f012afdf1e..28d66fe7fc65a38ec5dd9d0576352f16caad8c37 100644 (file)
 #include "egluNativeDisplay.hpp"
 #include "tcuCommandLine.hpp"
 #include "deSTLUtil.hpp"
+#include "deStringUtil.hpp"
+#include "glwEnums.hpp"
+
+#include <EGL/eglext.h>
 
 #include <algorithm>
 #include <sstream>
@@ -43,46 +47,56 @@ using std::vector;
 namespace eglu
 {
 
-vector<string> getPlatformExtensions (void)
+vector<EGLint> attribMapToVector (const AttribMap& attribs)
 {
-       const char* const       extensionStr    = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
-       const EGLint            result                  = eglGetError();
+       vector<EGLint> attribList;
 
-       if (result == EGL_SUCCESS)
+       for (AttribMap::const_iterator it = attribs.begin(); it != attribs.end(); ++it)
        {
-               std::istringstream      stream                  (extensionStr);
-               string                          currentExtension;
-               vector<string>          extensions;
+               attribList.push_back(it->first);
+               attribList.push_back(it->second);
+       }
 
-               while (std::getline(stream, currentExtension, ' '))
-                       extensions.push_back(currentExtension);
+       attribList.push_back(EGL_NONE);
 
-               return extensions;
-       }
-       else if (result != EGL_BAD_DISPLAY)
-               throw Error(result, "eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS)", DE_NULL, __FILE__, __LINE__);
-       else
-               return vector<string>();
+       return attribList;
 }
 
-vector<string> getClientExtensions (EGLDisplay display)
+Version getVersion (EGLDisplay display)
 {
-       const char* const       extensionStr    = eglQueryString(display, EGL_EXTENSIONS);
-       const EGLint            result                  = eglGetError();
+       EGLint major, minor;
 
-       if (result == EGL_SUCCESS)
-       {
-               std::istringstream      stream                  (extensionStr);
-               string                          currentExtension;
-               vector<string>          extensions;
+       // eglInitialize on already initialized displays just returns the version.
+       EGLU_CHECK_CALL(eglInitialize(display, &major, &minor));
+
+       return Version(major, minor);
+}
 
-               while (std::getline(stream, currentExtension, ' '))
-                       extensions.push_back(currentExtension);
+vector<string> getExtensions (EGLDisplay display)
+{
+       const char*     const extensionStr = eglQueryString(display, EGL_EXTENSIONS);
 
-               return extensions;
-       }
-       else
-               throw Error(result, "eglQueryString(display, EGL_EXTENSIONS)", DE_NULL, __FILE__, __LINE__);
+       EGLU_CHECK_MSG("Querying extensions failed");
+
+       return de::splitString(extensionStr, ' ');
+}
+
+bool hasExtension (EGLDisplay display, const string& str)
+{
+       const vector<string> extensions = getExtensions(display);
+       return de::contains(extensions.begin(), extensions.end(), str);
+}
+
+vector<string> getPlatformExtensions (void)
+{
+       return getExtensions(EGL_NO_DISPLAY);
+}
+
+vector<string> getClientExtensions (EGLDisplay display)
+{
+       DE_ASSERT(display != EGL_NO_DISPLAY);
+
+       return getExtensions(display);
 }
 
 vector<EGLConfig> getConfigs (EGLDisplay display)
@@ -143,6 +157,11 @@ EGLint getConfigAttribInt (EGLDisplay display, EGLConfig config, EGLint attrib)
        return value;
 }
 
+EGLint getConfigID (EGLDisplay display, EGLConfig config)
+{
+       return getConfigAttribInt (display, config, EGL_CONFIG_ID);
+}
+
 EGLint querySurfaceInt (EGLDisplay display, EGLSurface surface, EGLint attrib)
 {
        EGLint value = 0;
index 1f8527514976bc6029b2958d9e4cae5ab6e9d984..9bd77bca44118392d3404ce95a0afd7aa63a702d 100644 (file)
@@ -24,6 +24,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "tcuDefs.hpp"
+#include "egluDefs.hpp"
 #include "egluHeaderWrapper.hpp"
 #include "egluNativeWindow.hpp"
 
@@ -44,12 +45,17 @@ class NativePixmap;
 
 typedef std::map<EGLint, EGLint> AttribMap;
 
+std::vector<EGLint>                    attribMapToVector                       (const AttribMap& map);
+
+Version                                                getVersion                                      (EGLDisplay display);
+bool                                           hasExtension                            (EGLDisplay display, const std::string& extName);
 std::vector<std::string>       getPlatformExtensions           (void);
 std::vector<std::string>       getClientExtensions                     (EGLDisplay display);
 std::vector<EGLConfig>         getConfigs                                      (EGLDisplay display);
 std::vector<EGLConfig>         chooseConfig                            (EGLDisplay display, const AttribMap& attribs);
 EGLConfig                                      chooseSingleConfig                      (EGLDisplay display, const AttribMap& attribs);
 EGLint                                         getConfigAttribInt                      (EGLDisplay display, EGLConfig config, EGLint attrib);
+EGLint                                         getConfigID                                     (EGLDisplay display, EGLConfig config);
 EGLint                                         querySurfaceInt                         (EGLDisplay display, EGLSurface surface, EGLint attrib);
 tcu::IVec2                                     getSurfaceSize                          (EGLDisplay display, EGLSurface surface);
 tcu::IVec2                                     getSurfaceResolution            (EGLDisplay display, EGLSurface surface);
index 189c7b013f4f7c720844ac678f3ee2cf18987165..9275db6fab164c35718fc9940b2b3c221236e1cd 100644 (file)
@@ -33,6 +33,9 @@
 #define GLU_CHECK_CALL_ERROR(CALL, ERR)        do { CALL; GLU_EXPECT_NO_ERROR(ERR, #CALL); } while (deGetFalse())
 #define GLU_CHECK_CALL(CALL)                   do { CALL; GLU_EXPECT_NO_ERROR(glGetError(), #CALL); } while (deGetFalse())
 
+#define GLU_CHECK_GLW_MSG(GL, MSG)             GLU_EXPECT_NO_ERROR((GL).getError(), MSG)
+#define GLU_CHECK_GLW(GL)                              GLU_CHECK_GLW_MSG(GL, DE_NULL)
+#define GLU_CHECK_GLW_CALL(GL, CALL)   do { (GL).CALL; GLU_EXPECT_NO_ERROR((GL).getError(), #CALL); } while (deGetFalse())
 
 /*--------------------------------------------------------------------*//*!
  * \brief OpenGL (ES) utilities
index c1f432053dd03c1644a974d9e5d36cacf6448182..55ffd1c8a7d512fa5dde832af7998b1b38924e8b 100644 (file)
@@ -54,6 +54,14 @@ ObjectWrapper::ObjectWrapper (const glw::Functions& gl, const ObjectTraits& trai
        }
 }
 
+ObjectWrapper::ObjectWrapper (const glw::Functions& gl, const ObjectTraits& traits, deUint32 object)
+       : m_gl          (gl)
+       , m_traits      (traits)
+       , m_object      (object)
+{
+       DE_ASSERT(object != 0);
+}
+
 ObjectWrapper::~ObjectWrapper (void)
 {
        (m_gl.*m_traits.deleteFunc)(1, &m_object);
index c29b310db15caaa6771d9837f5208797c89350b6..6edefd0b596b8701c336fab01504f08eb0ce0e86 100644 (file)
@@ -64,6 +64,7 @@ class ObjectWrapper
 {
 public:
                                                        ObjectWrapper           (const glw::Functions& gl, const ObjectTraits& traits);
+                                                       ObjectWrapper           (const glw::Functions& gl, const ObjectTraits& traits, deUint32 object);
                                                        ~ObjectWrapper          (void);
 
        inline deUint32                 get                                     (void) const { return m_object; }
@@ -85,6 +86,7 @@ private:
 template<ObjectType Type> class TypedObjectWrapper : public ObjectWrapper
 {
 public:
+                               TypedObjectWrapper (const glw::Functions& gl, deUint32 object) : ObjectWrapper(gl, objectTraits(Type), object) {}
        explicit        TypedObjectWrapper (const RenderContext& context) : ObjectWrapper(context.getFunctions(), objectTraits(Type)) {}
        explicit        TypedObjectWrapper (const glw::Functions& gl) : ObjectWrapper(gl, objectTraits(Type)) {}
 };
index 09e8252f99bb76189e50898efd731ccb340d84ac..1b47046f710bc54e82a7ad346a8d5da190ff065b 100644 (file)
@@ -38,29 +38,34 @@ namespace glu
 // Shader
 
 Shader::Shader (const RenderContext& renderCtx, ShaderType shaderType)
-       : m_renderCtx   (renderCtx)
-       , m_shader              (0)
+       : m_gl          (renderCtx.getFunctions())
+       , m_shader      (0)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
+       m_info.type     = shaderType;
+       m_shader        = m_gl.createShader(getGLShaderType(shaderType));
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateShader()");
+       TCU_CHECK(m_shader);
+}
 
+Shader::Shader (const glw::Functions& gl, ShaderType shaderType)
+       : m_gl          (gl)
+       , m_shader      (0)
+{
        m_info.type     = shaderType;
-       m_shader        = gl.createShader(getGLShaderType(shaderType));
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader()");
+       m_shader        = m_gl.createShader(getGLShaderType(shaderType));
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateShader()");
        TCU_CHECK(m_shader);
 }
 
 Shader::~Shader (void)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-       gl.deleteShader(m_shader);
+       m_gl.deleteShader(m_shader);
 }
 
 void Shader::setSources (int numSourceStrings, const char* const* sourceStrings, const int* lengths)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.shaderSource(m_shader, numSourceStrings, sourceStrings, lengths);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
+       m_gl.shaderSource(m_shader, numSourceStrings, sourceStrings, lengths);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glShaderSource()");
 
        m_info.source.clear();
        for (int ndx = 0; ndx < numSourceStrings; ndx++)
@@ -72,19 +77,17 @@ void Shader::setSources (int numSourceStrings, const char* const* sourceStrings,
 
 void Shader::compile (void)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
        m_info.compileOk                = false;
        m_info.compileTimeUs    = 0;
        m_info.infoLog.clear();
 
        {
                deUint64 compileStart = deGetMicroseconds();
-               gl.compileShader(m_shader);
+               m_gl.compileShader(m_shader);
                m_info.compileTimeUs = deGetMicroseconds() - compileStart;
        }
 
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()");
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCompileShader()");
 
        // Query status & log.
        {
@@ -92,16 +95,16 @@ void Shader::compile (void)
                int     infoLogLen              = 0;
                int     unusedLen;
 
-               gl.getShaderiv(m_shader, GL_COMPILE_STATUS,             &compileStatus);
-               gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH,    &infoLogLen);
-               GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
+               m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS,           &compileStatus);
+               m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH,  &infoLogLen);
+               GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");
 
                m_info.compileOk = compileStatus != GL_FALSE;
 
                if (infoLogLen > 0)
                {
                        std::vector<char> infoLog(infoLogLen);
-                       gl.getShaderInfoLog(m_shader, (int)infoLog.size(), &unusedLen, &infoLog[0]);
+                       m_gl.getShaderInfoLog(m_shader, (int)infoLog.size(), &unusedLen, &infoLog[0]);
                        m_info.infoLog = std::string(&infoLog[0], infoLogLen);
                }
        }
@@ -109,9 +112,8 @@ void Shader::compile (void)
 
 // Program
 
-static bool getProgramLinkStatus (const RenderContext& renderCtx, deUint32 program)
+static bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program)
 {
-       const glw::Functions& gl        = renderCtx.getFunctions();
        int     linkStatus                              = 0;
 
        gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
@@ -119,10 +121,8 @@ static bool getProgramLinkStatus (const RenderContext& renderCtx, deUint32 progr
        return (linkStatus != GL_FALSE);
 }
 
-static std::string getProgramInfoLog (const RenderContext& renderCtx, deUint32 program)
+static std::string getProgramInfoLog (const glw::Functions& gl, deUint32 program)
 {
-       const glw::Functions& gl = renderCtx.getFunctions();
-
        int     infoLogLen      = 0;
        int     unusedLen;
 
@@ -139,141 +139,133 @@ static std::string getProgramInfoLog (const RenderContext& renderCtx, deUint32 p
 }
 
 Program::Program (const RenderContext& renderCtx)
-       : m_renderCtx   (renderCtx)
-       , m_program             (0)
+       : m_gl          (renderCtx.getFunctions())
+       , m_program     (0)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
+       m_program = m_gl.createProgram();
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateProgram()");
+}
 
-       m_program = gl.createProgram();
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram()");
+Program::Program (const glw::Functions& gl)
+       : m_gl          (gl)
+       , m_program     (0)
+{
+       m_program = m_gl.createProgram();
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glCreateProgram()");
 }
 
 Program::Program (const RenderContext& renderCtx, deUint32 program)
-       : m_renderCtx   (renderCtx)
-       , m_program             (program)
+       : m_gl          (renderCtx.getFunctions())
+       , m_program     (program)
 {
-       m_info.linkOk   = getProgramLinkStatus(renderCtx, program);
-       m_info.infoLog  = getProgramInfoLog(renderCtx, program);
+       m_info.linkOk   = getProgramLinkStatus(m_gl, program);
+       m_info.infoLog  = getProgramInfoLog(m_gl, program);
 }
 
 Program::~Program (void)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-       gl.deleteProgram(m_program);
+       m_gl.deleteProgram(m_program);
 }
 
 void Program::attachShader (deUint32 shader)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.attachShader(m_program, shader);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()");
+       m_gl.attachShader(m_program, shader);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glAttachShader()");
 }
 
 void Program::detachShader (deUint32 shader)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.detachShader(m_program, shader);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader()");
+       m_gl.detachShader(m_program, shader);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDetachShader()");
 }
 
 void Program::bindAttribLocation (deUint32 location, const char* name)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.bindAttribLocation(m_program, location, name);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation()");
+       m_gl.bindAttribLocation(m_program, location, name);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindAttribLocation()");
 }
 
 void Program::transformFeedbackVaryings (int count, const char* const* varyings, deUint32 bufferMode)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.transformFeedbackVaryings(m_program, count, varyings, bufferMode);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings()");
+       m_gl.transformFeedbackVaryings(m_program, count, varyings, bufferMode);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTransformFeedbackVaryings()");
 }
 
 void Program::link (void)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
        m_info.linkOk           = false;
        m_info.linkTimeUs       = 0;
        m_info.infoLog.clear();
 
        {
                deUint64 linkStart = deGetMicroseconds();
-               gl.linkProgram(m_program);
+               m_gl.linkProgram(m_program);
                m_info.linkTimeUs = deGetMicroseconds() - linkStart;
        }
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()");
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glLinkProgram()");
 
-       m_info.linkOk   = getProgramLinkStatus(m_renderCtx, m_program);
-       m_info.infoLog  = getProgramInfoLog(m_renderCtx, m_program);
+       m_info.linkOk   = getProgramLinkStatus(m_gl, m_program);
+       m_info.infoLog  = getProgramInfoLog(m_gl, m_program);
 }
 
 bool Program::isSeparable (void) const
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
        int separable = GL_FALSE;
 
-       gl.getProgramiv(m_program, GL_PROGRAM_SEPARABLE, &separable);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
+       m_gl.getProgramiv(m_program, GL_PROGRAM_SEPARABLE, &separable);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetProgramiv()");
 
        return (separable != GL_FALSE);
 }
 
 void Program::setSeparable (bool separable)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.programParameteri(m_program, GL_PROGRAM_SEPARABLE, separable);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri()");
+       m_gl.programParameteri(m_program, GL_PROGRAM_SEPARABLE, separable);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glProgramParameteri()");
 }
 
 // ProgramPipeline
 
 ProgramPipeline::ProgramPipeline (const RenderContext& renderCtx)
-       : m_renderCtx   (renderCtx)
+       : m_gl                  (renderCtx.getFunctions())
        , m_pipeline    (0)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
+       m_gl.genProgramPipelines(1, &m_pipeline);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenProgramPipelines()");
+}
 
-       gl.genProgramPipelines(1, &m_pipeline);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines()");
+ProgramPipeline::ProgramPipeline (const glw::Functions& gl)
+       : m_gl                  (gl)
+       , m_pipeline    (0)
+{
+       m_gl.genProgramPipelines(1, &m_pipeline);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenProgramPipelines()");
 }
 
 ProgramPipeline::~ProgramPipeline (void)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-       gl.deleteProgramPipelines(1, &m_pipeline);
+       m_gl.deleteProgramPipelines(1, &m_pipeline);
 }
 
 void ProgramPipeline::useProgramStages (deUint32 stages, deUint32 program)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.useProgramStages(m_pipeline, stages, program);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages()");
+       m_gl.useProgramStages(m_pipeline, stages, program);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgramStages()");
 }
 
 void ProgramPipeline::activeShaderProgram (deUint32 program)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
-
-       gl.activeShaderProgram(m_pipeline, program);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram()");
+       m_gl.activeShaderProgram(m_pipeline, program);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glActiveShaderProgram()");
 }
 
 bool ProgramPipeline::isValid (void)
 {
-       const glw::Functions& gl = m_renderCtx.getFunctions();
        glw::GLint status = GL_FALSE;
-       gl.validateProgramPipeline(m_pipeline);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline()");
+       m_gl.validateProgramPipeline(m_pipeline);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glValidateProgramPipeline()");
 
-       gl.getProgramPipelineiv(m_pipeline, GL_VALIDATE_STATUS, &status);
+       m_gl.getProgramPipelineiv(m_pipeline, GL_VALIDATE_STATUS, &status);
 
        return (status != GL_FALSE);
 }
@@ -281,7 +273,18 @@ bool ProgramPipeline::isValid (void)
 // ShaderProgram
 
 ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramSources& sources)
-       : m_program(renderCtx)
+       : m_program(renderCtx.getFunctions())
+{
+       init(renderCtx.getFunctions(), sources);
+}
+
+ShaderProgram::ShaderProgram (const glw::Functions& gl, const ProgramSources& sources)
+       : m_program(gl)
+{
+       init(gl, sources);
+}
+
+void ShaderProgram::init (const glw::Functions& gl, const ProgramSources& sources)
 {
        try
        {
@@ -296,7 +299,7 @@ ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramSourc
 
                                m_shaders[shaderType].reserve(m_shaders[shaderType].size() + 1);
 
-                               m_shaders[shaderType].push_back(new Shader(renderCtx, ShaderType(shaderType)));
+                               m_shaders[shaderType].push_back(new Shader(gl, ShaderType(shaderType)));
                                m_shaders[shaderType].back()->setSources(1, &source, &length);
                                m_shaders[shaderType].back()->compile();
 
index ac62809271beadbe47d47c17c8c0ed9d59e6c7bd..8614eccbd551a4dce7a0d376413da429fc5283d1 100644 (file)
@@ -72,6 +72,7 @@ struct ProgramInfo
 class Shader
 {
 public:
+                                                       Shader                          (const glw::Functions& gl, ShaderType shaderType);
                                                        Shader                          (const RenderContext& renderCtx, ShaderType shaderType);
                                                        ~Shader                         (void);
 
@@ -92,7 +93,7 @@ private:
                                                        Shader                          (const Shader& other);
        Shader&                                 operator=                       (const Shader& other);
 
-       const RenderContext&    m_renderCtx;
+       const glw::Functions&   m_gl;
        deUint32                                m_shader;       //!< Shader handle.
        ShaderInfo                              m_info;         //!< Client-side clone of state for debug / perf reasons.
 };
@@ -103,6 +104,7 @@ private:
 class Program
 {
 public:
+                                                       Program                                         (const glw::Functions& gl);
                                                        Program                                         (const RenderContext& renderCtx);
                                                        Program                                         (const RenderContext& renderCtx, deUint32 program);
                                                        ~Program                                        (void);
@@ -132,7 +134,7 @@ private:
                                                        Program                                         (const Program& other);
        Program&                                operator=                                       (const Program& other);
 
-       const RenderContext&    m_renderCtx;
+       const glw::Functions&   m_gl;
        deUint32                                m_program;
        ProgramInfo                             m_info;
 };
@@ -145,6 +147,7 @@ class ProgramPipeline
 {
 public:
                                                        ProgramPipeline                         (const RenderContext& renderCtx);
+                                                       ProgramPipeline                         (const glw::Functions& gl);
                                                        ~ProgramPipeline                        (void);
 
        deUint32                                getPipeline                                     (void) const { return m_pipeline; }
@@ -156,7 +159,7 @@ private:
                                                        ProgramPipeline                         (const ProgramPipeline& other);
        ProgramPipeline&                operator=                                       (const ProgramPipeline& other);
 
-       const RenderContext&    m_renderCtx;
+       const glw::Functions&   m_gl;
        deUint32                                m_pipeline;
 };
 
@@ -171,6 +174,7 @@ struct ProgramSources;
 class ShaderProgram
 {
 public:
+                                                       ShaderProgram                           (const glw::Functions& gl, const ProgramSources& sources);
                                                        ShaderProgram                           (const RenderContext& renderCtx, const ProgramSources& sources);
                                                        ~ShaderProgram                          (void);
 
@@ -185,6 +189,7 @@ public:
 private:
                                                        ShaderProgram                           (const ShaderProgram& other);
        ShaderProgram&                  operator=                                       (const ShaderProgram& other);
+       void                                    init                                            (const glw::Functions& gl, const ProgramSources& sources);
 
        std::vector<Shader*>    m_shaders[SHADERTYPE_LAST];
        Program                                 m_program;
index f84618466a0d286e48618e308b357cfc0c973f5e..76d3d1a4d8464fc55021b52d872e207dfc5eab3b 100644 (file)
@@ -84,3 +84,6 @@ typedef void*                         GLeglImageOES;
 
 /* Callback for GL_ARB_debug_output. */
 typedef void (GLW_APIENTRY* GLDEBUGPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+
+/* OES_EGL_image */
+typedef void*                          GLeglImageOES;
index e5779df0ba1a6003a2c3495c5c0b3ea8282d27f1..92e3dd7a14ab49841fa5c38bc0dff52e4aa5a182 100644 (file)
@@ -29,6 +29,8 @@ set(DEQP_EGL_SRCS
        teglGLES1RenderUtil.hpp
        teglGLES2RenderUtil.cpp
        teglGLES2RenderUtil.hpp
+       teglImageUtil.cpp
+       teglImageUtil.hpp
        teglImageTests.cpp
        teglImageTests.hpp
        teglInfoTests.cpp
index b00e327e14983030b39b16bfd63cb8b11af19a66..fb093fc3f5d57f271f269439a00387892f749247 100644 (file)
@@ -22,6 +22,8 @@
  *//*--------------------------------------------------------------------*/
 #include "teglImageFormatTests.hpp"
 
+#include "deStringUtil.hpp"
+
 #include "tcuTestLog.hpp"
 #include "tcuSurface.hpp"
 #include "tcuTexture.hpp"
 #include "egluNativeWindow.hpp"
 #include "egluNativePixmap.hpp"
 #include "egluConfigFilter.hpp"
+#include "egluUnique.hpp"
 #include "egluUtil.hpp"
 
+#include "gluCallLogWrapper.hpp"
+#include "gluShaderProgram.hpp"
+#include "gluStrUtil.hpp"
 #include "gluTexture.hpp"
 #include "gluPixelTransfer.hpp"
+#include "gluObjectWrapper.hpp"
 #include "gluTextureUtil.hpp"
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <EGL/eglext.h>
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+
+#include "teglImageUtil.hpp"
 
 #include <vector>
 #include <string>
@@ -51,6 +59,19 @@ using std::vector;
 using std::set;
 using std::string;
 
+using de::MovePtr;
+using de::UniquePtr;
+
+using glu::Framebuffer;
+using glu::Renderbuffer;
+using glu::Texture;
+
+using eglu::UniqueImage;
+
+using tcu::ConstPixelBufferAccess;
+
+using namespace glw;
+
 namespace deqp
 {
 namespace egl
@@ -59,78 +80,20 @@ namespace egl
 namespace
 {
 
-// \todo [2013-04-09 pyry] Use glu::Program
-class Program
+glu::ProgramSources programSources (const string& vertexSource, const string& fragmentSource)
 {
-public:
-       Program (const char* vertexSource, const char* fragmentSource)
-               : m_program                     (0)
-               , m_vertexShader        (0)
-               , m_fragmentShader      (0)
-               , m_isOk                        (false)
-       {
-               m_program                       = glCreateProgram();
-               m_vertexShader          = glCreateShader(GL_VERTEX_SHADER);
-               m_fragmentShader        = glCreateShader(GL_FRAGMENT_SHADER);
-
-               try
-               {
-                       bool    vertexCompileOk         = false;
-                       bool    fragmentCompileOk       = false;
-                       bool    linkOk                          = false;
-
-                       for (int ndx = 0; ndx < 2; ndx++)
-                       {
-                               const char*             source                  = ndx ? fragmentSource          : vertexSource;
-                               const deUint32  shader                  = ndx ? m_fragmentShader        : m_vertexShader;
-                               int                             compileStatus   = 0;
-                               bool&                   compileOk               = ndx ? fragmentCompileOk       : vertexCompileOk;
-
-                               glShaderSource(shader, 1, &source, DE_NULL);
-                               glCompileShader(shader);
-                               glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
+       glu::ProgramSources sources;
 
-                               compileOk = (compileStatus == GL_TRUE);
-                       }
-
-                       if (vertexCompileOk && fragmentCompileOk)
-                       {
-                               int linkStatus = 0;
-
-                               glAttachShader(m_program, m_vertexShader);
-                               glAttachShader(m_program, m_fragmentShader);
-                               glLinkProgram(m_program);
-                               glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus);
-
-                               linkOk = (linkStatus == GL_TRUE);
-                       }
-
-                       m_isOk = linkOk;
-               }
-               catch (...)
-               {
-                       glDeleteShader(m_vertexShader);
-                       glDeleteShader(m_fragmentShader);
-                       glDeleteProgram(m_program);
-                       throw;
-               }
-       }
-
-       ~Program (void)
-       {
-               glDeleteShader(m_vertexShader);
-               glDeleteShader(m_fragmentShader);
-               glDeleteProgram(m_program);
-       }
+       sources << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource);
 
-       bool                    isOk                    (void) const { return m_isOk;   }
-       deUint32                getProgram              (void) const {return m_program; }
+       return sources;
+}
 
-private:
-       deUint32                m_program;
-       deUint32                m_vertexShader;
-       deUint32                m_fragmentShader;
-       bool                    m_isOk;
+class Program : public glu::ShaderProgram
+{
+public:
+       Program (const glw::Functions& gl, const char* vertexSource, const char* fragmentSource)
+               : glu::ShaderProgram(gl, programSources(vertexSource, fragmentSource)) {}
 };
 
 } // anonymous
@@ -138,25 +101,14 @@ private:
 namespace Image
 {
 
-class EglExt
+class ImageApi;
+
+class Action
 {
 public:
-       EglExt (void)
-       {
-               eglCreateImageKHR                                               = (PFNEGLCREATEIMAGEKHRPROC)                                            eglGetProcAddress("eglCreateImageKHR");
-               eglDestroyImageKHR                                              = (PFNEGLDESTROYIMAGEKHRPROC)                                           eglGetProcAddress("eglDestroyImageKHR");
-
-               glEGLImageTargetTexture2DOES                    = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)                         eglGetProcAddress("glEGLImageTargetTexture2DOES");
-               glEGLImageTargetRenderbufferStorageOES  = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)       eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
-       }
-
-       PFNEGLCREATEIMAGEKHRPROC                                                eglCreateImageKHR;
-       PFNEGLDESTROYIMAGEKHRPROC                                               eglDestroyImageKHR;
-
-       PFNGLEGLIMAGETARGETTEXTURE2DOESPROC                             glEGLImageTargetTexture2DOES;
-       PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC   glEGLImageTargetRenderbufferStorageOES;
-
-private:
+       virtual                 ~Action                                 (void) {}
+       virtual bool    invoke                                  (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& refImg) const = 0;
+       virtual string  getRequiredExtension    (void) const = 0;
 };
 
 struct TestSpec
@@ -175,19 +127,9 @@ struct TestSpec
 
        struct Operation
        {
-               enum Type
-               {
-                               TYPE_CREATE = 0,
-                               TYPE_RENDER,
-                               TYPE_MODIFY,
-
-                               TYPE_LAST
-               };
-
-               ApiContext      requiredApi;
-               int                     apiIndex;
-               Type            type;
-               int                     operationIndex;
+               Operation (int apiIndex_, const Action& action_) : apiIndex(apiIndex_), action(&action_) {}
+               int                             apiIndex;
+               const Action*   action;
        };
 
        vector<ApiContext>      contexts;
@@ -198,130 +140,131 @@ struct TestSpec
 class ImageApi
 {
 public:
-                                                       ImageApi                                (int contextId, tcu::TestLog& log, tcu::egl::Display& display, tcu::egl::Surface* surface);
+                                                       ImageApi                                (int contextId, tcu::egl::Display& display, tcu::egl::Surface* surface);
        virtual                                 ~ImageApi                               (void) {}
 
-       virtual EGLImageKHR             create                                  (int operationNdx, tcu::Texture2D& ref) = 0;
-       virtual bool                    render                                  (int operationNdx, EGLImageKHR img, const tcu::Texture2D& reference) = 0;
-       virtual void                    modify                                  (int operationNdx, EGLImageKHR img, tcu::Texture2D& reference) = 0;
-
-       virtual void                    checkRequiredExtensions (set<string>& extensions, TestSpec::Operation::Type type, int operationNdx) = 0;
-
 protected:
        int                                             m_contextId;
-       tcu::TestLog&                   m_log;
        tcu::egl::Display&              m_display;
        tcu::egl::Surface*              m_surface;
 };
 
-ImageApi::ImageApi (int contextId, tcu::TestLog& log, tcu::egl::Display& display, tcu::egl::Surface* surface)
+ImageApi::ImageApi (int contextId, tcu::egl::Display& display, tcu::egl::Surface* surface)
        : m_contextId           (contextId)
-       , m_log                         (log)
        , m_display                     (display)
        , m_surface                     (surface)
 {
 }
 
-class GLES2ImageApi : public ImageApi
+class GLES2ImageApi : public ImageApi, private glu::CallLogWrapper
 {
 public:
-       enum Create
+       class GLES2Action : public Action
        {
-               CREATE_TEXTURE2D_RGB8 = 0,
-               CREATE_TEXTURE2D_RGB565,
-               CREATE_TEXTURE2D_RGBA8,
-               CREATE_TEXTURE2D_RGBA5_A1,
-               CREATE_TEXTURE2D_RGBA4,
-
-               CREATE_CUBE_MAP_POSITIVE_X_RGBA8,
-               CREATE_CUBE_MAP_NEGATIVE_X_RGBA8,
-               CREATE_CUBE_MAP_POSITIVE_Y_RGBA8,
-               CREATE_CUBE_MAP_NEGATIVE_Y_RGBA8,
-               CREATE_CUBE_MAP_POSITIVE_Z_RGBA8,
-               CREATE_CUBE_MAP_NEGATIVE_Z_RGBA8,
-
-               CREATE_CUBE_MAP_POSITIVE_X_RGB8,
-               CREATE_CUBE_MAP_NEGATIVE_X_RGB8,
-               CREATE_CUBE_MAP_POSITIVE_Y_RGB8,
-               CREATE_CUBE_MAP_NEGATIVE_Y_RGB8,
-               CREATE_CUBE_MAP_POSITIVE_Z_RGB8,
-               CREATE_CUBE_MAP_NEGATIVE_Z_RGB8,
-
-               CREATE_RENDER_BUFFER_DEPTH16,
-               CREATE_RENDER_BUFFER_RGBA4,
-               CREATE_RENDER_BUFFER_RGB5_A1,
-               CREATE_RENDER_BUFFER_RGB565,
-               CREATE_RENDER_BUFFER_STENCIL,
-
-               CREATE_LAST
+       public:
+               bool                            invoke                                  (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
+               virtual bool            invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const = 0;
        };
 
-       enum Render
+       class Create : public GLES2Action
        {
-               RENDER_TEXTURE2D = 0,
+       public:
+                                                               Create                                  (MovePtr<ImageSource> imgSource) : m_imgSource(imgSource) {}
+               string                                  getRequiredExtension    (void) const { return m_imgSource->getRequiredExtension(); }
+               bool                                    invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
+
+       private:
+               UniquePtr<ImageSource>  m_imgSource;
+       };
+
+       class Render : public GLES2Action
+       {
+       public:
+               string                          getRequiredExtension    (void) const { return "GL_OES_EGL_image"; }
+       };
 
-               // \note Not supported
-               RENDER_CUBE_MAP_POSITIVE_X,
-               RENDER_CUBE_MAP_NEGATIVE_X,
-               RENDER_CUBE_MAP_POSITIVE_Y,
-               RENDER_CUBE_MAP_NEGATIVE_Y,
-               RENDER_CUBE_MAP_POSITIVE_Z,
-               RENDER_CUBE_MAP_NEGATIVE_Z,
+       class RenderTexture2D                           : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
+       class RenderTextureCubemap                      : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
+       class RenderReadPixelsRenderbuffer      : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
+       class RenderDepthbuffer                         : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
+       class RenderTryAll                                      : public Render { public: bool invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const; };
 
-               RENDER_READ_PIXELS_RENDERBUFFER,
-               RENDER_DEPTHBUFFER,
+       class Modify : public GLES2Action
+       {
+       public:
+               string                          getRequiredExtension    (void) const { return "GL_OES_EGL_image"; }
+       };
 
-               RENDER_TRY_ALL,
+       class ModifyTexSubImage : public Modify
+       {
+       public:
+                                                       ModifyTexSubImage               (GLenum format, GLenum type) : m_format(format), m_type(type) {}
+               bool                            invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
 
-               RENDER_LAST
+       private:
+               GLenum                          m_format;
+               GLenum                          m_type;
        };
 
-       enum Modify
+       class ModifyRenderbuffer : public Modify
        {
-               MODIFY_TEXSUBIMAGE_RGBA8,
-               MODIFY_TEXSUBIMAGE_RGBA5_A1,
-               MODIFY_TEXSUBIMAGE_RGBA4,
-               MODIFY_TEXSUBIMAGE_RGB8,
-               MODIFY_TEXSUBIMAGE_RGB565,
-               MODIFY_RENDERBUFFER_CLEAR_COLOR,
-               MODIFY_RENDERBUFFER_CLEAR_DEPTH,
-               MODIFY_RENDERBUFFER_CLEAR_STENCIL,
-
-               MODIFY_LAST
+       public:
+               bool                            invokeGLES2                             (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const;
+
+       protected:
+               virtual void            initializeRbo                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const = 0;
        };
 
-                                       GLES2ImageApi                                   (int contextId, tcu::TestLog& log, tcu::egl::Display& display, tcu::egl::Surface* surface, EGLConfig config);
-                                       ~GLES2ImageApi                                  (void);
+       class ModifyRenderbufferClearColor : public ModifyRenderbuffer
+       {
+       public:
+                                       ModifyRenderbufferClearColor    (tcu::Vec4 color) : m_color(color) {}
+
+       protected:
+               void            initializeRbo                                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
 
-       EGLImageKHR             create                                                  (int operationNdx, tcu::Texture2D& ref);
-       EGLImageKHR             createTexture2D                                 (tcu::Texture2D& ref, GLenum target, GLenum format, GLenum type);
-       EGLImageKHR             createRenderBuffer                              (tcu::Texture2D& ref, GLenum type);
+               tcu::Vec4       m_color;
+       };
+
+       class ModifyRenderbufferClearDepth : public ModifyRenderbuffer
+       {
+       public:
+                                       ModifyRenderbufferClearDepth    (GLfloat depth) : m_depth(depth) {}
+
+       protected:
+               void            initializeRbo                                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
 
-       bool                    render                                                  (int operationNdx, EGLImageKHR img, const tcu::Texture2D& reference);
-       bool                    renderTexture2D                                 (EGLImageKHR img, const tcu::Texture2D& reference);
-       bool                    renderDepth                                             (EGLImageKHR img, const tcu::Texture2D& reference);
-       bool                    renderReadPixelsRenderBuffer    (EGLImageKHR img, const tcu::Texture2D& reference);
-       bool                    renderTryAll                                    (EGLImageKHR img, const tcu::Texture2D& reference);
+               GLfloat         m_depth;
+       };
 
-       // \note Not supported
-       bool                    renderCubeMap                                   (EGLImageKHR img, const tcu::Surface& reference, GLenum face);
+       class ModifyRenderbufferClearStencil : public ModifyRenderbuffer
+       {
+       public:
+                                       ModifyRenderbufferClearStencil  (GLint stencil) : m_stencil(stencil) {}
 
-       void                    modify                                                  (int operationNdx, EGLImageKHR img, tcu::Texture2D& reference);
-       void                    modifyTexSubImage                               (EGLImageKHR img, tcu::Texture2D& reference, GLenum format, GLenum type);
-       void                    modifyRenderbufferClearColor    (EGLImageKHR img, tcu::Texture2D& reference);
-       void                    modifyRenderbufferClearDepth    (EGLImageKHR img, tcu::Texture2D& reference);
-       void                    modifyRenderbufferClearStencil  (EGLImageKHR img, tcu::Texture2D& reference);
+       protected:
+               void            initializeRbo                                   (GLES2ImageApi& api, GLuint rbo, tcu::Texture2D& ref) const;
 
-       void                    checkRequiredExtensions                 (set<string>& extensions, TestSpec::Operation::Type type, int operationNdx);
+               GLint           m_stencil;
+       };
+
+                                       GLES2ImageApi                                   (const glw::Functions& gl, int contextId, tcu::TestLog& log, tcu::egl::Display& display, tcu::egl::Surface* surface, EGLConfig config);
+                                       ~GLES2ImageApi                                  (void);
 
 private:
-       tcu::egl::Context*      m_context;
-       EglExt                          m_eglExt;
+       tcu::egl::Context*                      m_context;
+       const glw::Functions&           m_gl;
+       const eglu::ImageFunctions      m_imgExt;
+
+       MovePtr<UniqueImage>            createImage                     (const ImageSource& source, const ClientBuffer& buffer) const;
 };
 
-GLES2ImageApi::GLES2ImageApi (int contextId, tcu::TestLog& log, tcu::egl::Display& display, tcu::egl::Surface* surface, EGLConfig config)
-       : ImageApi      (contextId, log, display, surface)
-       , m_context     (DE_NULL)
+GLES2ImageApi::GLES2ImageApi (const glw::Functions& gl, int contextId, tcu::TestLog& log, tcu::egl::Display& display, tcu::egl::Surface* surface, EGLConfig config)
+       : ImageApi                              (contextId, display, surface)
+       , glu::CallLogWrapper   (gl, log)
+       , m_context                             (DE_NULL)
+       , m_gl                                  (gl)
+       , m_imgExt                              (eglu::getImageFunctions(display.getEGLDisplay()))
 {
        EGLint attriblist[] =
        {
@@ -331,7 +274,7 @@ GLES2ImageApi::GLES2ImageApi (int contextId, tcu::TestLog& log, tcu::egl::Displa
 
        EGLint configId = -1;
        TCU_CHECK_EGL_CALL(eglGetConfigAttrib(m_display.getEGLDisplay(), config, EGL_CONFIG_ID, &configId));
-       m_log << tcu::TestLog::Message << "Creating gles2 context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage;
+       getLog() << tcu::TestLog::Message << "Creating gles2 context with config id: " << configId << " context: " << m_contextId << tcu::TestLog::EndMessage;
        m_context = new tcu::egl::Context(m_display, config, attriblist, EGL_OPENGL_ES_API);
        TCU_CHECK_EGL_MSG("Failed to create GLES2 context");
 
@@ -344,398 +287,96 @@ GLES2ImageApi::~GLES2ImageApi (void)
        delete m_context;
 }
 
-EGLImageKHR GLES2ImageApi::create (int operationNdx, tcu::Texture2D& ref)
+bool GLES2ImageApi::GLES2Action::invoke (ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
 {
-       m_context->makeCurrent(*m_surface, *m_surface);
-       EGLImageKHR     img = EGL_NO_IMAGE_KHR;
-       switch (operationNdx)
-       {
-               case CREATE_TEXTURE2D_RGB8:                             img = createTexture2D(ref, GL_TEXTURE_2D, GL_RGB,       GL_UNSIGNED_BYTE);                      break;
-               case CREATE_TEXTURE2D_RGB565:                   img = createTexture2D(ref, GL_TEXTURE_2D, GL_RGB,       GL_UNSIGNED_SHORT_5_6_5);       break;
-               case CREATE_TEXTURE2D_RGBA8:                    img = createTexture2D(ref, GL_TEXTURE_2D, GL_RGBA,      GL_UNSIGNED_BYTE);                      break;
-               case CREATE_TEXTURE2D_RGBA4:                    img = createTexture2D(ref, GL_TEXTURE_2D, GL_RGBA,      GL_UNSIGNED_SHORT_4_4_4_4);     break;
-               case CREATE_TEXTURE2D_RGBA5_A1:                 img = createTexture2D(ref, GL_TEXTURE_2D, GL_RGBA,      GL_UNSIGNED_SHORT_5_5_5_1);     break;
-
-               case CREATE_CUBE_MAP_POSITIVE_X_RGBA8:  img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_RGBA, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_NEGATIVE_X_RGBA8:  img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_RGBA, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_POSITIVE_Y_RGBA8:  img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_RGBA, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_NEGATIVE_Y_RGBA8:  img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_RGBA, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_POSITIVE_Z_RGBA8:  img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_RGBA, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_NEGATIVE_Z_RGBA8:  img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_RGBA, GL_UNSIGNED_BYTE); break;
-
-               case CREATE_CUBE_MAP_POSITIVE_X_RGB8:   img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_RGB, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_NEGATIVE_X_RGB8:   img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_RGB, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_POSITIVE_Y_RGB8:   img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_RGB, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_NEGATIVE_Y_RGB8:   img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_RGB, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_POSITIVE_Z_RGB8:   img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_RGB, GL_UNSIGNED_BYTE); break;
-               case CREATE_CUBE_MAP_NEGATIVE_Z_RGB8:   img = createTexture2D(ref, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_RGB, GL_UNSIGNED_BYTE); break;
-
-               case CREATE_RENDER_BUFFER_DEPTH16:              img = createRenderBuffer(ref, GL_DEPTH_COMPONENT16);    break;
-               case CREATE_RENDER_BUFFER_RGBA4:                img = createRenderBuffer(ref, GL_RGBA4);                                break;
-               case CREATE_RENDER_BUFFER_RGB5_A1:              img = createRenderBuffer(ref, GL_RGB5_A1);                              break;
-               case CREATE_RENDER_BUFFER_RGB565:               img = createRenderBuffer(ref, GL_RGB565);                               break;
-               case CREATE_RENDER_BUFFER_STENCIL:              img = createRenderBuffer(ref, GL_STENCIL_INDEX8);               break;
-
-               default:
-                       DE_ASSERT(false);
-                       break;
-       }
+       GLES2ImageApi& gles2Api = dynamic_cast<GLES2ImageApi&>(api);
 
-       return img;
+       gles2Api.m_context->makeCurrent(*gles2Api.m_surface, *gles2Api.m_surface);
+       return invokeGLES2(gles2Api, image, ref);
 }
 
-namespace
-{
 
-const char* glTargetToString (GLenum target)
+bool GLES2ImageApi::Create::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& image, tcu::Texture2D& ref) const
 {
-       switch (target)
-       {
-               case GL_TEXTURE_2D: return "GL_TEXTURE_2D";
-               break;
-               case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return "GL_TEXTURE_CUBE_MAP_POSITIVE_X";
-               break;
-               case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X";
-               break;
-               case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y";
-               break;
-               case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y";
-               break;
-               case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z";
-               break;
-               case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z";
-               break;
-               default:
-                       DE_ASSERT(false);
-               break;
-       };
-       return "";
+       de::UniquePtr<ClientBuffer>     buffer  (m_imgSource->createBuffer(api.m_gl, &ref));
+       image = api.createImage(*m_imgSource, *buffer);
+       return true;
 }
 
-const char* glFormatToString (GLenum format)
+MovePtr<UniqueImage> GLES2ImageApi::createImage (const ImageSource& source, const ClientBuffer& buffer) const
 {
-       switch (format)
-       {
-               case GL_RGB:
-                       return "GL_RGB";
-
-               case GL_RGBA:
-                       return "GL_RGBA";
-
-               default:
-                       DE_ASSERT(false);
-                       return "";
-       }
+       const EGLImageKHR image = source.createImage(m_imgExt, m_display.getEGLDisplay(), m_context->getEGLContext(), buffer.get());
+       return MovePtr<UniqueImage>(new UniqueImage(m_display.getEGLDisplay(), image, m_imgExt));
 }
 
-const char* glTypeToString (GLenum type)
+static void imageTargetTexture2D (const glw::Functions& gl, GLeglImageOES img)
 {
-       switch (type)
+       gl.eglImageTargetTexture2DOES(GL_TEXTURE_2D, img);
        {
-               case GL_UNSIGNED_BYTE:
-                       return "GL_UNSIGNED_BYTE";
-
-               case GL_UNSIGNED_SHORT_5_6_5:
-                       return "GL_UNSIGNED_SHORT_5_6_5";
+               const GLenum error = gl.getError();
 
-               case GL_UNSIGNED_SHORT_4_4_4_4:
-                       return "GL_UNSIGNED_SHORT_4_4_4_4";
+               if (error == GL_INVALID_OPERATION)
+                       TCU_THROW(NotSupportedError, "Creating texture2D from EGLImage type not supported");
 
-               case GL_UNSIGNED_SHORT_5_5_5_1:
-                       return "GL_UNSIGNED_SHORT_5_5_5_1";
-
-               default:
-                       DE_ASSERT(false);
-                       return "";
+               GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetTexture2DOES()");
+               EGLU_CHECK_MSG("glEGLImageTargetTexture2DOES()");
        }
 }
 
-} // anonymous
-
-EGLImageKHR    GLES2ImageApi::createTexture2D (tcu::Texture2D& reference, GLenum target, GLenum format, GLenum type)
+static void imageTargetRenderbuffer (const glw::Functions& gl, GLeglImageOES img)
 {
-       tcu::Texture2D src(glu::mapGLTransferFormat(format, type), 64, 64);
-       src.allocLevel(0);
-
-       tcu::fillWithComponentGradients(src.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
-       m_log << tcu::TestLog::Message << "Creating EGLImage from " << glTargetToString(target) << " " << glFormatToString(format) << " " << glTypeToString(type) << " in context: " << m_contextId << tcu::TestLog::EndMessage;
-
-       deUint32 srcTex = 0;
-       glGenTextures(1, &srcTex);
-       TCU_CHECK(srcTex != 0);
-       if (GL_TEXTURE_2D == target)
+       gl.eglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, img);
        {
-               GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, format, src.getWidth(), src.getHeight(), 0, format, type, src.getLevel(0).getDataPtr()));
-       }
-       else
-       {
-               GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-               GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
-
-               // First fill all faces, required by eglCreateImageKHR
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format, src.getWidth(), src.getHeight(), 0, format, type, 0));
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format, src.getWidth(), src.getHeight(), 0, format, type, 0));
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format, src.getWidth(), src.getHeight(), 0, format, type, 0));
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format, src.getWidth(), src.getHeight(), 0, format, type, 0));
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format, src.getWidth(), src.getHeight(), 0, format, type, 0));
-               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format, src.getWidth(), src.getHeight(), 0, format, type, 0));
-               GLU_CHECK_CALL(glTexImage2D(target, 0, format, src.getWidth(), src.getHeight(), 0, format, type, src.getLevel(0).getDataPtr()));
-       }
+               const GLenum error = gl.getError();
 
-       EGLint attrib[] = {
-               EGL_GL_TEXTURE_LEVEL_KHR, 0,
-               EGL_NONE
-       };
+               if (error == GL_INVALID_OPERATION)
+                       TCU_THROW(NotSupportedError, "Creating renderbuffer from EGLImage type not supported");
 
-       EGLImageKHR img = EGL_NO_IMAGE_KHR;
-
-       if (GL_TEXTURE_2D == target)
-       {
-               img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib);
+               GLU_EXPECT_NO_ERROR(error, "glEGLImageTargetRenderbufferStorageOES()");
+               EGLU_CHECK_MSG("glEGLImageTargetRenderbufferStorageOES()");
        }
-       else
-       {
-               switch (target)
-               {
-                       case GL_TEXTURE_CUBE_MAP_POSITIVE_X: img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib); break;
-                       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib); break;
-                       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib); break;
-                       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib); break;
-                       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib); break;
-                       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, (EGLClientBuffer)(deUintptr)srcTex, attrib); break;
-
-                       default:
-                               DE_ASSERT(false);
-                               break;
-               }
-       }
-
-       GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
-       TCU_CHECK_EGL_MSG("Failed to create EGLImage");
-       TCU_CHECK_MSG(img != EGL_NO_IMAGE_KHR, "Failed to create EGLImage, got EGL_NO_IMAGE_KHR");
-       glBindTexture(GL_TEXTURE_2D, 0);
-
-       reference = src;
-
-       return img;
 }
 
-static std::string glRenderbufferTargetToString (GLenum format)
+static void framebufferRenderbuffer (const glw::Functions& gl, GLenum attachment, GLuint rbo)
 {
-       switch (format)
-       {
-               case GL_RGBA4:
-                       return "GL_RGBA4";
-                       break;
-
-               case GL_RGB5_A1:
-                       return "GL_RGB5_A1";
-                       break;
-
-               case GL_RGB565:
-                       return "GL_RGB565";
-                       break;
-
-               case GL_DEPTH_COMPONENT16:
-                       return "GL_DEPTH_COMPONENT16";
-                       break;
-
-               case GL_STENCIL_INDEX8:
-                       return "GL_STENCIL_INDEX8";
-                       break;
-
-               default:
-                       DE_ASSERT(false);
-                       break;
-       }
-
-       DE_ASSERT(false);
-       return "";
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rbo));
+       TCU_CHECK_AND_THROW(NotSupportedError,
+                                               gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
+                                               ("EGLImage as " + string(glu::getFramebufferAttachmentName(attachment)) + " not supported").c_str());
 }
 
-EGLImageKHR GLES2ImageApi::createRenderBuffer (tcu::Texture2D& ref, GLenum format)
+static const float squareTriangleCoords[] =
 {
-       m_log << tcu::TestLog::Message << "Creating EGLImage from GL_RENDERBUFFER " << glRenderbufferTargetToString(format) << " " << " in context: " << m_contextId << tcu::TestLog::EndMessage;
-       GLuint renderBuffer = 1;
-
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer));
-       GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, format, 64, 64));
+       -1.0, -1.0,
+       1.0, -1.0,
+       1.0,  1.0,
 
-       GLuint frameBuffer = 1;
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer));
-
-       switch (format)
-       {
-               case GL_STENCIL_INDEX8:
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer));
-                       TCU_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-                       GLU_CHECK_CALL(glClearStencil(235));
-                       GLU_CHECK_CALL(glClear(GL_STENCIL_BUFFER_BIT));
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0));
-                       ref = tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::I, tcu::TextureFormat::UNORM_INT8),  64, 64);
-                       ref.allocLevel(0);
-
-                       for (int x = 0; x < 64; x++)
-                       {
-                               for (int y = 0; y < 64; y++)
-                               {
-                                       ref.getLevel(0).setPixel(tcu::IVec4(235, 235, 235, 235), x, y);
-                               }
-                       }
-                       break;
-
-               case GL_DEPTH_COMPONENT16:
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer));
-                       TCU_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-                       GLU_CHECK_CALL(glClearDepthf(0.5f));
-                       GLU_CHECK_CALL(glClear(GL_DEPTH_BUFFER_BIT));
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0));
-                       ref = tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::I, tcu::TextureFormat::UNORM_INT16),  64, 64);
-                       ref.allocLevel(0);
-
-                       for (int x = 0; x < 64; x++)
-                       {
-                               for (int y = 0; y < 64; y++)
-                               {
-                                       ref.getLevel(0).setPixel(tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f), x, y);
-                               }
-                       }
-                       break;
-
-               case GL_RGBA4:
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer));
-                       TCU_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-                       GLU_CHECK_CALL(glClearColor(0.9f, 0.5f, 0.65f, 1.0f));
-                       GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0));
-                       ref = tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_4444),  64, 64);
-                       ref.allocLevel(0);
-
-                       for (int x = 0; x < 64; x++)
-                       {
-                               for (int y = 0; y < 64; y++)
-                               {
-                                       ref.getLevel(0).setPixel(tcu::Vec4(0.9f, 0.5f, 0.65f, 1.0f), x, y);
-                               }
-                       }
-                       break;
-
-               case GL_RGB5_A1:
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer));
-                       TCU_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-                       GLU_CHECK_CALL(glClearColor(0.5f, 0.7f, 0.65f, 1.0f));
-                       GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0));
-                       ref = tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_5551),  64, 64);
-                       ref.allocLevel(0);
-
-                       for (int x = 0; x < 64; x++)
-                       {
-                               for (int y = 0; y < 64; y++)
-                               {
-                                       ref.getLevel(0).setPixel(tcu::Vec4(0.5f, 0.7f, 0.65f, 1.0f), x, y);
-                               }
-                       }
-                       break;
-
-               case GL_RGB565:
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer));
-                       TCU_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
-                       GLU_CHECK_CALL(glClearColor(0.2f, 0.5f, 0.65f, 1.0f));
-                       GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
-                       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0));
-                       ref = tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_SHORT_565),  64, 64);
-                       ref.allocLevel(0);
-
-                       for (int x = 0; x < 64; x++)
-                       {
-                               for (int y = 0; y < 64; y++)
-                               {
-                                       ref.getLevel(0).setPixel(tcu::Vec4(0.2f, 0.5f, 0.65f, 1.0f), x, y);
-                               }
-                       }
-                       break;
-
-               default:
-                       DE_ASSERT(false);
-       }
-
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-       GLU_CHECK_CALL(glDeleteFramebuffers(1, &frameBuffer));
-
-       EGLint attrib[] = {
-               EGL_NONE
-       };
-
-       EGLImageKHR img = m_eglExt.eglCreateImageKHR(m_display.getEGLDisplay(), m_context->getEGLContext(), EGL_GL_RENDERBUFFER_KHR, (EGLClientBuffer)(deUintptr)renderBuffer, attrib);
-
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderBuffer));
-       return img;
-}
+       1.0,  1.0,
+       -1.0,  1.0,
+       -1.0, -1.0
+};
 
-bool GLES2ImageApi::render (int operationNdx, EGLImageKHR img, const tcu::Texture2D& reference)
+bool GLES2ImageApi::RenderTexture2D::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
-       m_context->makeCurrent(*m_surface, *m_surface);
-       switch (operationNdx)
-       {
-               case RENDER_TEXTURE2D:
-                       return renderTexture2D(img, reference);
-
-               case RENDER_READ_PIXELS_RENDERBUFFER:
-                       return renderReadPixelsRenderBuffer(img, reference);
-
-               case RENDER_DEPTHBUFFER:
-                       return renderDepth(img, reference);
-
-               case RENDER_TRY_ALL:
-                       return renderTryAll(img, reference);
-
-               default:
-                       DE_ASSERT(false);
-                       break;
-       };
-       return false;
-}
+       const glw::Functions&   gl              = api.m_gl;
+       tcu::TestLog&                   log             = api.getLog();
+       Texture                                 srcTex  (gl);
 
-bool GLES2ImageApi::renderTexture2D (EGLImageKHR img, const tcu::Texture2D& reference)
-{
-       glClearColor(0.0, 0.0, 0.0, 0.0);
-       glViewport(0, 0, reference.getWidth(), reference.getHeight());
-       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-       glDisable(GL_DEPTH_TEST);
-
-       m_log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << m_contextId << tcu::TestLog::EndMessage;
-       TCU_CHECK(img != EGL_NO_IMAGE_KHR);
-
-       deUint32 srcTex = 0;
-       glGenTextures(1, &srcTex);
-       TCU_CHECK(srcTex != 0);
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
-       m_eglExt.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)img);
-       GLenum error = glGetError();
-
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
-               throw tcu::NotSupportedError("Creating texture2D from EGLImage type not supported", "glEGLImageTargetTexture2DOES", __FILE__, __LINE__);
-       }
+       gl.clearColor(0.0, 0.0, 0.0, 0.0);
+       gl.viewport(0, 0, reference.getWidth(), reference.getHeight());
+       gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+       gl.disable(GL_DEPTH_TEST);
 
-       TCU_CHECK(error == GL_NONE);
+       log << tcu::TestLog::Message << "Rendering EGLImage as GL_TEXTURE_2D in context: " << api.m_contextId << tcu::TestLog::EndMessage;
+       TCU_CHECK(**img != EGL_NO_IMAGE_KHR);
 
-       TCU_CHECK_EGL_MSG("glEGLImageTargetTexture2DOES() failed");
+       GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
+       imageTargetTexture2D(gl, **img);
 
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+       GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+       GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+       GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+       GLU_CHECK_GLW_CALL(gl, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
 
        const char* vertexShader =
                "attribute highp vec2 a_coord;\n"
@@ -753,111 +394,60 @@ bool GLES2ImageApi::renderTexture2D (EGLImageKHR img, const tcu::Texture2D& refe
                "\tgl_FragColor = vec4(texColor);\n"
                "}";
 
-       Program program(vertexShader, fragmentShader);
+       Program program(gl, vertexShader, fragmentShader);
        TCU_CHECK(program.isOk());
 
        GLuint glProgram = program.getProgram();
-       GLU_CHECK_CALL(glUseProgram(glProgram));
+       GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
 
-       GLuint coordLoc = glGetAttribLocation(glProgram, "a_coord");
+       GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
        TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
 
-       GLuint samplerLoc = glGetUniformLocation(glProgram, "u_sampler");
+       GLuint samplerLoc = gl.getUniformLocation(glProgram, "u_sampler");
        TCU_CHECK_MSG((int)samplerLoc != (int)-1, "Couldn't find uniform u_sampler");
 
-       float coords[] =
-       {
-               -1.0, -1.0,
-               1.0, -1.0,
-               1.0,  1.0,
-
-               1.0,  1.0,
-               -1.0,  1.0,
-               -1.0, -1.0
-       };
-
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
-       GLU_CHECK_CALL(glUniform1i(samplerLoc, 0));
-       GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
-       GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords));
+       GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
+       GLU_CHECK_GLW_CALL(gl, uniform1i(samplerLoc, 0));
+       GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
+       GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
 
-       GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
-       GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, 0));
-       GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
+       GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(squareTriangleCoords)));
+       GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
+       GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
 
-       tcu::Surface screen(reference.getWidth(), reference.getHeight());
-       glReadPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
-       GLU_CHECK_MSG("glReadPixels()");
+       tcu::Surface refSurface (reference.getWidth(), reference.getHeight());
+       tcu::Surface screen             (reference.getWidth(), reference.getHeight());
+       GLU_CHECK_GLW_CALL(gl, readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr()));
 
-       tcu::Surface referenceScreen(reference.getWidth(), reference.getHeight());
-
-       for (int y = 0; y < referenceScreen.getHeight(); y++)
-       {
-               for (int x = 0; x < referenceScreen.getWidth(); x++)
-               {
-                       tcu::Vec4 src = reference.getLevel(0).getPixel(x, y);
-                       referenceScreen.setPixel(x, y, tcu::RGBA(src));
-               }
-       }
+       tcu::copy(refSurface.getAccess(), reference.getLevel(0));
 
        float   threshold       = 0.05f;
-       bool    match           = tcu::fuzzyCompare(m_log, "ComparisonResult", "Image comparison result", referenceScreen, screen, threshold, tcu::COMPARE_LOG_RESULT);
+       bool    match           = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refSurface, screen, threshold, tcu::COMPARE_LOG_RESULT);
 
        return match;
 }
 
-bool GLES2ImageApi::renderDepth (EGLImageKHR img, const tcu::Texture2D& reference)
+bool GLES2ImageApi::RenderDepthbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
-       m_log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage;
-
-       deUint32 framebuffer;
-       glGenFramebuffers(1, &framebuffer);
-       TCU_CHECK(framebuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
+       const glw::Functions&   gl                                      = api.m_gl;
+       tcu::TestLog&                   log                                     = api.getLog();
+       Framebuffer                             framebuffer                     (gl);
+       Renderbuffer                    renderbufferColor       (gl);
+       Renderbuffer                    renderbufferDepth       (gl);
+       log << tcu::TestLog::Message << "Rendering with depth buffer" << tcu::TestLog::EndMessage;
 
-       deUint32 renderbufferColor = 0;
-       glGenRenderbuffers(1, &renderbufferColor);
-       TCU_CHECK(renderbufferColor != (GLuint)-1);
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferColor));
-       GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+       GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
 
-       deUint32 renderbufferDepth = 0;
-       glGenRenderbuffers(1, &renderbufferDepth);
-       TCU_CHECK(renderbufferDepth != (GLuint)-1);
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferDepth));
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferColor));
+       GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, reference.getWidth(), reference.getHeight()));
+       framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbufferColor);
 
-       m_eglExt.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)img);
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbufferDepth));
+       imageTargetRenderbuffer(gl, **img);
+       framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, *renderbufferDepth);
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
 
-       GLenum error = glGetError();
-
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbufferDepth));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbufferColor));
-               throw tcu::NotSupportedError("Creating renderbuffer from EGLImage type not supported", "glEGLImageTargetRenderbufferStorageOES", __FILE__, __LINE__);
-       }
-
-       TCU_CHECK(error == GL_NONE);
-
-       TCU_CHECK_EGL_MSG("glEGLImageTargetRenderbufferStorageOES() failed");
-
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferDepth));
-       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferDepth));
-
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferColor));
-       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferColor));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-
-       GLU_CHECK_CALL(glViewport(0, 0, reference.getWidth(), reference.getHeight()));
-       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbufferDepth));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbufferColor));
-               throw tcu::NotSupportedError("EGLImage as depth attachment not supported", "", __FILE__, __LINE__);
-       }
+       GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
 
        // Render
        const char* vertexShader =
@@ -873,45 +463,21 @@ bool GLES2ImageApi::renderDepth (EGLImageKHR img, const tcu::Texture2D& referenc
                "\tgl_FragColor = u_color;\n"
                "}";
 
-       Program program(vertexShader, fragmentShader);
+       Program program(gl, vertexShader, fragmentShader);
        TCU_CHECK(program.isOk());
 
        GLuint glProgram = program.getProgram();
-       GLU_CHECK_CALL(glUseProgram(glProgram));
+       GLU_CHECK_GLW_CALL(gl, useProgram(glProgram));
 
-       GLuint coordLoc = glGetAttribLocation(glProgram, "a_coord");
+       GLuint coordLoc = gl.getAttribLocation(glProgram, "a_coord");
        TCU_CHECK_MSG((int)coordLoc != -1, "Couldn't find attribute a_coord");
 
-       GLuint colorLoc = glGetUniformLocation(glProgram, "u_color");
+       GLuint colorLoc = gl.getUniformLocation(glProgram, "u_color");
        TCU_CHECK_MSG((int)colorLoc != (int)-1, "Couldn't find uniform u_color");
 
-       GLuint depthLoc = glGetUniformLocation(glProgram, "u_depth");
+       GLuint depthLoc = gl.getUniformLocation(glProgram, "u_depth");
        TCU_CHECK_MSG((int)depthLoc != (int)-1, "Couldn't find uniform u_depth");
 
-       float coords[] =
-       {
-               -1.0, -1.0,
-               1.0, -1.0,
-               1.0,  1.0,
-
-               1.0,  1.0,
-               -1.0,  1.0,
-               -1.0, -1.0
-       };
-
-       float depthLevels[] = {
-               0.1f,
-               0.2f,
-               0.3f,
-               0.4f,
-               0.5f,
-               0.6f,
-               0.7f,
-               0.8f,
-               0.9f,
-               1.0f
-       };
-
        tcu::Vec4 depthLevelColors[] = {
                tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
                tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
@@ -926,678 +492,205 @@ bool GLES2ImageApi::renderDepth (EGLImageKHR img, const tcu::Texture2D& referenc
                tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f)
        };
 
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(depthLevels) == DE_LENGTH_OF_ARRAY(depthLevelColors));
-
-       GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
-       GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords));
+       GLU_CHECK_GLW_CALL(gl, enableVertexAttribArray(coordLoc));
+       GLU_CHECK_GLW_CALL(gl, vertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, squareTriangleCoords));
 
-       GLU_CHECK_CALL(glEnable(GL_DEPTH_TEST));
-       GLU_CHECK_CALL(glDepthFunc(GL_LESS));
+       GLU_CHECK_GLW_CALL(gl, enable(GL_DEPTH_TEST));
+       GLU_CHECK_GLW_CALL(gl, depthFunc(GL_LESS));
 
-       for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevels); level++)
+       for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
        {
                tcu::Vec4 color = depthLevelColors[level];
-               GLU_CHECK_CALL(glUniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
-               GLU_CHECK_CALL(glUniform1f(depthLoc, depthLevels[level]));
-               GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
+               GLU_CHECK_GLW_CALL(gl, uniform4f(colorLoc, color.x(), color.y(), color.z(), color.w()));
+               GLU_CHECK_GLW_CALL(gl, uniform1f(depthLoc, (level + 1) * 0.1f));
+               GLU_CHECK_GLW_CALL(gl, drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(squareTriangleCoords)));
        }
 
-       GLU_CHECK_CALL(glDisable(GL_DEPTH_TEST));
-       GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
+       GLU_CHECK_GLW_CALL(gl, disable(GL_DEPTH_TEST));
+       GLU_CHECK_GLW_CALL(gl, disableVertexAttribArray(coordLoc));
 
-       tcu::Surface screen(reference.getWidth(), reference.getHeight());
-       tcu::Surface referenceScreen(reference.getWidth(), reference.getHeight());
+       const ConstPixelBufferAccess&   refAccess               = reference.getLevel(0);
+       tcu::Surface                                    screen                  (reference.getWidth(), reference.getHeight());
+       tcu::Surface                                    referenceScreen (reference.getWidth(), reference.getHeight());
 
-       glReadPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
+       gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
 
        for (int y = 0; y < reference.getHeight(); y++)
        {
                for (int x = 0; x < reference.getWidth(); x++)
                {
-                       tcu::RGBA result;
-                       for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevels); level++)
-                       {
-                               tcu::Vec4 src = reference.getLevel(0).getPixel(x, y);
+                       tcu::Vec4 result;
 
-                               if (src.x() < depthLevels[level])
-                               {
-                                       result = tcu::RGBA((int)(depthLevelColors[level].x() * 255.0f), (int)(depthLevelColors[level].y() * 255.0f), (int)(depthLevelColors[level].z() * 255.0f), (int)(depthLevelColors[level].w() * 255.0f));
-                               }
+                       for (int level = 0; level < DE_LENGTH_OF_ARRAY(depthLevelColors); level++)
+                       {
+                               if (refAccess.getPixDepth(x, y) < (level + 1) * 0.1f)
+                                       result = depthLevelColors[level];
                        }
 
-                       referenceScreen.setPixel(x, reference.getHeight(), result);
+                       referenceScreen.getAccess().setPixel(result, x, y);
                }
        }
 
-       bool isOk = tcu::pixelThresholdCompare(m_log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, tcu::RGBA(1,1,1,1), tcu::COMPARE_LOG_RESULT);
+       GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
+       GLU_CHECK_GLW_CALL(gl, finish());
 
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbufferDepth));
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbufferColor));
-       GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-       GLU_CHECK_CALL(glFinish());
-
-       return isOk;
+       return tcu::pixelThresholdCompare(log, "Depth buffer rendering result", "Result from rendering with depth buffer", referenceScreen, screen, tcu::RGBA(1,1,1,1), tcu::COMPARE_LOG_RESULT);
 }
 
-bool GLES2ImageApi::renderReadPixelsRenderBuffer (EGLImageKHR img, const tcu::Texture2D& reference)
+bool GLES2ImageApi::RenderReadPixelsRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
-       m_log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
-
-       deUint32 framebuffer;
-       glGenFramebuffers(1, &framebuffer);
-       TCU_CHECK(framebuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
+       const glw::Functions&   gl                              = api.m_gl;
+       tcu::TestLog&                   log                             = api.getLog();
+       Framebuffer                             framebuffer             (gl);
+       Renderbuffer                    renderbuffer    (gl);
+       tcu::Surface                    screen                  (reference.getWidth(), reference.getHeight());
+       tcu::Surface                    refSurface              (reference.getWidth(), reference.getHeight());
 
-       deUint32 renderbuffer = 0;
-       glGenRenderbuffers(1, &renderbuffer);
-       TCU_CHECK(renderbuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer));
+       log << tcu::TestLog::Message << "Reading with ReadPixels from renderbuffer" << tcu::TestLog::EndMessage;
 
-       m_eglExt.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)img);
+       GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
+       imageTargetRenderbuffer(gl, **img);
+       framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, *renderbuffer);
 
-       GLenum error = glGetError();
+       GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
 
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("Creating renderbuffer from EGLImage type not supported", "glEGLImageTargetRenderbufferStorageOES", __FILE__, __LINE__);
-       }
+       gl.readPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
 
-       TCU_CHECK(error == GL_NONE);
+       GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
+       GLU_CHECK_GLW_CALL(gl, finish());
 
-       TCU_CHECK_EGL_MSG("glEGLImageTargetRenderbufferStorageOES() failed");
+       tcu::copy(refSurface.getAccess(), reference.getLevel(0));
 
-       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer));
+       return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, tcu::RGBA(1,1,1,1), tcu::COMPARE_LOG_RESULT);
 
-       GLU_CHECK_CALL(glViewport(0, 0, reference.getWidth(), reference.getHeight()));
-       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("EGLImage as color attachment not supported", "", __FILE__, __LINE__);
-       }
-
-       tcu::Surface screen(reference.getWidth(), reference.getHeight());
-       tcu::Surface referenceScreen(reference.getWidth(), reference.getHeight());
-
-       glReadPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
-
-       for (int y = 0; y < reference.getHeight(); y++)
-       {
-               for (int x = 0; x < reference.getWidth(); x++)
-               {
-                       tcu::Vec4 src = reference.getLevel(0).getPixel(x, y);
-                       referenceScreen.setPixel(x, y, tcu::RGBA(src));
-               }
-       }
-
-       bool isOk = tcu::pixelThresholdCompare(m_log, "Renderbuffer read", "Result from reading renderbuffer", referenceScreen, screen, tcu::RGBA(1,1,1,1), tcu::COMPARE_LOG_RESULT);
-
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-       GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-       GLU_CHECK_CALL(glFinish());
-
-       return isOk;
 }
 
-bool GLES2ImageApi::renderTryAll (EGLImageKHR img, const tcu::Texture2D& reference)
+bool GLES2ImageApi::RenderTryAll::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
-       bool isOk = true;
-       bool foundSupportedRendering = false;
-
-       try
-       {
-               if (!renderTexture2D(img, reference))
-                       isOk = false;
-
-               foundSupportedRendering = true;
-       }
-       catch (const tcu::NotSupportedError& error)
-       {
-               m_log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
-       }
-
-       if (!isOk)
-               return false;
+       bool                                                                            foundSupported                  = false;
+       tcu::TestLog&                                                           log                                             = api.getLog();
+       GLES2ImageApi::RenderTexture2D                          renderTex2D;
+       GLES2ImageApi::RenderReadPixelsRenderbuffer     renderReadPixels;
+       GLES2ImageApi::RenderDepthbuffer                        renderDepth;
+       Action*                                                                         actions[]                               = { &renderTex2D, &renderReadPixels, &renderDepth };
 
-       try
+       for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(actions); ++ndx)
        {
-               if (!renderReadPixelsRenderBuffer(img, reference))
-                       isOk = false;
-
-               foundSupportedRendering = true;
-       }
-       catch (const tcu::NotSupportedError& error)
-       {
-               m_log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
-       }
-
-       if (!isOk)
-               return false;
-
-       try
-       {
-               if (!renderDepth(img, reference))
-                       isOk = false;
+               try
+               {
+                       if (!actions[ndx]->invoke(api, img, reference))
+                               return false;
 
-               foundSupportedRendering = true;
-       }
-       catch (const tcu::NotSupportedError& error)
-       {
-               m_log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
+                       foundSupported = true;
+               }
+               catch (const tcu::NotSupportedError& error)
+               {
+                       log << tcu::TestLog::Message << error.what() << tcu::TestLog::EndMessage;
+               }
        }
 
-       if (!foundSupportedRendering)
+       if (!foundSupported)
                throw tcu::NotSupportedError("Rendering not supported", "", __FILE__, __LINE__);
 
-       return isOk;
-}
-
-bool GLES2ImageApi::renderCubeMap (EGLImageKHR img, const tcu::Surface& reference, GLenum face)
-{
-       // \note This is not supported by EGLImage
-       DE_ASSERT(false);
-
-       glClearColor(0.5, 0.5, 0.5, 1.0);
-       glViewport(0, 0, reference.getWidth(), reference.getHeight());
-       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-       glDisable(GL_DEPTH_TEST);
-
-       m_log << tcu::TestLog::Message << "Rendering EGLImage as " <<  glTargetToString(face) << " in context: " << m_contextId << tcu::TestLog::EndMessage;
-       DE_ASSERT(img != EGL_NO_IMAGE_KHR);
-
-       deUint32 srcTex = 0;
-       glGenTextures(1, &srcTex);
-       DE_ASSERT(srcTex != 0);
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex));
-       GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, reference.getWidth(), reference.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
-       GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, reference.getWidth(), reference.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
-       GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, reference.getWidth(), reference.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
-       GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, reference.getWidth(), reference.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
-       GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, reference.getWidth(), reference.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
-       GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, reference.getWidth(), reference.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
-
-       m_eglExt.glEGLImageTargetTexture2DOES(face, (GLeglImageOES)img);
-       GLenum error = glGetError();
-
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
-               throw tcu::NotSupportedError("Creating texture cubemap from EGLImage type not supported", "glEGLImageTargetTexture2DOES", __FILE__, __LINE__);
-       }
-
-       TCU_CHECK(error == GL_NONE);
-
-       TCU_CHECK_EGL_MSG("glEGLImageTargetTexture2DOES() failed");
-
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
-
-       const char* vertexShader =
-               "attribute highp vec3 a_coord;\n"
-               "attribute highp vec3 a_texCoord;\n"
-               "varying mediump vec3 v_texCoord;\n"
-               "void main(void) {\n"
-               "\tv_texCoord = a_texCoord;\n"
-               "\tgl_Position = vec4(a_coord.xy, -0.1, 1.0);\n"
-               "}\n";
-
-       const char* fragmentShader =
-               "varying mediump vec3 v_texCoord;\n"
-               "uniform samplerCube u_sampler;\n"
-               "void main(void) {\n"
-               "\tmediump vec4 texColor = textureCube(u_sampler, v_texCoord);\n"
-               "\tgl_FragColor = vec4(texColor.rgb, 1.0);\n"
-               "}";
-
-       Program program(vertexShader, fragmentShader);
-       DE_ASSERT(program.isOk());
-
-       GLuint glProgram = program.getProgram();
-       GLU_CHECK_CALL(glUseProgram(glProgram));
-
-       GLint coordLoc = glGetAttribLocation(glProgram, "a_coord");
-       DE_ASSERT(coordLoc != -1);
-
-       GLint texCoordLoc = glGetAttribLocation(glProgram, "a_texCoord");
-       DE_ASSERT(texCoordLoc != -1);
-
-       GLint samplerLoc = glGetUniformLocation(glProgram, "u_sampler");
-       DE_ASSERT(samplerLoc != -1);
-
-       float coords[] =
-       {
-               -1.0, -1.0,
-               1.0, -1.0,
-               1.0,  1.0,
-
-               1.0,  1.0,
-               -1.0,  1.0,
-               -1.0, -1.0,
-       };
-
-       float sampleTexCoords[] =
-       {
-               10.0, -1.0, -1.0,
-               10.0,  1.0, -1.0,
-               10.0,  1.0,  1.0,
-
-               10.0,  1.0,  1.0,
-               10.0, -1.0,  1.0,
-               10.0, -1.0, -1.0,
-       };
-
-       vector<float> texCoords;
-       float   sign    = 0.0f;
-       int             dir             = -1;
-
-       switch (face)
-       {
-               case GL_TEXTURE_CUBE_MAP_POSITIVE_X: sign =  1.0; dir = 0; break;
-               case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: sign = -1.0; dir = 0; break;
-               case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: sign =  1.0; dir = 1; break;
-               case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: sign = -1.0; dir = 1; break;
-               case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: sign =  1.0; dir = 2; break;
-               case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: sign = -1.0; dir = 2; break;
-               default:
-                               DE_ASSERT(false);
-       }
-
-       for (int i = 0; i < 6; i++)
-       {
-               texCoords.push_back(sign * sampleTexCoords[i*3 + (dir % 3)]);
-               texCoords.push_back(sampleTexCoords[i*3 + ((dir + 1) % 3)]);
-               texCoords.push_back(sampleTexCoords[i*3 + ((dir + 2) % 3)]);
-       }
-
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex));
-       GLU_CHECK_CALL(glUniform1i(samplerLoc, 0));
-       GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
-       GLU_CHECK_CALL(glEnableVertexAttribArray(texCoordLoc));
-       GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords));
-       GLU_CHECK_CALL(glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, coords));
-
-       GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
-       GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
-       GLU_CHECK_CALL(glDisableVertexAttribArray(texCoordLoc));
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
-       GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
-
-       tcu::Surface screen(reference.getWidth(), reference.getHeight());
-       glReadPixels(0, 0, screen.getWidth(), screen.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, screen.getAccess().getDataPtr());
-       GLU_CHECK_MSG("glReadPixels()");
-
-       float   threshold       = 0.05f;
-       bool    match           = tcu::fuzzyCompare(m_log, "ComparisonResult", "Image comparison result", reference, screen, threshold, tcu::COMPARE_LOG_RESULT);
-
-       return match;
-}
-
-void GLES2ImageApi::modify (int operationNdx, EGLImageKHR img, tcu::Texture2D& reference)
-{
-       switch (operationNdx)
-       {
-               case MODIFY_TEXSUBIMAGE_RGBA8:
-                       modifyTexSubImage(img, reference, GL_RGBA, GL_UNSIGNED_BYTE);
-                       break;
-
-               case MODIFY_TEXSUBIMAGE_RGBA5_A1:
-                       modifyTexSubImage(img, reference, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
-                       break;
-
-               case MODIFY_TEXSUBIMAGE_RGBA4:
-                       modifyTexSubImage(img, reference, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
-                       break;
-
-               case MODIFY_TEXSUBIMAGE_RGB8:
-                       modifyTexSubImage(img, reference, GL_RGB, GL_UNSIGNED_BYTE);
-                       break;
-
-               case MODIFY_TEXSUBIMAGE_RGB565:
-                       modifyTexSubImage(img, reference, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
-                       break;
-
-               case MODIFY_RENDERBUFFER_CLEAR_COLOR:
-                       modifyRenderbufferClearColor(img, reference);
-                       break;
-
-               case MODIFY_RENDERBUFFER_CLEAR_DEPTH:
-                       modifyRenderbufferClearDepth(img, reference);
-                       break;
-
-               case MODIFY_RENDERBUFFER_CLEAR_STENCIL:
-                       modifyRenderbufferClearStencil(img, reference);
-                       break;
-
-               default:
-                       DE_ASSERT(false);
-                       break;
-       }
+       return true;
 }
 
-void GLES2ImageApi::modifyTexSubImage (EGLImageKHR img, tcu::Texture2D& reference, GLenum format, GLenum type)
+bool GLES2ImageApi::ModifyTexSubImage::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
-       m_log << tcu::TestLog::Message << "Modifying EGLImage with glTexSubImage2D" << tcu::TestLog::EndMessage;
+       const glw::Functions&   gl              = api.m_gl;
+       tcu::TestLog&                   log             = api.getLog();
+       glu::Texture                    srcTex  (gl);
+       const int                               xOffset = 8;
+       const int                               yOffset = 16;
+       const int                               xSize   = de::clamp(16, 0, reference.getWidth() - xOffset);
+       const int                               ySize   = de::clamp(16, 0, reference.getHeight() - yOffset);
+       tcu::Texture2D                  src             (glu::mapGLTransferFormat(m_format, m_type), xSize, ySize);
 
-       deUint32 srcTex = 0;
-       glGenTextures(1, &srcTex);
-       TCU_CHECK(srcTex != 0);
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
+       log << tcu::TestLog::Message << "Modifying EGLImage with gl.texSubImage2D" << tcu::TestLog::EndMessage;
 
-       m_eglExt.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)img);
-
-       GLenum error = glGetError();
-
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
-               throw tcu::NotSupportedError("Creating texture2D from EGLImage type not supported", "glEGLImageTargetTexture2DOES", __FILE__, __LINE__);
-       }
-       TCU_CHECK(error == GL_NONE);
-
-       TCU_CHECK_EGL_MSG("glEGLImageTargetTexture2DOES() failed");
-
-       int xOffset = 8;
-       int yOffset = 16;
-
-       tcu::Texture2D src(glu::mapGLTransferFormat(format, type), 16, 16);
        src.allocLevel(0);
        tcu::fillWithComponentGradients(src.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
 
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex));
-       GLU_CHECK_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), format, type, src.getLevel(0).getDataPtr()));
+       GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, *srcTex));
+       imageTargetTexture2D(gl, **img);
+       GLU_CHECK_GLW_CALL(gl, texSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, src.getWidth(), src.getHeight(), m_format, m_type, src.getLevel(0).getDataPtr()));
+       GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, 0));
+       GLU_CHECK_GLW_CALL(gl, finish());
 
-       for (int x = 0; x < src.getWidth(); x++)
-       {
-               if (x + xOffset >= reference.getWidth())
-                       continue;
-
-               for (int y = 0; y < src.getHeight(); y++)
-               {
-                       if (y + yOffset >= reference.getHeight())
-                               continue;
+       tcu::copy(tcu::getSubregion(reference.getLevel(0), xOffset, yOffset, 0, xSize, ySize, 1), src.getLevel(0));
 
-                       reference.getLevel(0).setPixel(src.getLevel(0).getPixel(x, y), x+xOffset, y+yOffset);
-               }
-       }
-
-       GLU_CHECK_CALL(glDeleteTextures(1, &srcTex));
-       GLU_CHECK_CALL(glFinish());
-       GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, 0));
+       return true;
 }
 
-void GLES2ImageApi::modifyRenderbufferClearColor (EGLImageKHR img, tcu::Texture2D& reference)
+bool GLES2ImageApi::ModifyRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
-       m_log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
-
-       deUint32 framebuffer;
-       glGenFramebuffers(1, &framebuffer);
-       TCU_CHECK(framebuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
+       const glw::Functions&   gl                              = api.m_gl;
+       tcu::TestLog&                   log                             = api.getLog();
+       glu::Framebuffer                framebuffer             (gl);
+       glu::Renderbuffer               renderbuffer    (gl);
 
-       deUint32 renderbuffer = 0;
-       glGenRenderbuffers(1, &renderbuffer);
-       TCU_CHECK(renderbuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer));
+       log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
 
-       m_eglExt.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)img);
+       GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, *framebuffer));
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer));
 
-       GLenum error = glGetError();
+       imageTargetRenderbuffer(gl, **img);
 
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("Creating renderbuffer from EGLImage type not supported", "glEGLImageTargetRenderbufferStorageOES", __FILE__, __LINE__);
-       }
-       TCU_CHECK(error == GL_NONE);
-
-       TCU_CHECK_EGL_MSG("glEGLImageTargetRenderbufferStorageOES() failed");
-
-       float red       = 0.3f;
-       float green     = 0.5f;
-       float blue      = 0.3f;
-       float alpha     = 1.0f;
+       initializeRbo(api, *renderbuffer, reference);
 
-       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer));
+       GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, 0));
+       GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, 0));
 
-       GLU_CHECK_CALL(glViewport(0, 0, reference.getWidth(), reference.getHeight()));
-       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("EGLImage type as color attachment not supported", "", __FILE__, __LINE__);
-       }
+       GLU_CHECK_GLW_CALL(gl, finish());
 
-       GLU_CHECK_CALL(glClearColor(red, green, blue, alpha));
-       GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
-
-       for (int x = 0; x < reference.getWidth(); x++)
-       {
-               for (int y = 0; y < reference.getHeight(); y++)
-               {
-                       tcu::Vec4 color = tcu::Vec4(red, green, blue, alpha);
-                       reference.getLevel(0).setPixel(color, x, y);
-               }
-       }
-
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-       GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-       GLU_CHECK_CALL(glFinish());
+       return true;
 }
 
-void GLES2ImageApi::modifyRenderbufferClearDepth (EGLImageKHR img, tcu::Texture2D& reference)
+void GLES2ImageApi::ModifyRenderbufferClearColor::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
 {
-       m_log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
-
-       deUint32 framebuffer;
-       glGenFramebuffers(1, &framebuffer);
-       TCU_CHECK(framebuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
-
-       deUint32 renderbuffer = 0;
-       glGenRenderbuffers(1, &renderbuffer);
-       TCU_CHECK(renderbuffer != 0);
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer));
-
-       m_eglExt.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)img);
+       const glw::Functions&   gl              = api.m_gl;
+       const tcu::Vec4                 color   (0.3f, 0.5f, 0.3f, 1.0f);
 
-       GLenum error = glGetError();
+       framebufferRenderbuffer(gl, GL_COLOR_ATTACHMENT0, renderbuffer);
 
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("Creating renderbuffer from EGLImage type not supported", "glEGLImageTargetRenderbufferStorageOES", __FILE__, __LINE__);
-       }
-       TCU_CHECK(error == GL_NONE);
-
-       TCU_CHECK_EGL_MSG("glEGLImageTargetRenderbufferStorageOES() failed");
-
-       float depth = 0.7f;
-
-       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer));
-
-       GLU_CHECK_CALL(glViewport(0, 0, reference.getWidth(), reference.getHeight()));
-       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("EGLImage type as depth attachment not supported", "", __FILE__, __LINE__);
-       }
-
-       GLU_CHECK_CALL(glClearDepthf(depth));
-       GLU_CHECK_CALL(glClear(GL_DEPTH_BUFFER_BIT));
-
-       for (int x = 0; x < reference.getWidth(); x++)
-       {
-               for (int y = 0; y < reference.getHeight(); y++)
-               {
-                       tcu::Vec4 color = tcu::Vec4(depth, depth, depth, depth);
-                       reference.getLevel(0).setPixel(color, x, y);
-               }
-       }
+       GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
+       GLU_CHECK_GLW_CALL(gl, clearColor(color.x(), color.y(), color.z(), color.w()));
+       GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
 
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-       GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-       GLU_CHECK_CALL(glFinish());
+       tcu::clear(reference.getLevel(0), color);
 }
 
-void GLES2ImageApi::modifyRenderbufferClearStencil (EGLImageKHR img, tcu::Texture2D& reference)
+void GLES2ImageApi::ModifyRenderbufferClearDepth::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
 {
-       m_log << tcu::TestLog::Message << "Modifying EGLImage with glClear to renderbuffer" << tcu::TestLog::EndMessage;
+       const glw::Functions&   gl              = api.m_gl;
+       const float                             depth   = 0.7f;
 
-       deUint32 framebuffer;
-       glGenFramebuffers(1, &framebuffer);
-       TCU_CHECK(framebuffer != (GLuint)-1);
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
+       framebufferRenderbuffer(gl, GL_DEPTH_ATTACHMENT, renderbuffer);
 
-       deUint32 renderbuffer = 0;
-       glGenRenderbuffers(1, &renderbuffer);
-       TCU_CHECK(renderbuffer != 0);
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer));
+       GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
+       GLU_CHECK_GLW_CALL(gl, clearDepthf(depth));
+       GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
 
-       m_eglExt.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)img);
-       GLenum error = glGetError();
-
-       if (error == GL_INVALID_OPERATION)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("Creating renderbuffer from EGLImage type not supported", "glEGLImageTargetRenderbufferStorageOES", __FILE__, __LINE__);
-       }
-       TCU_CHECK(error == GL_NONE);
-
-       TCU_CHECK_EGL_MSG("glEGLImageTargetRenderbufferStorageOES() failed");
-
-       int stencilValue = 78;
-
-       GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer));
-
-       GLU_CHECK_CALL(glViewport(0, 0, reference.getWidth(), reference.getHeight()));
-       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-       {
-               GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-               throw tcu::NotSupportedError("EGLImage type as stencil attachment not supported", "", __FILE__, __LINE__);
-       }
-
-       GLU_CHECK_CALL(glClearStencil(stencilValue));
-       GLU_CHECK_CALL(glClear(GL_STENCIL_BUFFER_BIT));
-
-       for (int x = 0; x < reference.getWidth(); x++)
-       {
-               for (int y = 0; y < reference.getHeight(); y++)
-               {
-                       tcu::IVec4 color = tcu::IVec4(stencilValue, stencilValue, stencilValue, stencilValue);
-                       reference.getLevel(0).setPixel(color, x, y);
-               }
-       }
-
-       GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-       GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-       GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
-       GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
-       GLU_CHECK_CALL(glFinish());
+       tcu::clearDepth(reference.getLevel(0), depth);
 }
 
-
-void GLES2ImageApi::checkRequiredExtensions (set<string>& extensions, TestSpec::Operation::Type type, int operationNdx)
+void GLES2ImageApi::ModifyRenderbufferClearStencil::initializeRbo (GLES2ImageApi& api, GLuint renderbuffer, tcu::Texture2D& reference) const
 {
-       switch (type)
-       {
-               case TestSpec::Operation::TYPE_CREATE:
-                       switch (operationNdx)
-                       {
-                               case CREATE_TEXTURE2D_RGB8:
-                               case CREATE_TEXTURE2D_RGB565:
-                               case CREATE_TEXTURE2D_RGBA8:
-                               case CREATE_TEXTURE2D_RGBA5_A1:
-                               case CREATE_TEXTURE2D_RGBA4:
-                                       extensions.insert("EGL_KHR_gl_texture_2D_image");
-                                       break;
-
-                               case CREATE_CUBE_MAP_POSITIVE_X_RGB8:
-                               case CREATE_CUBE_MAP_NEGATIVE_X_RGB8:
-                               case CREATE_CUBE_MAP_POSITIVE_Y_RGB8:
-                               case CREATE_CUBE_MAP_NEGATIVE_Y_RGB8:
-                               case CREATE_CUBE_MAP_POSITIVE_Z_RGB8:
-                               case CREATE_CUBE_MAP_NEGATIVE_Z_RGB8:
-                               case CREATE_CUBE_MAP_POSITIVE_X_RGBA8:
-                               case CREATE_CUBE_MAP_NEGATIVE_X_RGBA8:
-                               case CREATE_CUBE_MAP_POSITIVE_Y_RGBA8:
-                               case CREATE_CUBE_MAP_NEGATIVE_Y_RGBA8:
-                               case CREATE_CUBE_MAP_POSITIVE_Z_RGBA8:
-                               case CREATE_CUBE_MAP_NEGATIVE_Z_RGBA8:
-                                       extensions.insert("EGL_KHR_gl_texture_cubemap_image");
-                                       break;
-
-                               case CREATE_RENDER_BUFFER_RGBA4:
-                               case CREATE_RENDER_BUFFER_RGB5_A1:
-                               case CREATE_RENDER_BUFFER_RGB565:
-                               case CREATE_RENDER_BUFFER_DEPTH16:
-                               case CREATE_RENDER_BUFFER_STENCIL:
-                                       extensions.insert("EGL_KHR_gl_renderbuffer_image");
-                                       break;
-
-                               default:
-                                       DE_ASSERT(false);
-                       }
-                       break;
+       const glw::Functions&   gl              = api.m_gl;
+       const int                               stencil = 78;
 
-               case TestSpec::Operation::TYPE_RENDER:
-                       switch (operationNdx)
-                       {
-                               case RENDER_TEXTURE2D:
-                               case RENDER_READ_PIXELS_RENDERBUFFER:
-                               case RENDER_DEPTHBUFFER:
-                               case RENDER_TRY_ALL:
-                                       extensions.insert("GL_OES_EGL_image");
-                                       break;
-
-                               default:
-                                       DE_ASSERT(false);
-                                       break;
-                       }
-                       break;
+       framebufferRenderbuffer(gl, GL_STENCIL_ATTACHMENT, renderbuffer);
 
-               case TestSpec::Operation::TYPE_MODIFY:
-                       switch (operationNdx)
-                       {
-                               case MODIFY_TEXSUBIMAGE_RGB565:
-                               case MODIFY_TEXSUBIMAGE_RGB8:
-                               case MODIFY_TEXSUBIMAGE_RGBA8:
-                               case MODIFY_TEXSUBIMAGE_RGBA5_A1:
-                               case MODIFY_TEXSUBIMAGE_RGBA4:
-                               case MODIFY_RENDERBUFFER_CLEAR_COLOR:
-                               case MODIFY_RENDERBUFFER_CLEAR_DEPTH:
-                               case MODIFY_RENDERBUFFER_CLEAR_STENCIL:
-                                       extensions.insert("GL_OES_EGL_image");
-                                       break;
-
-                               default:
-                                       DE_ASSERT(false);
-                                       break;
-                       };
-                       break;
-
-               default:
-                       DE_ASSERT(false);
-                       break;
-       }
+       GLU_CHECK_GLW_CALL(gl, viewport(0, 0, reference.getWidth(), reference.getHeight()));
+       GLU_CHECK_GLW_CALL(gl, clearStencil(stencil));
+       GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
+
+       tcu::clearStencil(reference.getLevel(0), stencil);
 }
 
-class ImageFormatCase : public TestCase
+class ImageFormatCase : public TestCase, private glu::CallLogWrapper
 {
 public:
                                                ImageFormatCase         (EglTestContext& eglTestCtx, const TestSpec& spec);
@@ -1612,7 +705,6 @@ private:
        EGLConfig                       getConfig                       (void);
 
        const TestSpec          m_spec;
-       tcu::TestLog&           m_log;
 
        vector<ImageApi*>       m_apiContexts;
 
@@ -1621,9 +713,9 @@ private:
        tcu::egl::Surface*      m_surface;
        EGLConfig                       m_config;
        int                                     m_curIter;
-       EGLImageKHR                     m_img;
+       MovePtr<UniqueImage>m_img;
        tcu::Texture2D          m_refImg;
-       EglExt                          m_eglExt;
+       glw::Functions          m_gl;
 };
 
 EGLConfig ImageFormatCase::getConfig (void)
@@ -1645,16 +737,15 @@ EGLConfig ImageFormatCase::getConfig (void)
 }
 
 ImageFormatCase::ImageFormatCase (EglTestContext& eglTestCtx, const TestSpec& spec)
-       : TestCase                      (eglTestCtx, spec.name.c_str(), spec.desc.c_str())
-       , m_spec                        (spec)
-       , m_log                         (eglTestCtx.getTestContext().getLog())
-       , m_display                     (DE_NULL)
-       , m_window                      (DE_NULL)
-       , m_surface                     (DE_NULL)
-       , m_config                      (0)
-       , m_curIter                     (0)
-       , m_img                         (EGL_NO_IMAGE_KHR)
-       , m_refImg                      (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
+       : TestCase                              (eglTestCtx, spec.name.c_str(), spec.desc.c_str())
+       , glu::CallLogWrapper   (m_gl, eglTestCtx.getTestContext().getLog())
+       , m_spec                                (spec)
+       , m_display                             (DE_NULL)
+       , m_window                              (DE_NULL)
+       , m_surface                             (DE_NULL)
+       , m_config                              (0)
+       , m_curIter                             (0)
+       , m_refImg                              (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1)
 {
 }
 
@@ -1665,47 +756,39 @@ ImageFormatCase::~ImageFormatCase (void)
 
 void ImageFormatCase::checkExtensions (void)
 {
-       vector<string> extensions;
-       m_display->getExtensions(extensions);
-
-       set<string> extSet(extensions.begin(), extensions.end());
+       const EGLDisplay                dpy             = m_display->getEGLDisplay();
+       set<string>                             exts;
+       const vector<string>    glExts  = de::splitString((const char*) m_gl.getString(GL_EXTENSIONS));
+       const vector<string>    eglExts = eglu::getClientExtensions(dpy);
 
-       const char* glExt = (const char*)glGetString(GL_EXTENSIONS);
+       exts.insert(glExts.begin(), glExts.end());
+       exts.insert(eglExts.begin(), eglExts.end());
 
-       for (const char* c = glExt; true; c++)
+       if (eglu::getVersion(dpy) >= eglu::Version(1, 5))
        {
-               if (*c == '\0')
-               {
-                       extSet.insert(string(glExt));
-                       break;
-               }
-
-               if (*c == ' ')
-               {
-                       extSet.insert(string(glExt, c));
-                       glExt = (c+1);
-               }
+               // EGL 1.5 has built-in support for EGLImage and GL sources
+               exts.insert("EGL_KHR_image_base");
+               exts.insert("EGL_KHR_gl_texture_2D_image");
+               exts.insert("EGL_KHR_gl_texture_cubemap_image");
+               exts.insert("EGL_KHR_gl_renderbuffer_image");
        }
 
-       if (extSet.find("EGL_KHR_image_base") == extSet.end()
-                       && extSet.find("EGL_KHR_image") == extSet.end())
+       if (!de::contains(exts, "EGL_KHR_image_base") && !de::contains(exts, "EGL_KHR_image"))
        {
-               m_log << tcu::TestLog::Message
-                       << "EGL_KHR_image and EGL_KHR_image_base not supported."
-                       << "One should be supported."
-                       << tcu::TestLog::EndMessage;
-               throw tcu::NotSupportedError("Extension not supported", "EGL_KHR_image_base", __FILE__, __LINE__);
+               getLog() << tcu::TestLog::Message
+                                << "EGL version is under 1.5 and neither EGL_KHR_image nor EGL_KHR_image_base is supported."
+                                << "One should be supported."
+                                << tcu::TestLog::EndMessage;
+               TCU_THROW(NotSupportedError, "Extension not supported: EGL_KHR_image_base");
        }
 
-       set<string> requiredExtensions;
        for (int operationNdx = 0; operationNdx < (int)m_spec.operations.size(); operationNdx++)
-               m_apiContexts[m_spec.operations[m_curIter].apiIndex]->checkRequiredExtensions(requiredExtensions, m_spec.operations[operationNdx].type, m_spec.operations[operationNdx].operationIndex);
-
-       std::set<string>::iterator extIter = requiredExtensions.begin();
-       for (; extIter != requiredExtensions.end(); extIter++)
        {
-               if (extSet.find(*extIter) == extSet.end())
-                       throw tcu::NotSupportedError("Extension not supported", (*extIter).c_str(), __FILE__, __LINE__);
+               const TestSpec::Operation&      op      = m_spec.operations[operationNdx];
+               const string                            ext     = op.action->getRequiredExtension();
+
+               if (!de::contains(exts, ext))
+                       TCU_THROW_EXPR(NotSupportedError, "Extension not supported", ext.c_str());
        }
 }
 
@@ -1716,6 +799,8 @@ void ImageFormatCase::init (void)
        m_window        = m_eglTestCtx.createNativeWindow(m_display->getEGLDisplay(), m_config, DE_NULL, 480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine()));
        m_surface       = new tcu::egl::WindowSurface(*m_display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_display->getEGLDisplay(), m_config, DE_NULL));
 
+       m_eglTestCtx.getGLFunctions(m_gl, glu::ApiType::es(2, 0), vector<const char*>(1, "GL_OES_EGL_image"));
+
        for (int contextNdx = 0; contextNdx < (int)m_spec.contexts.size(); contextNdx++)
        {
                ImageApi* api = DE_NULL;
@@ -1723,7 +808,7 @@ void ImageFormatCase::init (void)
                {
                        case TestSpec::API_GLES2:
                        {
-                               api = new GLES2ImageApi(contextNdx, m_log, *m_display, m_surface, m_config);
+                               api = new GLES2ImageApi(m_gl, contextNdx, getLog(), *m_display, m_surface, m_config);
                                break;
                        }
 
@@ -1750,381 +835,268 @@ void ImageFormatCase::deinit (void)
 
 TestCase::IterateResult ImageFormatCase::iterate (void)
 {
-       bool isOk = true;
+       const TestSpec::Operation&      op              = m_spec.operations[m_curIter++];
+       ImageApi&                                       api             = *m_apiContexts[op.apiIndex];
+       const bool                                      isOk    = op.action->invoke(api, m_img, m_refImg);
 
-       switch (m_spec.operations[m_curIter].type)
-       {
-               case TestSpec::Operation::TYPE_CREATE:
-               {
-                       // Delete old image if exists
-                       if (m_img != EGL_NO_IMAGE_KHR)
-                       {
-                               m_log << tcu::TestLog::Message << "Destroying old EGLImage" << tcu::TestLog::EndMessage;
-                               TCU_CHECK_EGL_CALL(m_eglExt.eglDestroyImageKHR(m_display->getEGLDisplay(), m_img));
+       if (isOk && m_curIter < (int)m_spec.operations.size())
+               return CONTINUE;
+       else if (isOk)
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       else
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
 
-                               m_img = EGL_NO_IMAGE_KHR;
-                       }
+       return STOP;
+}
 
-                       m_img = m_apiContexts[m_spec.operations[m_curIter].apiIndex]->create(m_spec.operations[m_curIter].operationIndex, m_refImg);
-                       break;
-               }
+struct LabeledAction
+{
+       string                  label;
+       MovePtr<Action> action;
+};
 
-               case TestSpec::Operation::TYPE_RENDER:
-               {
-                       DE_ASSERT(m_apiContexts[m_spec.operations[m_curIter].apiIndex]);
-                       isOk = m_apiContexts[m_spec.operations[m_curIter].apiIndex]->render(m_spec.operations[m_curIter].operationIndex, m_img, m_refImg);
-                       break;
-               }
+// A simple vector mockup that we need because MovePtr isn't copy-constructible.
+struct LabeledActions
+{
+                                       LabeledActions  (void) : m_numActions(0){}
+       LabeledAction&  operator[]              (int ndx)                               { DE_ASSERT(0 <= ndx && ndx < m_numActions); return m_actions[ndx]; }
+       void                    add                             (const string& label, MovePtr<Action> action);
+       int                             size                    (void) const                    { return m_numActions; }
+private:
+       LabeledAction   m_actions[32];
+       int                             m_numActions;
+};
 
-               case TestSpec::Operation::TYPE_MODIFY:
-               {
-                       m_apiContexts[m_spec.operations[m_curIter].apiIndex]->modify(m_spec.operations[m_curIter].operationIndex, m_img, m_refImg);
-                       break;
-               }
+void LabeledActions::add (const string& label, MovePtr<Action> action)
+{
+       DE_ASSERT(m_numActions < DE_LENGTH_OF_ARRAY(m_actions));
+       m_actions[m_numActions].label = label;
+       m_actions[m_numActions].action = action;
+       ++m_numActions;
+}
 
-               default:
-                       DE_ASSERT(false);
-                       break;
-       }
+class ImageTests : public TestCaseGroup
+{
+protected:
+                                       ImageTests                                              (EglTestContext& eglTestCtx, const string& name, const string& desc)
+                                               : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
 
-       if (isOk && ++m_curIter < (int)m_spec.operations.size())
-       {
-               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-               return CONTINUE;
-       }
-       else if (!isOk)
-       {
-               if (m_img != EGL_NO_IMAGE_KHR)
-               {
-                       m_log << tcu::TestLog::Message << "Destroying EGLImage" << tcu::TestLog::EndMessage;
-                       TCU_CHECK_EGL_CALL(m_eglExt.eglDestroyImageKHR(m_display->getEGLDisplay(), m_img));
-                       m_img = EGL_NO_IMAGE_KHR;
-               }
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
-               return STOP;
-       }
-       else
-       {
-               if (m_img != EGL_NO_IMAGE_KHR)
-               {
-                       m_log << tcu::TestLog::Message << "Destroying EGLImage" << tcu::TestLog::EndMessage;
-                       TCU_CHECK_EGL_CALL(m_eglExt.eglDestroyImageKHR(m_display->getEGLDisplay(), m_img));
-                       m_img = EGL_NO_IMAGE_KHR;
-               }
-               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-               return STOP;
-       }
+       void                    addCreateTexture                                (const string& name, EGLenum source, GLenum format, GLenum type);
+       void                    addCreateRenderbuffer                   (const string& name, GLenum format);
+       void                    addCreateTexture2DActions               (const string& prefix);
+       void                    addCreateTextureCubemapActions  (const string& suffix, GLenum format, GLenum type);
+       void                    addCreateRenderbufferActions    (void);
+
+       LabeledActions  m_createActions;
+};
+
+void ImageTests::addCreateTexture (const string& name, EGLenum source, GLenum format, GLenum type)
+{
+       m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createTextureImageSource(source, format, type))));
 }
 
-SimpleCreationTests::SimpleCreationTests (EglTestContext& eglTestCtx)
-       : TestCaseGroup (eglTestCtx, "create", "EGLImage creation tests")
+void ImageTests::addCreateRenderbuffer (const string& name, GLenum format)
 {
+       m_createActions.add(name, MovePtr<Action>(new GLES2ImageApi::Create(createRenderbufferImageSource(format))));
 }
 
-#define PUSH_VALUES_TO_VECTOR(type, vector, ...)\
-do {\
-       type array[] = __VA_ARGS__;\
-       for (int i = 0; i < DE_LENGTH_OF_ARRAY(array); i++)\
-       {\
-               vector.push_back(array[i]);\
-       }\
-} while(false);
+void ImageTests::addCreateTexture2DActions (const string& prefix)
+{
+       addCreateTexture(prefix + "rgb8",               EGL_GL_TEXTURE_2D_KHR,  GL_RGB,         GL_UNSIGNED_BYTE);
+       addCreateTexture(prefix + "rgb565",             EGL_GL_TEXTURE_2D_KHR,  GL_RGB,         GL_UNSIGNED_SHORT_5_6_5);
+       addCreateTexture(prefix + "rgba8",              EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_UNSIGNED_BYTE);
+       addCreateTexture(prefix + "rgba5_a1",   EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_UNSIGNED_SHORT_5_5_5_1);
+       addCreateTexture(prefix + "rgba4",              EGL_GL_TEXTURE_2D_KHR,  GL_RGBA,        GL_UNSIGNED_SHORT_4_4_4_4);
+}
 
-void SimpleCreationTests::init (void)
+void ImageTests::addCreateTextureCubemapActions (const string& suffix, GLenum format, GLenum type)
 {
-       GLES2ImageApi::Create createOperations[] = {
-               GLES2ImageApi::CREATE_TEXTURE2D_RGB8,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGB565,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA8,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA5_A1,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA4,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_X_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Y_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Z_RGBA8,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_X_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Y_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Z_RGBA8,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_X_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Y_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Z_RGB8,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_X_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Y_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Z_RGB8,
-
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGBA4,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGB5_A1,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGB565,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_DEPTH16,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_STENCIL
-       };
+       addCreateTexture("cubemap_positive_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, format, type);
+       addCreateTexture("cubemap_positive_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, format, type);
+       addCreateTexture("cubemap_positive_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, format, type);
+       addCreateTexture("cubemap_negative_x" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, format, type);
+       addCreateTexture("cubemap_negative_y" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, format, type);
+       addCreateTexture("cubemap_negative_z" + suffix, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, format, type);
+}
 
-       const char* createOperationsStr[] = {
-               "texture_rgb8",
-               "texture_rgb565",
-               "texture_rgba8",
-               "texture_rgba5_a1",
-               "texture_rgba4",
-
-               "cubemap_positive_x_rgba",
-               "cubemap_positive_y_rgba",
-               "cubemap_positive_z_rgba",
-
-               "cubemap_negative_x_rgba",
-               "cubemap_negative_y_rgba",
-               "cubemap_negative_z_rgba",
-
-               "cubemap_positive_x_rgb",
-               "cubemap_positive_y_rgb",
-               "cubemap_positive_z_rgb",
-
-               "cubemap_negative_x_rgb",
-               "cubemap_negative_y_rgb",
-               "cubemap_negative_z_rgb",
-
-               "renderbuffer_rgba4",
-               "renderbuffer_rgb5_a1",
-               "renderbuffer_rgb565",
-               "renderbuffer_depth16",
-               "renderbuffer_stencil"
-       };
+void ImageTests::addCreateRenderbufferActions (void)
+{
+       addCreateRenderbuffer("renderbuffer_rgba4",             GL_RGBA4);
+       addCreateRenderbuffer("renderbuffer_rgb5_a1",   GL_RGB5_A1);
+       addCreateRenderbuffer("renderbuffer_rgb565",    GL_RGB565);
+       addCreateRenderbuffer("renderbuffer_depth16",   GL_DEPTH_COMPONENT16);
+       addCreateRenderbuffer("renderbuffer_stencil",   GL_STENCIL_INDEX8);
+}
 
-       GLES2ImageApi::Render renderOperations[] = {
-                       GLES2ImageApi::RENDER_TEXTURE2D,
-                       GLES2ImageApi::RENDER_READ_PIXELS_RENDERBUFFER,
-                       GLES2ImageApi::RENDER_DEPTHBUFFER
-       };
-       const char* renderOperationsStr[] = {
-                       "texture",
-                       "read_pixels",
-                       "depth_buffer"
-       };
+class RenderTests : public ImageTests
+{
+protected:
+                                                                                       RenderTests                             (EglTestContext& eglTestCtx, const string& name, const string& desc)
+                                                                                               : ImageTests                    (eglTestCtx, name, desc) {}
+
+       void                                                                    addRenderActions                (void);
+       LabeledActions                                                  m_renderActions;
+};
 
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(createOperations) == DE_LENGTH_OF_ARRAY(createOperationsStr));
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(renderOperations) == DE_LENGTH_OF_ARRAY(renderOperationsStr));
+void RenderTests::addRenderActions (void)
+{
+       m_renderActions.add("texture",          MovePtr<Action>(new GLES2ImageApi::RenderTexture2D()));
+       m_renderActions.add("read_pixels",      MovePtr<Action>(new GLES2ImageApi::RenderReadPixelsRenderbuffer()));
+       m_renderActions.add("depth_buffer",     MovePtr<Action>(new GLES2ImageApi::RenderDepthbuffer()));
+}
 
-       for (int createNdx = 0; createNdx < DE_LENGTH_OF_ARRAY(createOperations); createNdx++)
+class SimpleCreationTests : public RenderTests
+{
+public:
+                       SimpleCreationTests             (EglTestContext& eglTestCtx, const string& name, const string& desc) : RenderTests(eglTestCtx, name, desc) {}
+       void    init                                    (void);
+};
+
+void SimpleCreationTests::init (void)
+{
+       addCreateTexture2DActions("texture_");
+       addCreateTextureCubemapActions("_rgba", GL_RGBA, GL_UNSIGNED_BYTE);
+       addCreateTextureCubemapActions("_rgb", GL_RGB, GL_UNSIGNED_BYTE);
+       addCreateRenderbufferActions();
+       addRenderActions();
+
+       for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
        {
-               for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renderOperations); renderNdx++)
+               const LabeledAction& createAction = m_createActions[createNdx];
+
+               for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
                {
-                       TestSpec spec;
-                       spec.name = std::string("gles2_") + createOperationsStr[createNdx] + "_" + renderOperationsStr[renderNdx];
-                       spec.desc = spec.name;
+                       const LabeledAction&    renderAction    = m_renderActions[renderNdx];
+                       TestSpec                                spec;
 
-                       PUSH_VALUES_TO_VECTOR(TestSpec::ApiContext, spec.contexts,
-                       {
-                               TestSpec::API_GLES2
-                       });
-                       PUSH_VALUES_TO_VECTOR(TestSpec::Operation, spec.operations,
-                       {
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_CREATE, createOperations[createNdx] },
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_RENDER, renderOperations[renderNdx] },
-                       });
+                       spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
+                       spec.desc = spec.name;
+                       spec.contexts.push_back(TestSpec::API_GLES2);
+                       spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
+                       spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
 
                        addChild(new ImageFormatCase(m_eglTestCtx, spec));
                }
        }
 }
 
-MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx)
-       : TestCaseGroup (eglTestCtx, "render_multiple_contexts", "EGLImage render tests on multiple contexts")
+TestCaseGroup* createSimpleCreationTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
 {
+       return new SimpleCreationTests(eglTestCtx, name, desc);
 }
 
-void MultiContextRenderTests::init (void)
+class MultiContextRenderTests : public RenderTests
 {
-       GLES2ImageApi::Create createOperations[] = {
-               GLES2ImageApi::CREATE_TEXTURE2D_RGB8,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGB565,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA8,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA5_A1,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA4,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_X_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Y_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Z_RGBA8,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_X_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Y_RGBA8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Z_RGBA8,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_X_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Y_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_POSITIVE_Z_RGB8,
-
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_X_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Y_RGB8,
-               GLES2ImageApi::CREATE_CUBE_MAP_NEGATIVE_Z_RGB8,
-
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGBA4,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGB5_A1,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGB565,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_DEPTH16,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_STENCIL
-       };
-
-       const char* createOperationsStr[] = {
-               "texture_rgb8",
-               "texture_rgb565",
-               "texture_rgba8",
-               "texture_rgba5_a1",
-               "texture_rgba4",
-
-               "cubemap_positive_x_rgba8",
-               "cubemap_positive_y_rgba8",
-               "cubemap_positive_z_rgba8",
-
-               "cubemap_negative_x_rgba8",
-               "cubemap_negative_y_rgba8",
-               "cubemap_negative_z_rgba8",
-
-               "cubemap_positive_x_rgb8",
-               "cubemap_positive_y_rgb8",
-               "cubemap_positive_z_rgb8",
-
-               "cubemap_negative_x_rgb8",
-               "cubemap_negative_y_rgb8",
-               "cubemap_negative_z_rgb8",
-
-               "renderbuffer_rgba4",
-               "renderbuffer_rgb5_a1",
-               "renderbuffer_rgb565",
-               "renderbuffer_depth16",
-               "renderbuffer_stencil"
-       };
+public:
+                       MultiContextRenderTests         (EglTestContext& eglTestCtx, const string& name, const string& desc);
+       void    init                                            (void);
+};
 
-       GLES2ImageApi::Render renderOperations[] = {
-                       GLES2ImageApi::RENDER_TEXTURE2D,
-                       GLES2ImageApi::RENDER_READ_PIXELS_RENDERBUFFER,
-                       GLES2ImageApi::RENDER_DEPTHBUFFER
-       };
-       const char* renderOperationsStr[] = {
-                       "texture",
-                       "read_pixels",
-                       "depth_buffer"
-       };
+MultiContextRenderTests::MultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
+       : RenderTests   (eglTestCtx, name, desc)
+{
+}
 
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(createOperations) == DE_LENGTH_OF_ARRAY(createOperationsStr));
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(renderOperations) == DE_LENGTH_OF_ARRAY(renderOperationsStr));
+void MultiContextRenderTests::init (void)
+{
+       addCreateTexture2DActions("texture_");
+       addCreateTextureCubemapActions("_rgba8", GL_RGBA, GL_UNSIGNED_BYTE);
+       addCreateTextureCubemapActions("_rgb8", GL_RGB, GL_UNSIGNED_BYTE);
+       addCreateRenderbufferActions();
+       addRenderActions();
 
-       for (int createNdx = 0; createNdx < DE_LENGTH_OF_ARRAY(createOperations); createNdx++)
+       for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
        {
-               for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renderOperations); renderNdx++)
+               const LabeledAction& createAction = m_createActions[createNdx];
+               for (int renderNdx = 0; renderNdx < m_renderActions.size(); renderNdx++)
                {
-                       TestSpec spec;
-                       spec.name = std::string("gles2_") + createOperationsStr[createNdx] + "_" + renderOperationsStr[renderNdx];
+                       const LabeledAction&    renderAction    = m_renderActions[renderNdx];
+                       TestSpec                                spec;
+                       spec.name = std::string("gles2_") + createAction.label + "_" + renderAction.label;
                        spec.desc = spec.name;
 
-                       PUSH_VALUES_TO_VECTOR(TestSpec::ApiContext, spec.contexts,
-                       {
-                               TestSpec::API_GLES2,
-                               TestSpec::API_GLES2
-                       });
-                       PUSH_VALUES_TO_VECTOR(TestSpec::Operation, spec.operations,
-                       {
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_CREATE, createOperations[createNdx] },
-                               { TestSpec::API_GLES2, 1, TestSpec::Operation::TYPE_RENDER, renderOperations[renderNdx] },
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_RENDER, renderOperations[renderNdx] },
-                               { TestSpec::API_GLES2, 1, TestSpec::Operation::TYPE_CREATE, createOperations[createNdx] },
-                               { TestSpec::API_GLES2, 1, TestSpec::Operation::TYPE_RENDER, renderOperations[renderNdx] },
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_RENDER, renderOperations[renderNdx] }
-                       });
+                       spec.contexts.push_back(TestSpec::API_GLES2);
+                       spec.contexts.push_back(TestSpec::API_GLES2);
+
+                       spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
+                       spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
+                       spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
+                       spec.operations.push_back(TestSpec::Operation(1, *createAction.action));
+                       spec.operations.push_back(TestSpec::Operation(1, *renderAction.action));
+                       spec.operations.push_back(TestSpec::Operation(0, *renderAction.action));
+
                        addChild(new ImageFormatCase(m_eglTestCtx, spec));
                }
        }
 }
 
-ModifyTests::ModifyTests (EglTestContext& eglTestCtx)
-       : TestCaseGroup (eglTestCtx, "modify", "EGLImage modifying tests")
+TestCaseGroup* createMultiContextRenderTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
 {
+       return new MultiContextRenderTests(eglTestCtx, name, desc);
 }
 
-void ModifyTests::init (void)
+class ModifyTests : public ImageTests
 {
-       GLES2ImageApi::Create createOperations[] = {
-               GLES2ImageApi::CREATE_TEXTURE2D_RGB8,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGB565,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA8,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA5_A1,
-               GLES2ImageApi::CREATE_TEXTURE2D_RGBA4,
-
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGBA4,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGB5_A1,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_RGB565,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_DEPTH16,
-               GLES2ImageApi::CREATE_RENDER_BUFFER_STENCIL
-       };
-
-       const char* createOperationsStr[] = {
-               "tex_rgb8",
-               "tex_rgb565",
-               "tex_rgba8",
-               "tex_rgba5_a1",
-               "tex_rgba4",
-
-               "renderbuffer_rgba4",
-               "renderbuffer_rgb5_a1",
-               "renderbuffer_rgb565",
-               "renderbuffer_depth16",
-               "renderbuffer_stencil"
-       };
+public:
+                                                               ModifyTests             (EglTestContext& eglTestCtx, const string& name, const string& desc)
+                                                                       : ImageTests(eglTestCtx, name, desc) {}
 
-       GLES2ImageApi::Modify modifyOperations[] = {
-               GLES2ImageApi::MODIFY_TEXSUBIMAGE_RGB8,
-               GLES2ImageApi::MODIFY_TEXSUBIMAGE_RGB565,
-               GLES2ImageApi::MODIFY_TEXSUBIMAGE_RGBA8,
-               GLES2ImageApi::MODIFY_TEXSUBIMAGE_RGBA5_A1,
-               GLES2ImageApi::MODIFY_TEXSUBIMAGE_RGBA4,
+       void                                            init                    (void);
 
-               GLES2ImageApi::MODIFY_RENDERBUFFER_CLEAR_COLOR,
-               GLES2ImageApi::MODIFY_RENDERBUFFER_CLEAR_DEPTH,
-               GLES2ImageApi::MODIFY_RENDERBUFFER_CLEAR_STENCIL,
-       };
+protected:
+       void                                            addModifyActions(void);
 
-       const char* modifyOperationsStr[] = {
-               "tex_subimage_rgb8",
-               "tex_subimage_rgb565",
-               "tex_subimage_rgba8",
-               "tex_subimage_rgba5_a1",
-               "tex_subimage_rgba4",
+       LabeledActions                          m_modifyActions;
+       GLES2ImageApi::RenderTryAll     m_renderAction;
+};
 
-               "renderbuffer_clear_color",
-               "renderbuffer_clear_depth",
-               "renderbuffer_clear_stencil",
-       };
+void ModifyTests::addModifyActions (void)
+{
+       m_modifyActions.add("tex_subimage_rgb8",                        MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,    GL_UNSIGNED_BYTE)));
+       m_modifyActions.add("tex_subimage_rgb565",                      MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGB,    GL_UNSIGNED_SHORT_5_6_5)));
+       m_modifyActions.add("tex_subimage_rgba8",                       MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,   GL_UNSIGNED_BYTE)));
+       m_modifyActions.add("tex_subimage_rgba5_a1",            MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,   GL_UNSIGNED_SHORT_5_5_5_1)));
+       m_modifyActions.add("tex_subimage_rgba4",                       MovePtr<Action>(new GLES2ImageApi::ModifyTexSubImage(GL_RGBA,   GL_UNSIGNED_SHORT_4_4_4_4)));
+
+       m_modifyActions.add("renderbuffer_clear_color",         MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearColor(tcu::Vec4(0.3f, 0.5f, 0.3f, 1.0f))));
+       m_modifyActions.add("renderbuffer_clear_depth",         MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearDepth(0.7f)));
+       m_modifyActions.add("renderbuffer_clear_stencil",       MovePtr<Action>(new GLES2ImageApi::ModifyRenderbufferClearStencil(78)));
+}
 
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(modifyOperations) == DE_LENGTH_OF_ARRAY(modifyOperationsStr));
-       DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(createOperations) == DE_LENGTH_OF_ARRAY(createOperationsStr));
+void ModifyTests::init (void)
+{
+       addCreateTexture2DActions("tex_");
+       addCreateRenderbufferActions();
+       addModifyActions();
 
-       for (int createNdx = 0; createNdx < DE_LENGTH_OF_ARRAY(createOperations); createNdx++)
+       for (int createNdx = 0; createNdx < m_createActions.size(); createNdx++)
        {
-               for (int modifyNdx = 0; modifyNdx < DE_LENGTH_OF_ARRAY(modifyOperations); modifyNdx++)
+               LabeledAction& createAction = m_createActions[createNdx];
+
+               for (int modifyNdx = 0; modifyNdx < m_modifyActions.size(); modifyNdx++)
                {
+                       LabeledAction& modifyAction = m_modifyActions[modifyNdx];
                        TestSpec spec;
-                       spec.name = "gles2_tex_sub_image";
-                       spec.desc = spec.name;
+                       spec.name = createAction.label + "_" + modifyAction.label;
+                       spec.desc = "gles2_tex_sub_image";
 
-                       PUSH_VALUES_TO_VECTOR(TestSpec::ApiContext, spec.contexts,
-                       {
-                               TestSpec::API_GLES2
-                       });
-                       PUSH_VALUES_TO_VECTOR(TestSpec::Operation, spec.operations,
-                       {
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_CREATE, createOperations[createNdx] },
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_RENDER, GLES2ImageApi::RENDER_TRY_ALL },
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_MODIFY, modifyOperations[modifyNdx] },
-                               { TestSpec::API_GLES2, 0, TestSpec::Operation::TYPE_RENDER, GLES2ImageApi::RENDER_TRY_ALL }
-                       });
+                       spec.contexts.push_back(TestSpec::API_GLES2);
+
+                       spec.operations.push_back(TestSpec::Operation(0, *createAction.action));
+                       spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
+                       spec.operations.push_back(TestSpec::Operation(0, *modifyAction.action));
+                       spec.operations.push_back(TestSpec::Operation(0, m_renderAction));
 
-                       spec.name = std::string(createOperationsStr[createNdx]) + "_" + modifyOperationsStr[modifyNdx];
                        addChild(new ImageFormatCase(m_eglTestCtx, spec));
                }
        }
 }
 
+TestCaseGroup* createModifyTests (EglTestContext& eglTestCtx, const string& name, const string& desc)
+{
+       return new ModifyTests(eglTestCtx, name, desc);
+}
+
 } // Image
 } // egl
 } // deqp
index 2a26ff5054efef10474094635c8ac5d6f83572f1..af3fcaf6ab12a7d419bd0c205aeaf266682e2a55 100644 (file)
@@ -33,26 +33,9 @@ namespace egl
 namespace Image
 {
 
-class SimpleCreationTests : public TestCaseGroup
-{
-public:
-                       SimpleCreationTests             (EglTestContext& eglTestCtx);
-       void    init                                            (void);
-};
-
-class ModifyTests : public TestCaseGroup
-{
-public:
-                       ModifyTests             (EglTestContext& eglTestCtx);
-       void    init                    (void);
-};
-
-class MultiContextRenderTests : public TestCaseGroup
-{
-public:
-                       MultiContextRenderTests         (EglTestContext& eglTestCtx);
-       void    init                                            (void);
-};
+TestCaseGroup* createSimpleCreationTests               (EglTestContext& eglTestCtx, const std::string& name, const std::string& desc);
+TestCaseGroup* createModifyTests                               (EglTestContext& eglTestCtx, const std::string& name, const std::string& desc);
+TestCaseGroup* createMultiContextRenderTests   (EglTestContext& eglTestCtx, const std::string& name, const std::string& desc);
 
 } // Image
 } // egl
index 6656d1e5e597ccbafcb5319b25e6a5dff86f9500..255cc9ad9addb3eb6e94b8d4367c9f4654c810a7 100644 (file)
 
 #include "teglImageTests.hpp"
 
+#include "teglImageUtil.hpp"
 #include "teglImageFormatTests.hpp"
 
+#include "egluExtensions.hpp"
 #include "egluNativeDisplay.hpp"
 #include "egluNativeWindow.hpp"
 #include "egluNativePixmap.hpp"
 #include "egluStrUtil.hpp"
+#include "egluUnique.hpp"
 #include "egluUtil.hpp"
+#include "egluGLUtil.hpp"
 
 #include "gluDefs.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluObjectWrapper.hpp"
 #include "gluStrUtil.hpp"
 
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+
 #include "tcuTestLog.hpp"
 #include "tcuCommandLine.hpp"
 
+#include "deUniquePtr.hpp"
 
 #include <algorithm>
 #include <sstream>
 #include <vector>
 #include <set>
 
-#include <EGL/eglext.h>
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
 using tcu::TestLog;
 
 using std::string;
 using std::vector;
 using std::set;
+using std::ostringstream;
+
+using de::MovePtr;
+using de::UniquePtr;
+using glu::ApiType;
+using glu::ContextType;
+using glu::Texture;
+using eglu::AttribMap;
+using eglu::NativeWindow;
+using eglu::NativePixmap;
+using eglu::UniqueImage;
+using eglu::UniqueSurface;
+using eglu::ScopedCurrentContext;
+
+using namespace glw;
 
 namespace deqp
 {
@@ -63,52 +83,8 @@ namespace egl
 namespace Image
 {
 
-bool checkExtensions (const tcu::egl::Display& dpy, const char** first, const char** last, vector<const char*>& unsupported)
-{
-       vector<string> extensions;
-       dpy.getExtensions(extensions);
-
-       set<string> extSet(extensions.begin(), extensions.end());
-
-       unsupported.clear();
-
-       for (const char** extIter = first; extIter != last; extIter++)
-       {
-               const char* ext = *extIter;
-
-               if (extSet.find(ext) == extSet.end())
-                       unsupported.push_back(ext);
-       }
-
-       return unsupported.size() == 0;
-}
-
-string join (const vector<const char*>& parts, const char* separator)
-{
-       std::ostringstream str;
-       for (std::vector<const char*>::const_iterator i = parts.begin(); i != parts.end(); i++)
-       {
-               if (i != parts.begin())
-                       str << separator;
-               str << *i;
-       }
-       return str.str();
-}
-
-void checkExtensions (const tcu::egl::Display& dpy, const char** first, const char** last)
-{
-       vector<const char*> unsupported;
-       if (!checkExtensions(dpy, first, last, unsupported))
-               throw tcu::NotSupportedError("Extension not supported", join(unsupported, " ").c_str(), __FILE__, __LINE__);
-}
-
-template <size_t N>
-void checkExtensions (const tcu::egl::Display& dpy, const char* (&extensions)[N])
-{
-       checkExtensions(dpy, &extensions[0], &extensions[N]);
-}
-
-#define CHECK_EXTENSIONS(EXTENSIONS) do { static const char* ext[] = EXTENSIONS; checkExtensions(m_eglTestCtx.getDisplay(), ext); } while (deGetFalse())
+#define CHECK_EXTENSION(DPY, EXTNAME) \
+       TCU_CHECK_AND_THROW(NotSupportedError, eglu::hasExtension(DPY, EXTNAME), (string("Unsupported extension: ") + EXTNAME).c_str())
 
 template <typename RetVal>
 RetVal checkCallError (tcu::TestContext& testCtx, const char* call, RetVal returnValue, EGLint expectError)
@@ -155,205 +131,133 @@ void checkCallReturn (tcu::TestContext& testCtx, const char* call, RetVal return
        }
 }
 
-void checkGLCall (tcu::TestContext& testCtx, const char* call, GLenum expectError)
-{
-       TestLog& log = testCtx.getLog();
-       log << TestLog::Message << call << TestLog::EndMessage;
-
-       GLenum error = glGetError();
-
-       if (error != expectError)
-       {
-               log << TestLog::Message << "  Fail: Error code mismatch! Expected " << glu::getErrorStr(expectError) << ", got " << glu::getErrorStr(error) << TestLog::EndMessage;
-
-               if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-                       testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code");
-       }
-}
-
-// \note These macros expect "TestContext m_testCtx" and "ExtFuncTable efTable" variables to be defined.
-#define CHECK_EXT_CALL_RET(CALL, EXPECT_RETURN_VALUE, EXPECT_ERROR)    checkCallReturn(m_testCtx, #CALL, efTable.CALL, (EXPECT_RETURN_VALUE), (EXPECT_ERROR))
-#define CHECK_EXT_CALL_ERR(CALL, EXPECT_ERROR)                                         checkCallError(m_testCtx, #CALL, efTable.CALL, (EXPECT_ERROR))
-#define CHECK_GL_EXT_CALL(CALL, EXPECT_ERROR)                                          do { efTable.CALL; checkGLCall(m_testCtx, #CALL, (EXPECT_ERROR)); } while (deGetFalse())
+// \note These macros expect "TestContext m_testCtx" to be defined.
+#define CHECK_EXT_CALL_RET(CALL, EXPECT_RETURN_VALUE, EXPECT_ERROR)    checkCallReturn(m_testCtx, #CALL, CALL, (EXPECT_RETURN_VALUE), (EXPECT_ERROR))
+#define CHECK_EXT_CALL_ERR(CALL, EXPECT_ERROR)                                         checkCallError(m_testCtx, #CALL, CALL, (EXPECT_ERROR))
 
-class ExtFuncTable
+class ImageTestCase : public TestCase, public glu::CallLogWrapper
 {
 public:
-       PFNEGLCREATEIMAGEKHRPROC                                                eglCreateImageKHR;
-       PFNEGLDESTROYIMAGEKHRPROC                                               eglDestroyImageKHR;
+                               ImageTestCase           (EglTestContext& eglTestCtx, ApiType api, const string& name, const string& desc)
+                                       : TestCase                              (eglTestCtx, name.c_str(), desc.c_str())
+                                       , glu::CallLogWrapper   (m_gl, m_testCtx.getLog())
+                                       , m_api                                 (api) {}
 
-       PFNGLEGLIMAGETARGETTEXTURE2DOESPROC                             glEGLImageTargetTexture2DOES;
-       PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC   glEGLImageTargetRenderbufferStorageOES;
+       void            init                            (void)
+       {
+               m_eglTestCtx.getGLFunctions(m_gl, m_api, vector<const char*>(1, "GL_OES_EGL_image"));
+               m_imageExt = de::newMovePtr<eglu::ImageFunctions>(eglu::getImageFunctions(m_eglTestCtx.getEGLDisplay()));
+       }
 
-       ExtFuncTable (void)
+protected:
+       EGLImageKHR     eglCreateImageKHR       (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attribList)
        {
-               // EGL_KHR_image_base
-               eglCreateImageKHR                                               = (PFNEGLCREATEIMAGEKHRPROC)                                            eglGetProcAddress("eglCreateImageKHR");
-               eglDestroyImageKHR                                              = (PFNEGLDESTROYIMAGEKHRPROC)                                           eglGetProcAddress("eglDestroyImageKHR");
+               return m_imageExt->createImage(dpy, ctx, target, buffer, attribList);
+       }
 
-               // OES_EGL_image
-               glEGLImageTargetTexture2DOES                    = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)                         eglGetProcAddress("glEGLImageTargetTexture2DOES");
-               glEGLImageTargetRenderbufferStorageOES  = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)       eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
+       EGLBoolean      eglDestroyImageKHR      (EGLDisplay dpy, EGLImageKHR image)
+       {
+               return m_imageExt->destroyImage(dpy, image);
        }
+
+       glw::Functions                                  m_gl;
+       MovePtr<eglu::ImageFunctions>   m_imageExt;
+       ApiType                                                 m_api;
 };
 
-class InvalidCreateImage : public TestCase
+class InvalidCreateImage : public ImageTestCase
 {
 public:
        InvalidCreateImage (EglTestContext& eglTestCtx)
-               : TestCase(eglTestCtx, "invalid_create_image", "eglCreateImageKHR() with invalid arguments")
+               : ImageTestCase(eglTestCtx, ApiType::es(2, 0), "invalid_create_image", "eglCreateImageKHR() with invalid arguments")
        {
        }
 
+       void checkCreate (const char* desc, EGLDisplay dpy, const char* dpyStr, EGLContext context, const char* ctxStr, EGLenum source, const char* srcStr, EGLint expectError);
+
        IterateResult iterate (void)
        {
-               EGLDisplay              dpy = m_eglTestCtx.getDisplay().getEGLDisplay();
-               TestLog&                log     = m_testCtx.getLog();
-               ExtFuncTable    efTable;
+               const EGLDisplay                        dpy             = m_eglTestCtx.getEGLDisplay();
 
-               CHECK_EXTENSIONS({ "EGL_KHR_image_base" });
+#define CHECK_CREATE(MSG, DPY, CONTEXT, SOURCE, ERR) checkCreate(MSG, DPY, #DPY, CONTEXT, #CONTEXT, SOURCE, #SOURCE, ERR)
+               CHECK_CREATE("Testing bad display (-1)...", (EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, EGL_BAD_DISPLAY);
+               CHECK_CREATE("Testing bad context (-1)...", dpy, (EGLContext)-1, EGL_NONE, EGL_BAD_CONTEXT);
+               CHECK_CREATE("Testing bad source (-1)...", dpy, EGL_NO_CONTEXT, (EGLenum)-1, EGL_BAD_PARAMETER);
+#undef CHECK_CREATE
 
-               // Initialize result to pass.
                m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-
-               log << TestLog::Message << "Testing bad display (-1)..." << TestLog::EndMessage;
-               CHECK_EXT_CALL_RET(eglCreateImageKHR((EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, 0, DE_NULL),
-                                                  EGL_NO_IMAGE_KHR, EGL_BAD_DISPLAY);
-
-               log << TestLog::Message << "Testing bad context (-1)..." << TestLog::EndMessage;
-               CHECK_EXT_CALL_RET(eglCreateImageKHR(dpy, (EGLContext)-1, EGL_NONE, 0, DE_NULL),
-                                                  EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT);
-
-               log << TestLog::Message << "Testing bad parameter (-1).." << TestLog::EndMessage;
-               CHECK_EXT_CALL_RET(eglCreateImageKHR(dpy, EGL_NO_CONTEXT, (EGLenum)-1, 0, DE_NULL),
-                                                  EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER);
-
                return STOP;
        }
+
 };
 
-class GLES2Context
+void InvalidCreateImage::checkCreate (const char* msg, EGLDisplay dpy, const char* dpyStr, EGLContext context, const char* ctxStr, EGLenum source, const char* srcStr, EGLint expectError)
 {
-public:
-       GLES2Context (EglTestContext& eglTestCtx, EGLint configId, int width, int height)
-               : m_eglTestCtx  (eglTestCtx)
-               , m_config              (getConfigById(eglTestCtx.getDisplay(), configId))
-               , m_context             (eglTestCtx.getDisplay(), m_config, m_ctxAttrs, EGL_OPENGL_ES_API)
-               , m_window              (DE_NULL)
-               , m_pixmap              (DE_NULL)
-               , m_surface             (DE_NULL)
+       m_testCtx.getLog() << TestLog::Message << msg << TestLog::EndMessage;
        {
-               tcu::egl::Display&      dpy                             = eglTestCtx.getDisplay();
-               EGLint                          surfaceTypeBits = dpy.getConfigAttrib(m_config, EGL_SURFACE_TYPE);
+               const EGLImageKHR       image = m_imageExt->createImage(dpy, context, source, 0, DE_NULL);
+               ostringstream           call;
 
-               if (surfaceTypeBits & EGL_PBUFFER_BIT)
-               {
-                       EGLint pbufferAttrs[] =
-                       {
-                               EGL_WIDTH,              width,
-                               EGL_HEIGHT,             height,
-                               EGL_NONE
-                       };
-
-                       m_surface = new tcu::egl::PbufferSurface(dpy, m_config, pbufferAttrs);
-               }
-               else if (surfaceTypeBits & EGL_WINDOW_BIT)
-               {
-                       m_window        = eglTestCtx.createNativeWindow(dpy.getEGLDisplay(), m_config, DE_NULL, width, height, eglu::parseWindowVisibility(eglTestCtx.getTestContext().getCommandLine()));
-                       m_surface       = new tcu::egl::WindowSurface(dpy, eglu::createWindowSurface(eglTestCtx.getNativeDisplay(), *m_window, dpy.getEGLDisplay(), m_config, DE_NULL));
-               }
-               else if (surfaceTypeBits & EGL_PIXMAP_BIT)
-               {
-                       m_pixmap        = eglTestCtx.createNativePixmap(dpy.getEGLDisplay(), m_config, DE_NULL, width, height);
-                       m_surface       = new tcu::egl::PixmapSurface(dpy, eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *m_pixmap, dpy.getEGLDisplay(), m_config, DE_NULL));
-               }
-               else
-                       TCU_FAIL("No valid surface types supported in config");
-
-               m_context.makeCurrent(*m_surface, *m_surface);
+               call << "eglCreateImage(" << dpyStr << ", " << ctxStr << ", " << srcStr << ", 0, DE_NULL)";
+               checkCallReturn(m_testCtx, call.str().c_str(), image, EGL_NO_IMAGE_KHR, expectError);
        }
+}
 
-       ~GLES2Context (void)
-       {
-               eglMakeCurrent(m_eglTestCtx.getDisplay().getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 
-               delete m_window;
-               delete m_pixmap;
-               delete m_surface;
-       }
 
-       EGLDisplay getEglDisplay (void)
-       {
-               return m_eglTestCtx.getDisplay().getEGLDisplay();
-       }
+EGLConfig chooseConfig (EGLDisplay display, ApiType apiType)
+{
+       AttribMap                               attribs;
+       vector<EGLConfig>               configs;
+       // Prefer configs in order: pbuffer, window, pixmap
+       static const EGLenum    s_surfaceTypes[] = { EGL_PBUFFER_BIT, EGL_WINDOW_BIT, EGL_PIXMAP_BIT };
 
-       EGLContext getEglContext (void)
-       {
-               return m_context.getEGLContext();
-       }
+       attribs[EGL_RENDERABLE_TYPE] = eglu::apiRenderableType(apiType);
 
-       // Helper for selecting config.
-       static EGLint getConfigIdForApi (const vector<eglu::ConfigInfo>& configInfos, EGLint apiBits)
+       for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_surfaceTypes); ++ndx)
        {
-               EGLint  windowCfg       = 0;
-               EGLint  pixmapCfg       = 0;
-               EGLint  pbufferCfg      = 0;
+               attribs[EGL_SURFACE_TYPE] = s_surfaceTypes[ndx];
+               configs = eglu::chooseConfig(display, attribs);
 
-               for (vector<eglu::ConfigInfo>::const_iterator cfgIter = configInfos.begin(); cfgIter != configInfos.end(); cfgIter++)
-               {
-                       if ((cfgIter->renderableType & apiBits) == 0)
-                               continue;
-
-                       if (windowCfg == 0 && (cfgIter->surfaceType & EGL_WINDOW_BIT) != 0)
-                               windowCfg = cfgIter->configId;
-
-                       if (pixmapCfg == 0 && (cfgIter->surfaceType & EGL_PIXMAP_BIT) != 0)
-                               pixmapCfg = cfgIter->configId;
-
-                       if (pbufferCfg == 0 && (cfgIter->surfaceType & EGL_PBUFFER_BIT) != 0)
-                               pbufferCfg = cfgIter->configId;
-
-                       if (windowCfg && pixmapCfg && pbufferCfg)
-                               break;
-               }
-
-               // Prefer configs in order: pbuffer, window, pixmap
-               if (pbufferCfg)
-                       return pbufferCfg;
-               else if (windowCfg)
-                       return windowCfg;
-               else if (pixmapCfg)
-                       return pixmapCfg;
-               else
-                       throw tcu::NotSupportedError("No compatible EGL configs found", "", __FILE__, __LINE__);
+               if (!configs.empty())
+                       return configs.front();
        }
 
-private:
-       static EGLConfig getConfigById (const tcu::egl::Display& dpy, EGLint configId)
+       TCU_THROW(NotSupportedError, "No compatible EGL configs found");
+       return (EGLConfig)0;
+}
+
+class Context
+{
+public:
+                                                               Context (EglTestContext& eglTestCtx, ContextType ctxType, int width, int height)
+                                                                       : m_eglTestCtx  (eglTestCtx)
+                                                                       , m_config              (chooseConfig(eglTestCtx.getEGLDisplay(), ctxType.getAPI()))
+                                                                       , m_context             (eglu::createGLContext(eglTestCtx.getEGLDisplay(), m_config, ctxType))
+                                                                       , m_surface             (createSurface(eglTestCtx, m_config, width, height))
+                                                                       , m_current             (eglTestCtx.getEGLDisplay(), m_surface->get(), m_surface->get(), m_context)
        {
-               EGLint attributes[] = { EGL_CONFIG_ID, configId, EGL_NONE };
-               vector<EGLConfig> configs;
-               dpy.chooseConfig(attributes, configs);
-               TCU_CHECK(configs.size() == 1);
-               return configs[0];
+               m_eglTestCtx.getGLFunctions(m_gl, ctxType.getAPI());
        }
 
-       static const EGLint                     m_ctxAttrs[];
+       EGLConfig                                       getConfig               (void) const { return m_config; }
+       EGLDisplay                                      getEglDisplay   (void) const { return m_eglTestCtx.getEGLDisplay(); }
+       EGLContext                                      getEglContext   (void) const { return m_context; }
+       const glw::Functions&           gl                              (void) const { return m_gl; }
 
+private:
        EglTestContext&                         m_eglTestCtx;
        EGLConfig                                       m_config;
-       tcu::egl::Context                       m_context;
-       eglu::NativeWindow*                     m_window;
-       eglu::NativePixmap*                     m_pixmap;
-       tcu::egl::Surface*                      m_surface;
+       EGLContext                                      m_context;
+       UniquePtr<ManagedSurface>       m_surface;
+       ScopedCurrentContext            m_current;
+       glw::Functions                          m_gl;
 
-                                                               GLES2Context    (const GLES2Context&);
-       GLES2Context&                           operator=               (const GLES2Context&);
+                                                               Context                 (const Context&);
+       Context&                                        operator=               (const Context&);
 };
 
-const EGLint GLES2Context::m_ctxAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-
-class CreateImageGLES2 : public TestCase
+class CreateImageGLES2 : public ImageTestCase
 {
 public:
        static const char* getTargetName (EGLint target)
@@ -389,164 +293,73 @@ public:
                }
        }
 
-       CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum storage, bool useTexLevel0 = false)
-               : TestCase                      (eglTestCtx, (string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(storage) + (useTexLevel0 ? "_level0_only" : "")).c_str(), "Create EGLImage from GLES2 object")
-               , m_target                      (target)
-               , m_storage                     (storage)
-               , m_useTexLevel0        (useTexLevel0)
+       MovePtr<ImageSource> getImageSource (EGLint target, GLenum format)
        {
-       }
-
-       IterateResult iterate (void)
-       {
-               TestLog&                log     = m_testCtx.getLog();
-               ExtFuncTable    efTable;
-
-               if (m_target == EGL_GL_TEXTURE_2D_KHR)
-                       CHECK_EXTENSIONS({"EGL_KHR_gl_texture_2D_image"});
-               else if (m_target == EGL_GL_RENDERBUFFER_KHR)
-                       CHECK_EXTENSIONS({"EGL_KHR_gl_renderbuffer_image"});
-               else
-                       CHECK_EXTENSIONS({"EGL_KHR_gl_texture_cubemap_image"});
-
-               // Initialize result.
-               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-
-               // Create GLES2 context
-               EGLint configId = GLES2Context::getConfigIdForApi(m_eglTestCtx.getConfigs(), EGL_OPENGL_ES2_BIT);
-               log << TestLog::Message << "Using EGL config " << configId << TestLog::EndMessage;
-
-               GLES2Context context(m_eglTestCtx, configId, 64, 64);
-
-               switch (m_target)
+               switch (target)
                {
                        case EGL_GL_TEXTURE_2D_KHR:
-                       {
-                               deUint32 tex = 1;
-                               GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, tex));
-
-                               // Specify mipmap level 0
-                               GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, m_storage, 64, 64, 0, m_storage, GL_UNSIGNED_BYTE, DE_NULL));
-
-                               if (!m_useTexLevel0)
-                               {
-                                       // Set minification filter to linear. This makes the texture complete.
-                                       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
-                               }
-                               // Else spec allows using incomplete texture when miplevel 0 is only used and specified.
-
-                               // Create EGL image
-                               EGLint          attribs[]       = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
-                               EGLImageKHR     image           = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)tex, attribs), EGL_SUCCESS);
-                               if (image == EGL_NO_IMAGE_KHR)
-                               {
-                                       log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
-
-                                       if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-                                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
-                               }
-
-                               // Destroy image
-                               CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
-
-                               // Destroy texture object
-                               GLU_CHECK_CALL(glDeleteTextures(1, &tex));
-
-                               break;
-                       }
-
                        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
                        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
                        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
                        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
                        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
                        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
-                       {
-                               deUint32 tex = 1;
-                               GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, tex));
-
-                               // Specify mipmap level 0 for all faces
-                               GLenum faces[] =
-                               {
-                                       GL_TEXTURE_CUBE_MAP_POSITIVE_X,
-                                       GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
-                                       GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
-                                       GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
-                                       GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-                                       GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
-                               };
-                               for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++)
-                                       GLU_CHECK_CALL(glTexImage2D(faces[faceNdx], 0, m_storage, 64, 64, 0, m_storage, GL_UNSIGNED_BYTE, DE_NULL));
-
-                               if (!m_useTexLevel0)
-                               {
-                                       // Set minification filter to linear.
-                                       GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
-                               }
-
-                               // Create EGL image
-                               EGLint          attribs[]       = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE };
-                               EGLImageKHR     image           = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), m_target, (EGLClientBuffer)(deUintptr)tex, attribs), EGL_SUCCESS);
-                               if (image == EGL_NO_IMAGE_KHR)
-                               {
-                                       log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
-
-                                       if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-                                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
-                               }
-
-                               // Destroy image
-                               CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
-
-                               // Destroy texture object
-                               GLU_CHECK_CALL(glDeleteTextures(1, &tex));
-
-                               break;
-                       }
-
+                               return createTextureImageSource(target, format, GL_UNSIGNED_BYTE);
                        case EGL_GL_RENDERBUFFER_KHR:
-                       {
-                               // Create renderbuffer.
-                               deUint32 rbo = 1;
-                               GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, rbo));
+                               return createRenderbufferImageSource(format);
+                       default:
+                               DE_ASSERT(!"Impossible");
+                               return MovePtr<ImageSource>();
+               }
+       }
+
+       CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum storage, bool useTexLevel0 = false)
+               : ImageTestCase         (eglTestCtx, ApiType::es(2, 0), string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(storage) + (useTexLevel0 ? "_level0_only" : ""), "Create EGLImage from GLES2 object")
+               , m_source                      (getImageSource(target, storage))
+       {
+       }
+
+       IterateResult iterate (void)
+       {
+               const EGLDisplay        dpy                     = m_eglTestCtx.getEGLDisplay();
 
-                               // Specify storage.
-                               GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, m_storage, 64, 64));
+               if (eglu::getVersion(dpy) < eglu::Version(1, 5))
+                       CHECK_EXTENSION(dpy, m_source->getRequiredExtension());
 
-                               // Create EGL image
-                               EGLImageKHR image = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_RENDERBUFFER_KHR, (EGLClientBuffer)(deUintptr)rbo, DE_NULL), EGL_SUCCESS);
-                               if (image == EGL_NO_IMAGE_KHR)
-                               {
-                                       log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
+               // Initialize result.
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
 
-                                       if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-                                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
-                               }
+               // Create GLES2 context
+               TestLog&                                log                             = m_testCtx.getLog();
+               const ContextType               contextType             (ApiType::es(2, 0));
+               Context                                 context                 (m_eglTestCtx, contextType, 64, 64);
+               const EGLContext                eglContext              = context.getEglContext();
 
-                               // Destroy image
-                               CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
+               log << TestLog::Message << "Using EGL config " << eglu::getConfigID(dpy, context.getConfig()) << TestLog::EndMessage;
 
-                               // Destroy texture object
-                               GLU_CHECK_CALL(glDeleteRenderbuffers(1, &rbo));
+               UniquePtr<ClientBuffer> clientBuffer    (m_source->createBuffer(context.gl()));
+               const EGLImageKHR               image                   = m_source->createImage(*m_imageExt, dpy, eglContext, clientBuffer->get());
 
-                               break;
-                       }
+               if (image == EGL_NO_IMAGE_KHR)
+               {
+                       log << TestLog::Message << "  Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage;
 
-                       default:
-                               DE_ASSERT(DE_FALSE);
-                               break;
+                       if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR");
                }
 
+               // Destroy image
+               CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS);
+
                return STOP;
        }
 
 private:
-       EGLint  m_target;
-       GLenum  m_storage;
-       bool    m_useTexLevel0;
+       UniquePtr<ImageSource>  m_source;
+       bool                                    m_useTexLevel0;
 };
 
-class ImageTargetGLES2 : public TestCase
+class ImageTargetGLES2 : public ImageTestCase
 {
 public:
        static const char* getTargetName (GLenum target)
@@ -562,27 +375,25 @@ public:
        }
 
        ImageTargetGLES2 (EglTestContext& eglTestCtx, GLenum target)
-               : TestCase      (eglTestCtx, (string("image_target_gles2_") + getTargetName(target)).c_str(), "Use EGLImage as GLES2 object")
-               , m_target      (target)
+               : ImageTestCase (eglTestCtx, ApiType::es(2, 0), string("image_target_gles2_") + getTargetName(target), "Use EGLImage as GLES2 object")
+               , m_target              (target)
        {
        }
 
        IterateResult iterate (void)
        {
                TestLog&                log     = m_testCtx.getLog();
-               ExtFuncTable    efTable;
 
                // \todo [2011-07-21 pyry] Try all possible EGLImage sources
-               CHECK_EXTENSIONS({"EGL_KHR_gl_texture_2D_image"});
+               CHECK_EXTENSION(m_eglTestCtx.getEGLDisplay(), "EGL_KHR_gl_texture_2D_image");
 
                // Initialize result.
                m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
 
                // Create GLES2 context
-               EGLint configId = GLES2Context::getConfigIdForApi(m_eglTestCtx.getConfigs(), EGL_OPENGL_ES2_BIT);
-               log << TestLog::Message << "Using EGL config " << configId << TestLog::EndMessage;
 
-               GLES2Context context(m_eglTestCtx, configId, 64, 64);
+               Context context(m_eglTestCtx, ContextType(ApiType::es(2, 0)), 64, 64);
+               log << TestLog::Message << "Using EGL config " << eglu::getConfigID(context.getEglDisplay(), context.getConfig()) << TestLog::EndMessage;
 
                // Check for OES_EGL_image
                {
@@ -591,8 +402,8 @@ public:
                        if (string(glExt).find("GL_OES_EGL_image") == string::npos)
                                throw tcu::NotSupportedError("Extension not supported", "GL_OES_EGL_image", __FILE__, __LINE__);
 
-                       TCU_CHECK(efTable.glEGLImageTargetTexture2DOES);
-                       TCU_CHECK(efTable.glEGLImageTargetRenderbufferStorageOES);
+                       TCU_CHECK(m_gl.eglImageTargetTexture2DOES);
+                       TCU_CHECK(m_gl.eglImageTargetRenderbufferStorageOES);
                }
 
                // Create GL_TEXTURE_2D and EGLImage from it.
@@ -621,7 +432,7 @@ public:
 
                        deUint32 dstTex = 2;
                        GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, dstTex));
-                       CHECK_GL_EXT_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image), GL_NO_ERROR);
+                       GLU_CHECK_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image));
                        GLU_CHECK_CALL(glDeleteTextures(1, &dstTex));
                }
                else
@@ -632,7 +443,7 @@ public:
 
                        deUint32 dstRbo = 2;
                        GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, dstRbo));
-                       CHECK_GL_EXT_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image), GL_NO_ERROR);
+                       GLU_CHECK_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image));
                        GLU_CHECK_CALL(glDeleteRenderbuffers(1, &dstRbo));
                }
 
@@ -652,10 +463,7 @@ private:
 class ApiTests : public TestCaseGroup
 {
 public:
-       ApiTests (EglTestContext& eglTestCtx)
-               : TestCaseGroup(eglTestCtx, "api", "EGLImage API tests")
-       {
-       }
+       ApiTests (EglTestContext& eglTestCtx, const string& name, const string& desc) : TestCaseGroup(eglTestCtx, name.c_str(), desc.c_str()) {}
 
        void init (void)
        {
@@ -704,10 +512,10 @@ ImageTests::~ImageTests (void)
 
 void ImageTests::init (void)
 {
-       addChild(new Image::ApiTests(m_eglTestCtx));
-       addChild(new Image::SimpleCreationTests(m_eglTestCtx));
-       addChild(new Image::ModifyTests(m_eglTestCtx));
-       addChild(new Image::MultiContextRenderTests(m_eglTestCtx));
+       addChild(new Image::ApiTests(m_eglTestCtx, "api", "EGLImage API tests"));
+       addChild(Image::createSimpleCreationTests(m_eglTestCtx, "create", "EGLImage creation tests"));
+       addChild(Image::createModifyTests(m_eglTestCtx, "modify", "EGLImage modifying tests"));
+       addChild(Image::createMultiContextRenderTests(m_eglTestCtx, "render_multiple_contexts", "EGLImage render tests on multiple contexts"));
 }
 
 } // egl
diff --git a/modules/egl/teglImageUtil.cpp b/modules/egl/teglImageUtil.cpp
new file mode 100644 (file)
index 0000000..4a61ded
--- /dev/null
@@ -0,0 +1,375 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2014 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 Common utilities for EGL images.
+ *//*--------------------------------------------------------------------*/
+
+
+#include "teglImageUtil.hpp"
+
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+
+#include "egluGLUtil.hpp"
+#include "egluNativeWindow.hpp"
+#include "egluNativePixmap.hpp"
+
+#include "glwEnums.hpp"
+
+#include "gluObjectWrapper.hpp"
+#include "gluTextureUtil.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+namespace Image
+{
+
+using std::string;
+using std::vector;
+
+using de::UniquePtr;
+using de::MovePtr;
+
+using tcu::TextureFormat;
+using tcu::Texture2D;
+using tcu::Vec4;
+
+using glu::Framebuffer;
+using glu::Texture;
+
+using eglu::AttribMap;
+using eglu::UniqueSurface;
+using eglu::NativeWindow;
+using eglu::NativePixmap;
+
+using namespace glw;
+
+enum {
+       IMAGE_WIDTH             = 64,
+       IMAGE_HEIGHT    = 64,
+};
+
+
+template <typename T>
+struct NativeSurface : public ManagedSurface
+{
+public:
+       explicit                NativeSurface   (MovePtr<UniqueSurface> surface,
+                                                                        MovePtr<T>                             native)
+                                               : ManagedSurface        (surface)
+                                               , m_native                      (native) {}
+
+private:
+       UniquePtr<T>    m_native;
+};
+
+typedef NativeSurface<NativeWindow> NativeWindowSurface;
+typedef NativeSurface<NativePixmap> NativePixmapSurface;
+
+MovePtr<ManagedSurface> createSurface (EglTestContext& eglTestCtx, EGLConfig config, int width, int height)
+{
+       EGLDisplay      dpy                             = eglTestCtx.getEGLDisplay();
+       EGLint          surfaceTypeBits = eglu::getConfigAttribInt(dpy, config, EGL_SURFACE_TYPE);
+
+       if (surfaceTypeBits & EGL_PBUFFER_BIT)
+       {
+               static const EGLint attribs[]   = { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE };
+               const EGLSurface        surface         = eglCreatePbufferSurface(dpy, config, attribs);
+
+               EGLU_CHECK();
+
+               return de::newMovePtr<ManagedSurface>(de::newMovePtr<UniqueSurface>(dpy, surface));
+       }
+       else if (surfaceTypeBits & EGL_WINDOW_BIT)
+       {
+               MovePtr<NativeWindow>   window  (eglTestCtx.createNativeWindow(dpy, config, DE_NULL, width, height));
+               const EGLSurface                surface = eglu::createWindowSurface(eglTestCtx.getNativeDisplay(), *window, dpy, config, DE_NULL);
+
+               return MovePtr<ManagedSurface>(new NativeWindowSurface(de::newMovePtr<UniqueSurface>(dpy, surface), window));
+       }
+       else if (surfaceTypeBits & EGL_PIXMAP_BIT)
+       {
+               MovePtr<NativePixmap>   pixmap  (eglTestCtx.createNativePixmap(dpy, config, DE_NULL, width, height));
+               const EGLSurface                surface = eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *pixmap, dpy, config, DE_NULL);
+
+               return MovePtr<ManagedSurface>(new NativePixmapSurface(de::newMovePtr<UniqueSurface>(dpy, surface), pixmap));
+       }
+       else
+               TCU_FAIL("No valid surface types supported in config");
+}
+
+class TextureClientBuffer : public ClientBuffer
+{
+public:
+                                               TextureClientBuffer     (const glw::Functions& gl) : m_texture (gl) {}
+       GLuint                          getName                         (void) const { return *m_texture; }
+
+private:
+       glu::Texture            m_texture;
+};
+
+EGLImageKHR ImageSource::createImage    (const eglu::ImageFunctions& imgExt, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const
+{
+       const vector<EGLint>    attribs = eglu::attribMapToVector(getCreateAttribs());
+       const EGLImageKHR               image   = imgExt.createImage(dpy, ctx, getSource(), clientBuffer,
+                                                                                                                &attribs.front());
+       EGLU_CHECK_MSG("eglCreateImageKHR()");
+
+       return image;
+}
+
+class TextureImageSource : public ImageSource
+{
+public:
+                                                       TextureImageSource      (GLenum format, GLenum type, bool useTexLevel0) : m_format(format), m_type(type), m_useTexLevel0(useTexLevel0) {}
+       AttribMap                               getCreateAttribs        (void) const;
+       MovePtr<ClientBuffer>   createBuffer            (const glw::Functions& gl, Texture2D* reference) const;
+
+protected:
+       virtual void                    initTexture                     (const glw::Functions& gl) const = 0;
+       virtual GLenum                  getGLTarget                     (void) const = 0;
+
+       GLenum                                  m_format;
+       GLenum                                  m_type;
+       bool                                    m_useTexLevel0;
+};
+
+AttribMap TextureImageSource::getCreateAttribs (void) const
+{
+       AttribMap ret;
+
+       ret[EGL_GL_TEXTURE_LEVEL_KHR] = 0;
+
+       return ret;
+}
+
+
+MovePtr<ClientBuffer> TextureImageSource::createBuffer (const glw::Functions& gl, Texture2D* ref) const
+{
+       MovePtr<TextureClientBuffer>    clientBuffer    (new TextureClientBuffer(gl));
+       const GLuint                                    texture                 = clientBuffer->getName();
+       const GLenum                                    target                  = getGLTarget();
+
+       GLU_CHECK_GLW_CALL(gl, bindTexture(target, texture));
+       initTexture(gl);
+
+       if (!m_useTexLevel0)
+       {
+               // Set minification filter to linear. This makes the texture complete.
+               GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+       }
+
+       if (ref != DE_NULL)
+       {
+               Texture         srcTex          (gl);
+               GLenum          imgTarget       = eglu::getImageGLTarget(getSource());
+
+               *ref = Texture2D(glu::mapGLTransferFormat(m_format, m_type), IMAGE_WIDTH, IMAGE_HEIGHT);
+               ref->allocLevel(0);
+               tcu::fillWithComponentGradients(ref->getLevel(0),
+                                                                               tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
+                                                                               tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+
+               GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+               GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+               GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+               GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+
+               GLU_CHECK_GLW_CALL(gl, texImage2D(imgTarget, 0, m_format, IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                                 0, m_format, m_type, ref->getLevel(0).getDataPtr()));
+       }
+       GLU_CHECK_GLW_CALL(gl, bindTexture(target, 0));
+       return MovePtr<ClientBuffer>(clientBuffer);
+}
+
+class Texture2DImageSource : public TextureImageSource
+{
+public:
+                                       Texture2DImageSource    (GLenum format, GLenum type, bool useTexLevel0) : TextureImageSource(format, type, useTexLevel0) {}
+       EGLenum                 getSource                               (void) const { return EGL_GL_TEXTURE_2D_KHR; }
+       string                  getRequiredExtension    (void) const { return "EGL_KHR_gl_texture_2D_image"; }
+       GLenum                  getGLTarget                             (void) const { return GL_TEXTURE_2D; }
+
+protected:
+       void                    initTexture                             (const glw::Functions& gl) const;
+};
+
+void Texture2DImageSource::initTexture (const glw::Functions& gl) const
+{
+       // Specify mipmap level 0
+       GLU_CHECK_CALL_ERROR(gl.texImage2D(GL_TEXTURE_2D, 0, m_format, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL),
+                                                gl.getError());
+}
+
+class TextureCubeMapImageSource : public TextureImageSource
+{
+public:
+                                       TextureCubeMapImageSource       (EGLenum source, GLenum format, GLenum type, bool useTexLevel0) : TextureImageSource(format, type, useTexLevel0), m_source(source) {}
+       EGLenum                 getSource                                       (void) const { return m_source; }
+       string                  getRequiredExtension            (void) const { return "EGL_KHR_gl_texture_cubemap_image"; }
+       GLenum                  getGLTarget                                     (void) const { return GL_TEXTURE_CUBE_MAP; }
+
+protected:
+       void                    initTexture                                     (const glw::Functions& gl) const;
+
+       EGLenum                 m_source;
+};
+
+void TextureCubeMapImageSource::initTexture (const glw::Functions& gl) const
+{
+       // Specify mipmap level 0 for all faces
+       static const GLenum faces[] =
+       {
+               GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+               GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+               GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+               GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+               GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+               GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+       };
+
+       for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++)
+               GLU_CHECK_GLW_CALL(gl, texImage2D(faces[faceNdx], 0, m_format, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL));
+}
+
+class RenderbufferClientBuffer : public ClientBuffer
+{
+public:
+                                               RenderbufferClientBuffer        (const glw::Functions& gl) : m_rbo (gl) {}
+       GLuint                          getName                                         (void) const { return *m_rbo; }
+
+private:
+       glu::Renderbuffer       m_rbo;
+};
+
+class RenderbufferImageSource : public ImageSource
+{
+public:
+                                                       RenderbufferImageSource (GLenum format) : m_format(format) {}
+
+       EGLenum                                 getSource                               (void) const    { return EGL_GL_RENDERBUFFER_KHR; }
+       string                                  getRequiredExtension    (void) const    { return "EGL_KHR_gl_renderbuffer_image"; }
+       AttribMap                               getCreateAttribs                (void) const    { return AttribMap(); }
+       MovePtr<ClientBuffer>   createBuffer                    (const glw::Functions& gl, Texture2D* reference) const;
+
+private:
+       GLenum                                  m_format;
+};
+
+void initializeStencilRbo(const glw::Functions& gl, GLuint rbo, GLint value, Texture2D& ref)
+{
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                                                                                  GL_RENDERBUFFER, rbo));
+       GLU_CHECK_GLW_CALL(gl, clearStencil(value));
+       GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                                                                                  GL_RENDERBUFFER, 0));
+
+       tcu::clearStencil(ref.getLevel(0), value);
+}
+
+void initializeDepthRbo(const glw::Functions& gl, GLuint rbo, GLfloat value, Texture2D& ref)
+{
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                                                                                  GL_RENDERBUFFER, rbo));
+       GLU_CHECK_GLW_CALL(gl, clearDepthf(value));
+       GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                                                                                  GL_RENDERBUFFER, 0));
+
+       tcu::clearDepth(ref.getLevel(0), value);
+}
+
+void initializeColorRbo(const glw::Functions& gl, GLuint rbo, GLfloat r, GLfloat g, GLfloat b, GLfloat a, Texture2D& ref)
+{
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                                                                                  GL_RENDERBUFFER, rbo));
+       GLU_CHECK_GLW_CALL(gl, clearColor(r, g, b, a));
+       GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
+       GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                                                                                  GL_RENDERBUFFER, 0));
+
+       tcu::clear(ref.getLevel(0), Vec4(r, g, b, a));
+}
+
+MovePtr<ClientBuffer> RenderbufferImageSource::createBuffer (const glw::Functions& gl, Texture2D* ref) const
+{
+       MovePtr<RenderbufferClientBuffer>       buffer  (new RenderbufferClientBuffer(gl));
+       const GLuint                                            rbo             = buffer->getName();
+
+       GLU_CHECK_CALL_ERROR(gl.bindRenderbuffer(GL_RENDERBUFFER, rbo), gl.getError());
+
+       // Specify storage.
+       GLU_CHECK_CALL_ERROR(gl.renderbufferStorage(GL_RENDERBUFFER, m_format, 64, 64), gl.getError());
+
+       if (ref != DE_NULL)
+       {
+               Framebuffer                     fbo                     (gl);
+               const TextureFormat     texFormat       = glu::mapGLInternalFormat(m_format);
+
+               *ref = tcu::Texture2D(texFormat, 64, 64);
+               ref->allocLevel(0);
+
+               gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
+               switch (m_format)
+               {
+                       case GL_STENCIL_INDEX8:
+                               initializeStencilRbo(gl, rbo, 235, *ref);
+                               break;
+                       case GL_DEPTH_COMPONENT16:
+                               initializeDepthRbo(gl, rbo, 0.5f, *ref);
+                               break;
+                       case GL_RGBA4:
+                               initializeColorRbo(gl, rbo, 0.9f, 0.5f, 0.65f, 1.0f, *ref);
+                               break;
+                       case GL_RGB5_A1:
+                               initializeColorRbo(gl, rbo, 0.5f, 0.7f, 0.65f, 1.0f, *ref);
+                               break;
+                       case GL_RGB565:
+                               initializeColorRbo(gl, rbo, 0.2f, 0.5f, 0.65f, 1.0f, *ref);
+                               break;
+                       default:
+                               DE_ASSERT(!"Impossible");
+               }
+
+               gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+       }
+
+       return MovePtr<ClientBuffer>(buffer);
+}
+
+MovePtr<ImageSource> createTextureImageSource (EGLenum source, GLenum format, GLenum type, bool useTexLevel0)
+{
+       if (source == EGL_GL_TEXTURE_2D_KHR)
+               return MovePtr<ImageSource>(new Texture2DImageSource(format, type, useTexLevel0));
+       else
+               return MovePtr<ImageSource>(new TextureCubeMapImageSource(source, format, type, useTexLevel0));
+}
+
+MovePtr<ImageSource> createRenderbufferImageSource (GLenum format)
+{
+       return MovePtr<ImageSource>(new RenderbufferImageSource(format));
+}
+
+} // Image
+} // egl
+} // deqp
diff --git a/modules/egl/teglImageUtil.hpp b/modules/egl/teglImageUtil.hpp
new file mode 100644 (file)
index 0000000..7788cfa
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef _TEGLIMAGEUTIL_HPP
+#define _TEGLIMAGEUTIL_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2014 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 Common utilities for EGL images.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTexture.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include "teglTestCase.hpp"
+
+#include "egluUtil.hpp"
+#include "egluUnique.hpp"
+#include "egluHeaderWrapper.hpp"
+
+#include "glwDefs.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+namespace Image
+{
+
+class ManagedSurface
+{
+public:
+                                                                               ManagedSurface  (de::MovePtr<eglu::UniqueSurface> surface) : m_surface(surface) {}
+       virtual                                                         ~ManagedSurface (void) {}
+       EGLSurface                                                      get                             (void) const { return **m_surface; }
+
+private:
+       de::UniquePtr<eglu::UniqueSurface>      m_surface;
+};
+
+de::MovePtr<ManagedSurface> createSurface (EglTestContext& eglTestCtx, EGLConfig config, int width, int height);
+
+class ClientBuffer
+{
+public:
+       virtual                                 ~ClientBuffer   (void) {}
+       EGLClientBuffer                 get                             (void) const { return reinterpret_cast<EGLClientBuffer>(static_cast<deUintptr>(getName())); }
+
+protected:
+       virtual glw::GLuint             getName                 (void) const = 0;
+};
+
+class ImageSource
+{
+public:
+       virtual                                                         ~ImageSource            (void) {}
+       virtual EGLenum                                         getSource                       (void) const = 0;
+       virtual eglu::AttribMap                         getCreateAttribs        (void) const = 0;
+       virtual std::string                                     getRequiredExtension(void) const = 0;
+       virtual de::MovePtr<ClientBuffer>       createBuffer            (const glw::Functions& gl, tcu::Texture2D* reference = DE_NULL) const = 0;
+       EGLImageKHR                                                     createImage                     (const eglu::ImageFunctions& imgExt, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
+};
+
+de::MovePtr<ImageSource> createTextureImageSource                      (EGLenum source, glw::GLenum format, glw::GLenum type, bool useTexLevel0 = false);
+de::MovePtr<ImageSource> createRenderbufferImageSource         (glw::GLenum storage);
+
+} // Image
+} // egl
+} // deqp
+
+
+#endif // _TEGLIMAGEUTIL_HPP
index 721493660838b7612da7bce05a9519c3d1471184..3beeb76f3012cde4188ae36b0a05defce22cbdee 100644 (file)
@@ -221,6 +221,11 @@ eglu::NativeWindow* EglTestContext::createNativeWindow (EGLDisplay display, EGLC
        return m_windowFactory->createWindow(m_defaultNativeDisplay, display, config, attribList, eglu::WindowParams(width, height, visibility));
 }
 
+eglu::NativeWindow* EglTestContext::createNativeWindow (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height)
+{
+       return createNativeWindow(display, config, attribList, width, height, eglu::parseWindowVisibility(getTestContext().getCommandLine()));
+}
+
 eglu::NativePixmap* EglTestContext::createNativePixmap (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height)
 {
        if (!m_pixmapFactory)
@@ -259,13 +264,14 @@ deFunctionPtr EglTestContext::getGLFunction (glu::ApiType apiType, const char* n
        return library->getFunction(name);
 }
 
-void EglTestContext::getGLFunctions (glw::Functions& gl, glu::ApiType apiType) const
+void EglTestContext::getGLFunctions (glw::Functions& gl, glu::ApiType apiType, const std::vector<const char*>& extensions) const
 {
        const tcu::FunctionLibrary* const       library         = getGLLibrary(apiType);
        const eglu::GLFunctionLoader            loader          (library);
 
        // \note There may not be current context, so we can't use initFunctions().
        glu::initCoreFunctions(&gl, &loader, apiType);
+       glu::initExtensionFunctions(&gl, &loader, apiType, extensions.size(), &extensions.front());
 }
 
 TestCaseGroup::TestCaseGroup (EglTestContext& eglTestCtx, const char* name, const char* description)
index 494c67dec7d91bdd40ecfb7e658c294c3c46c000..cb3b5bb523d89d060b7761870250ef6e51c4de01 100644 (file)
@@ -30,6 +30,7 @@
 #include "egluConfigInfo.hpp"
 #include "tcuFunctionLibrary.hpp"
 #include "gluRenderContext.hpp"
+#include "deSTLUtil.hpp"
 
 #include <set>
 #include <map>
@@ -55,21 +56,24 @@ public:
                                                                                                EglTestContext                  (tcu::TestContext& testCtx, const eglu::NativeDisplayFactory& displayFactory, const eglu::NativeWindowFactory* windowFactory, const eglu::NativePixmapFactory* pixmapFactory);
                                                                                                ~EglTestContext                 (void);
 
-       tcu::TestContext&                                                       getTestContext                  (void)                  { return m_testCtx;                                                                                                     }
-       eglu::NativeDisplay&                                            getNativeDisplay                (void)                  { return *m_defaultNativeDisplay;                                                                       }
-       tcu::egl::Display&                                                      getDisplay                              (void)                  { return *m_defaultEGLDisplay;                                                                          }
+       tcu::TestContext&                                                       getTestContext                  (void) const    { return m_testCtx;                                                                                                     }
+       eglu::NativeDisplay&                                            getNativeDisplay                (void) const    { return *m_defaultNativeDisplay;                                                                       }
+       tcu::egl::Display&                                                      getDisplay                              (void) const    { return *m_defaultEGLDisplay;                                                                          }
+       EGLDisplay                                                                      getEGLDisplay                   (void) const    { return getDisplay().getEGLDisplay();                                                          }
        const std::vector<eglu::ConfigInfo>&            getConfigs                              (void) const    { return m_configs;                                                                                                     }
 
        const eglu::NativeWindowFactory&                        getNativeWindowFactory  (void) const;
        const eglu::NativePixmapFactory&                        getNativePixmapFactory  (void) const;
 
        eglu::NativeWindow*                                                     createNativeWindow              (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height, eglu::WindowParams::Visibility visibility);
+       eglu::NativeWindow*                                                     createNativeWindow              (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height);
        eglu::NativePixmap*                                                     createNativePixmap              (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height);
 
        deFunctionPtr                                                           getGLFunction                   (glu::ApiType apiType, const char* name) const;
-       void                                                                            getGLFunctions                  (glw::Functions& gl, glu::ApiType apiType) const;
+       void                                                                            getGLFunctions                  (glw::Functions& gl, glu::ApiType apiType, const std::vector<const char*>& extensions) const;
+       void                                                                            getGLFunctions                  (glw::Functions& gl, glu::ApiType apiType) const        { getGLFunctions(gl, apiType, std::vector<const char*>()); }
 
-       bool                                                                            isAPISupported                  (EGLint api)    { return m_supportedAPIs.find(api) != m_supportedAPIs.end();            }
+       bool                                                                            isAPISupported                  (EGLint api) const { return de::contains(m_supportedAPIs, api);                                         }
 
        // Test case wrapper will instruct test context to create display upon case init and destroy it in deinit
        void                                                                            createDefaultDisplay    (void);