Add multiple contexts tests
authorPiotr Byszewski <piotr.byszewski@mobica.com>
Fri, 25 Aug 2017 11:39:58 +0000 (13:39 +0200)
committerAntia Puentes <apuentes@igalia.com>
Tue, 10 Oct 2017 16:03:52 +0000 (18:03 +0200)
multiple_contexts test (one of shader_subroutine tests) was modified
and moved to contextless module. Shared contexts functionality was
restored in framework.

Components: Framework, OpenGL

VK-GL-CTS issue: 612

Affects:
KHR-NoContext.gl40.multiple_contexts.uniform_preservation
KHR-GL40.shader_subroutine.multiple_contexts

Change-Id: Id170ef37c2e3c488095663c91788978223d356ec
(cherry picked from commit 1b91247d4ad206cbdbef731a2bac9151d6ddda70)

38 files changed:
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl40-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl41-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl42-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl43-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl44-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl45-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/src/gl46-test-issues.txt
external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.5.5.x/gl40-khr-master.txt [new file with mode: 0644]
external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.5.5.x/src/gl40-khr-master.txt [new file with mode: 0644]
external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/gl40-khr-master.txt [new file with mode: 0644]
external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/mustpass.xml
external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/src/gl40-khr-master.txt [new file with mode: 0644]
external/openglcts/modules/common/CMakeLists.txt
external/openglcts/modules/common/glcContext.cpp
external/openglcts/modules/common/glcContext.hpp
external/openglcts/modules/common/glcMultipleContextsTests.cpp [new file with mode: 0644]
external/openglcts/modules/common/glcMultipleContextsTests.hpp [new file with mode: 0644]
external/openglcts/modules/common/glcNoDefaultContextPackage.cpp
external/openglcts/modules/gl/gl4cShaderSubroutineTests.cpp
external/openglcts/modules/gl/gl4cShaderSubroutineTests.hpp
external/openglcts/modules/runner/glcKhronosMustpassGlNocontext.hpp
external/openglcts/scripts/build_caselists.py
external/openglcts/scripts/build_mustpass.py
framework/egl/egluGLContextFactory.cpp
framework/egl/egluGLContextFactory.hpp
framework/egl/egluGLUtil.cpp
framework/egl/egluGLUtil.hpp
framework/opengl/gluContextFactory.hpp
framework/opengl/gluFboRenderContext.cpp
framework/opengl/gluRenderContext.cpp
framework/opengl/gluRenderContext.hpp
framework/platform/lnx/X11/tcuLnxX11GlxPlatform.cpp
framework/platform/null/tcuNullContextFactory.cpp
framework/platform/null/tcuNullContextFactory.hpp
framework/platform/win32/tcuWGL.cpp
framework/platform/win32/tcuWGL.hpp
framework/platform/win32/tcuWGLContextFactory.cpp
framework/platform/win32/tcuWGLContextFactory.hpp

diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.5.5.x/gl40-khr-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.5.5.x/gl40-khr-master.txt
new file mode 100644 (file)
index 0000000..a34c4d6
--- /dev/null
@@ -0,0 +1 @@
+KHR-NoContext.gl40.multiple_contexts.uniform_preservation
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.5.5.x/src/gl40-khr-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.5.5.x/src/gl40-khr-master.txt
new file mode 100644 (file)
index 0000000..c1c12c3
--- /dev/null
@@ -0,0 +1 @@
+KHR-NoContext.gl40.*
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/gl40-khr-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/gl40-khr-master.txt
new file mode 100644 (file)
index 0000000..a34c4d6
--- /dev/null
@@ -0,0 +1 @@
+KHR-NoContext.gl40.multiple_contexts.uniform_preservation
index 45dae0a..584e263 100644 (file)
@@ -19,6 +19,7 @@
  */-->
        <TestPackage name="Khronos Mustpass GL NoContext">
                <Configuration caseListFile="gl30-khr-master.txt" commandLine="--deqp-screen-rotation=unspecified --deqp-surface-width=64 --deqp-surface-height=64 --deqp-base-seed=1 --deqp-watchdog=disable" name="khr-master" os="any" useForFirstEGLConfig="True"/>
+               <Configuration caseListFile="gl40-khr-master.txt" commandLine="--deqp-screen-rotation=unspecified --deqp-surface-width=64 --deqp-surface-height=64 --deqp-base-seed=1 --deqp-watchdog=disable" name="khr-master" os="any" useForFirstEGLConfig="True"/>
                <Configuration caseListFile="gl45-khr-master.txt" commandLine="--deqp-screen-rotation=unspecified --deqp-surface-width=64 --deqp-surface-height=64 --deqp-base-seed=1 --deqp-watchdog=disable" name="khr-master" os="any" useForFirstEGLConfig="True"/>
        </TestPackage>
 </Mustpass>
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/src/gl40-khr-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.x/src/gl40-khr-master.txt
new file mode 100644 (file)
index 0000000..c1c12c3
--- /dev/null
@@ -0,0 +1 @@
+KHR-NoContext.gl40.*
index daee52c..41e4b3f 100644 (file)
@@ -32,6 +32,8 @@ set(GLCTS_COMMON_SRCS
        glcFragDepthTests.hpp
        glcInfoTests.cpp
        glcInfoTests.hpp
+       glcMultipleContextsTests.cpp
+       glcMultipleContextsTests.hpp
        glcNoErrorTests.cpp
        glcNoErrorTests.hpp
        glcRobustnessTests.cpp
index fb2e3b1..c1551c9 100644 (file)
@@ -83,11 +83,6 @@ void Context::destroyRenderContext(void)
        m_renderCtx   = DE_NULL;
 }
 
-glu::RenderContext* Context::createSharedContext(glu::ContextFlags, glu::ResetNotificationStrategy)
-{
-       TCU_THROW(InternalError, "Not implemented");
-}
-
 const tcu::RenderTarget& Context::getRenderTarget(void) const
 {
        return m_renderCtx->getRenderTarget();
index b91a365..d42e62c 100644 (file)
@@ -71,10 +71,6 @@ public:
 
        const tcu::RenderTarget& getRenderTarget(void) const;
 
-       glu::RenderContext* createSharedContext(
-               glu::ContextFlags                          ctxFlags = (glu::ContextFlags)0,
-               glu::ResetNotificationStrategy ctxReset = glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED);
-
 private:
        Context(const Context& other);
        Context& operator=(const Context& other);
diff --git a/external/openglcts/modules/common/glcMultipleContextsTests.cpp b/external/openglcts/modules/common/glcMultipleContextsTests.cpp
new file mode 100644 (file)
index 0000000..df78d0d
--- /dev/null
@@ -0,0 +1,875 @@
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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  glcMultipleContextsTests.cpp
+ * \brief
+ */ /*-------------------------------------------------------------------*/
+
+#include "glcMultipleContextsTests.hpp"
+#include "deSharedPtr.hpp"
+#include "gl4cShaderSubroutineTests.hpp"
+#include "gluContextInfo.hpp"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+#include "tcuMatrix.hpp"
+#include <cmath>
+#include <cstring>
+#include <deMath.h>
+
+using namespace glw;
+using namespace gl4cts::ShaderSubroutine;
+
+namespace glcts
+{
+
+/**
+ * * Create multiple contexts and verify that subroutine uniforms values
+ *   are preserved for each program stage when switching rendering context.
+ *
+ * OpenGL 4.1 or ARB_separate_shader_objects support required
+ * * Same as above, but use pipelines instead of monolithic program.
+ **/
+class UniformPreservationTest : public tcu::TestCase
+{
+public:
+       /* Public methods */
+       UniformPreservationTest(tcu::TestContext& testCtx, glu::ApiType apiType);
+
+       virtual void                                             deinit();
+       virtual tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private types */
+       struct subroutineUniformSet
+       {
+               bool operator!=(const subroutineUniformSet& arg) const;
+               void set(glw::GLuint bit_field, const subroutineUniformSet subroutine_indices[2]);
+
+               glw::GLuint m_vertex_shader_stage;
+               glw::GLuint m_tesselation_control_shader_stage;
+               glw::GLuint m_tesselation_evaluation_shader_stage;
+               glw::GLuint m_geometry_shader_stage;
+               glw::GLuint m_fragment_shader_stage;
+       };
+
+       /* Private methods */
+       void captureCurrentSubroutineSet(subroutineUniformSet& set);
+
+       void getShaders(const glw::GLchar*& out_vertex_shader_code, const glw::GLchar*& out_tesselation_control_shader_code,
+                                       const glw::GLchar*& out_tesselation_evaluation_shader_code,
+                                       const glw::GLchar*& out_geometry_shader_code, const glw::GLchar*& out_fragment_shader_code);
+
+       void initSharedContexts();
+
+       void prepareProgram(Utils::program** programs, bool is_separable);
+
+       void prepareProgramPipeline(glw::GLuint& pipeline_id, Utils::program** programs);
+
+       bool testCase(const glw::GLuint bit_field[5]);
+
+       bool testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
+                                        glw::GLuint n_test_cases);
+
+       void updateCurrentSubroutineSet(const subroutineUniformSet& set);
+
+       /* Private fields */
+       static const glw::GLuint m_n_shared_contexts;
+       static const glw::GLuint m_fragment_stage_index;
+       static const glw::GLuint m_geometry_stage_index;
+       static const glw::GLuint m_tesselation_control_stage_index;
+       static const glw::GLuint m_tesselation_evaluation_stage_index;
+       static const glw::GLuint m_vertex_stage_index;
+
+       glu::ApiType                             m_api_type;
+       de::SharedPtr<deqp::Context> m_base_context;
+       glu::RenderContext*                      m_shared_contexts[4];
+       glw::GLuint                                      m_program_pipelines[5];
+       subroutineUniformSet             m_subroutine_indices[2];
+       subroutineUniformSet             m_subroutine_uniform_locations;
+};
+
+/* Constants used by FunctionalTest20_21 */
+const GLuint UniformPreservationTest::m_n_shared_contexts                                 = 4;
+const GLuint UniformPreservationTest::m_fragment_stage_index                      = 0;
+const GLuint UniformPreservationTest::m_geometry_stage_index                      = 1;
+const GLuint UniformPreservationTest::m_tesselation_control_stage_index        = 2;
+const GLuint UniformPreservationTest::m_tesselation_evaluation_stage_index = 3;
+const GLuint UniformPreservationTest::m_vertex_stage_index                                = 4;
+
+/** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
+ *
+ * @param bit_field          Selects source of of index for each stage
+ * @param subroutine_indices Array of two indices sets
+ **/
+void UniformPreservationTest::subroutineUniformSet::set(GLuint                                    bit_field,
+                                                                                                               const subroutineUniformSet subroutine_indices[2])
+{
+       GLuint vertex_stage                                     = ((bit_field & (0x01 << 0)) >> 0);
+       GLuint tesselation_control_stage        = ((bit_field & (0x01 << 1)) >> 1);
+       GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2);
+       GLuint geometry_stage                           = ((bit_field & (0x01 << 3)) >> 3);
+       GLuint fragment_stage                           = ((bit_field & (0x01 << 4)) >> 4);
+
+       m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage;
+       m_tesselation_control_shader_stage =
+               subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage;
+       m_tesselation_evaluation_shader_stage =
+               subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage;
+       m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage;
+       m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage;
+}
+
+/** Negated comparison of two sets
+ *
+ * @param arg Instance that will be compared to this
+ *
+ * @return false when both objects are equal, true otherwise
+ **/
+bool UniformPreservationTest::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
+{
+       if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) ||
+               (arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) ||
+               (arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) ||
+               (arg.m_geometry_shader_stage != m_geometry_shader_stage) ||
+               (arg.m_fragment_shader_stage != m_fragment_shader_stage))
+       {
+               return true;
+       }
+
+       return false;
+}
+
+/** Constructor.
+ *
+ *  @param context Rendering context.
+ *
+ **/
+UniformPreservationTest::UniformPreservationTest(tcu::TestContext& testCtx, glu::ApiType apiType)
+       : tcu::TestCase(testCtx, "uniform_preservation",
+                                       "Verifies that shader uniforms are preserved when rendering context is switched.")
+       , m_api_type(apiType)
+{
+       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
+       {
+               m_program_pipelines[i] = 0;
+       }
+
+       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+       {
+               m_shared_contexts[i] = 0;
+       }
+}
+
+/** Deinitializes all GL objects that may have been created during
+ *  test execution.
+ **/
+void UniformPreservationTest::deinit()
+{
+       /* GL entry points */
+       const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
+
+       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
+       {
+               if (0 != m_program_pipelines[i])
+               {
+                       gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
+                       m_program_pipelines[i] = 0;
+               }
+       }
+
+       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+       {
+               if (0 != m_shared_contexts[i])
+               {
+                       delete m_shared_contexts[i];
+                       m_shared_contexts[i] = 0;
+               }
+       }
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP
+ */
+tcu::TestNode::IterateResult UniformPreservationTest::iterate()
+{
+       /* Test cases, values stored here are used as bit fields */
+       static const GLuint test_cases[][m_n_shared_contexts + 1] = {
+               { 0, 1, 2, 3, 4 },              { 1, 2, 3, 4, 0 },              { 2, 3, 4, 0, 1 },              { 3, 4, 0, 1, 2 },
+               { 4, 0, 1, 2, 3 },              { 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 },
+               { 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 },
+       };
+       static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+
+       glu::ContextType context_type(m_api_type);
+       m_base_context = de::SharedPtr<deqp::Context>(new deqp::Context(m_testCtx, context_type));
+
+       /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
+       if (!m_base_context->getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
+       {
+               throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
+       }
+
+       /* Prepare contexts */
+       initSharedContexts();
+
+       /* Test result */
+       bool result = true;
+
+       /* Program pointers */
+       Utils::program* program_pointers[5];
+
+       /* Test monolithic program */
+       {
+               /* Prepare program */
+               Utils::program program(*m_base_context.get());
+
+               program_pointers[m_fragment_stage_index] = &program;
+
+               prepareProgram(program_pointers, false);
+
+               /* Execute test */
+               if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by monolithic program."
+                                                          << tcu::TestLog::EndMessage;
+
+                       result = false;
+               }
+       }
+
+       /* Test separable programs */
+       if (true == m_base_context->getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
+       {
+               /* Prepare programs */
+               Utils::program vertex_program(*m_base_context.get());
+               Utils::program tesselation_control_program(*m_base_context.get());
+               Utils::program tesselation_evaluation_program(*m_base_context.get());
+               Utils::program geometry_program(*m_base_context.get());
+               Utils::program fragment_program(*m_base_context.get());
+
+               program_pointers[m_fragment_stage_index]                           = &fragment_program;
+               program_pointers[m_geometry_stage_index]                           = &geometry_program;
+               program_pointers[m_tesselation_control_stage_index]     = &tesselation_control_program;
+               program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
+               program_pointers[m_vertex_stage_index]                             = &vertex_program;
+
+               prepareProgram(program_pointers, true);
+
+               /* Execute test */
+               if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by separable program."
+                                                          << tcu::TestLog::EndMessage;
+                       result = false;
+               }
+       }
+
+       /* All done */
+       if (true == result)
+       {
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       }
+       else
+       {
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+       }
+
+       return tcu::TestNode::STOP;
+}
+
+/** Query state of subroutine uniforms of current program/pipeline
+ *
+ * @param set Storage for results
+ **/
+void UniformPreservationTest::captureCurrentSubroutineSet(subroutineUniformSet& set)
+{
+       /* GL entry points */
+       const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
+
+       /* Fragment */
+       gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
+                                                          &set.m_fragment_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
+
+       /* Geometry */
+       gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
+                                                          &set.m_geometry_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
+
+       /* Tess ctrl */
+       gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
+                                                          m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
+                                                          &set.m_tesselation_control_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
+
+       /* Tess eval */
+       gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
+                                                          m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
+                                                          &set.m_tesselation_evaluation_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
+
+       /* Vertex */
+       gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
+                                                          &set.m_vertex_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
+}
+
+/** Get shaders' source code
+ *
+ * @param out_vertex_shader_code                 Vertex source code
+ * @param out_tesselation_control_shader_code    Tess ctrl source code
+ * @param out_tesselation_evaluation_shader_code Tess eval source code
+ * @param out_geometry_shader_code               Geometry source code
+ * @param out_fragment_shader_code               Fragment source code
+ **/
+void UniformPreservationTest::getShaders(const glw::GLchar*& out_vertex_shader_code,
+                                                                                const glw::GLchar*& out_tesselation_control_shader_code,
+                                                                                const glw::GLchar*& out_tesselation_evaluation_shader_code,
+                                                                                const glw::GLchar*& out_geometry_shader_code,
+                                                                                const glw::GLchar*& out_fragment_shader_code)
+{
+       static const GLchar* vertex_shader_code = "#version 400 core\n"
+                                                                                         "#extension GL_ARB_shader_subroutine : require\n"
+                                                                                         "\n"
+                                                                                         "precision highp float;\n"
+                                                                                         "\n"
+                                                                                         "// Subroutine type\n"
+                                                                                         "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
+                                                                                         "\n"
+                                                                                         "// Subroutine definition\n"
+                                                                                         "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
+                                                                                         "{\n"
+                                                                                         "    return left + right;\n"
+                                                                                         "}\n"
+                                                                                         "\n"
+                                                                                         "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
+                                                                                         "{\n"
+                                                                                         "    return left * right;\n"
+                                                                                         "}\n"
+                                                                                         "\n"
+                                                                                         "// Sub routine uniform\n"
+                                                                                         "subroutine uniform routine_type routine;\n"
+                                                                                         "\n"
+                                                                                         "// Input data\n"
+                                                                                         "uniform vec4 uni_vs_left;\n"
+                                                                                         "uniform vec4 uni_vs_right;\n"
+                                                                                         "\n"
+                                                                                         "// Output\n"
+                                                                                         "out vec4 vs_tcs_result;\n"
+                                                                                         "\n"
+                                                                                         "void main()\n"
+                                                                                         "{\n"
+                                                                                         "    vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
+                                                                                         "}\n"
+                                                                                         "\n";
+
+       static const GLchar* tesselation_control_shader_code =
+               "#version 400 core\n"
+               "#extension GL_ARB_shader_subroutine : require\n"
+               "\n"
+               "precision highp float;\n"
+               "\n"
+               "layout(vertices = 1) out;\n"
+               "\n"
+               "// Subroutine type\n"
+               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
+               "\n"
+               "// Subroutine definition\n"
+               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left + right;\n"
+               "}\n"
+               "\n"
+               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left * right;\n"
+               "}\n"
+               "\n"
+               "// Sub routine uniform\n"
+               "subroutine uniform routine_type routine;\n"
+               "\n"
+               "// Input data\n"
+               "uniform vec4 uni_tcs_left;\n"
+               "uniform vec4 uni_tcs_right;\n"
+               "\n"
+               "in vec4 vs_tcs_result[];\n"
+               "\n"
+               "// Output\n"
+               "out vec4 tcs_tes_result[];\n"
+               "\n"
+               "void main()\n"
+               "{\n"
+               "    gl_TessLevelOuter[0] = 1.0;\n"
+               "    gl_TessLevelOuter[1] = 1.0;\n"
+               "    gl_TessLevelOuter[2] = 1.0;\n"
+               "    gl_TessLevelOuter[3] = 1.0;\n"
+               "    gl_TessLevelInner[0] = 1.0;\n"
+               "    gl_TessLevelInner[1] = 1.0;\n"
+               "\n"
+               "    tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
+               "}\n"
+               "\n";
+
+       static const GLchar* tesselation_evaluation_shader_code =
+               "#version 400 core\n"
+               "#extension GL_ARB_shader_subroutine : require\n"
+               "\n"
+               "precision highp float;\n"
+               "\n"
+               "layout(isolines, point_mode) in;\n"
+               "\n"
+               "// Subroutine type\n"
+               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
+               "\n"
+               "// Subroutine definition\n"
+               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left + right;\n"
+               "}\n"
+               "\n"
+               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left * right;\n"
+               "}\n"
+               "\n"
+               "// Sub routine uniform\n"
+               "subroutine uniform routine_type routine;\n"
+               "\n"
+               "// Input data\n"
+               "uniform vec4 uni_tes_left;\n"
+               "uniform vec4 uni_tes_right;\n"
+               "\n"
+               "in vec4 tcs_tes_result[];\n"
+               "\n"
+               "// Output\n"
+               "out vec4 tes_gs_result;\n"
+               "\n"
+               "void main()\n"
+               "{\n"
+               "    tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
+               "}\n"
+               "\n";
+
+       static const GLchar* geometry_shader_code =
+               "#version 400 core\n"
+               "#extension GL_ARB_shader_subroutine : require\n"
+               "\n"
+               "precision highp float;\n"
+               "\n"
+               "layout(points)                   in;\n"
+               "layout(points, max_vertices = 1) out;\n"
+               "\n"
+               "// Subroutine type\n"
+               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
+               "\n"
+               "// Subroutine definition\n"
+               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left + right;\n"
+               "}\n"
+               "\n"
+               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left * right;\n"
+               "}\n"
+               "\n"
+               "// Sub routine uniform\n"
+               "subroutine uniform routine_type routine;\n"
+               "\n"
+               "// Input data\n"
+               "uniform vec4 uni_gs_left;\n"
+               "uniform vec4 uni_gs_right;\n"
+               "\n"
+               "in vec4 tes_gs_result[];\n"
+               "\n"
+               "// Output\n"
+               "out vec4 gs_fs_result;\n"
+               "\n"
+               "void main()\n"
+               "{\n"
+               "    gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
+               "}\n"
+               "\n";
+
+       static const GLchar* fragmenty_shader_code =
+               "#version 400 core\n"
+               "#extension GL_ARB_shader_subroutine : require\n"
+               "\n"
+               "precision highp float;\n"
+               "\n"
+               "// Subroutine type\n"
+               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
+               "\n"
+               "// Subroutine definition\n"
+               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left + right;\n"
+               "}\n"
+               "\n"
+               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
+               "{\n"
+               "    return left * right;\n"
+               "}\n"
+               "\n"
+               "// Sub routine uniform\n"
+               "subroutine uniform routine_type routine;\n"
+               "\n"
+               "// Input data\n"
+               "uniform vec4 uni_fs_left;\n"
+               "uniform vec4 uni_fs_right;\n"
+               "\n"
+               "in vec4 gs_fs_result;\n"
+               "\n"
+               "// Output\n"
+               "out vec4 fs_out_result;\n"
+               "\n"
+               "void main()\n"
+               "{\n"
+               "    fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
+               "}\n"
+               "\n";
+
+       out_vertex_shader_code                             = vertex_shader_code;
+       out_tesselation_control_shader_code     = tesselation_control_shader_code;
+       out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
+       out_geometry_shader_code                           = geometry_shader_code;
+       out_fragment_shader_code                           = fragmenty_shader_code;
+}
+
+/** Create <m_n_shared_contexts> shared contexts
+ *
+ **/
+void UniformPreservationTest::initSharedContexts()
+{
+       glu::ContextType                context_type(m_api_type);
+       glu::RenderConfig               render_config(context_type);
+       const tcu::CommandLine& command_line(m_testCtx.getCommandLine());
+       glu::RenderContext*             shared_context = &(m_base_context->getRenderContext());
+       glu::parseRenderConfig(&render_config, command_line);
+
+#if (DE_OS == DE_OS_ANDROID)
+       // Android can only have one Window created at a time
+       // Note that this surface type is not supported on all platforms
+       render_config.surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC;
+#endif
+
+       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+       {
+               m_shared_contexts[i] =
+                       glu::createRenderContext(m_testCtx.getPlatform(), command_line, render_config, shared_context);
+       }
+       m_base_context->getRenderContext().makeCurrent();
+}
+
+/** Prepare program(s)
+ *
+ * @param programs     An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5
+ * @param is_separable Select if monolithic or separable programs should be prepared
+ **/
+void UniformPreservationTest::prepareProgram(Utils::program** programs, bool is_separable)
+{
+       /* Get shader sources */
+       const GLchar* vertex_shader_code;
+       const GLchar* tesselation_control_shader_code;
+       const GLchar* tesselation_evaluation_shader_code;
+       const GLchar* geometry_shader_code;
+       const GLchar* fragmenty_shader_code;
+
+       getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
+                          geometry_shader_code, fragmenty_shader_code);
+
+       /* Subroutines and uniform names */
+       static const GLchar* subroutine_names[] = { "add", "multiply" };
+       static const GLuint  n_subroutines              = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
+
+       static const GLchar* subroutine_uniform_name = "routine";
+
+       /* Build program */
+       if (false == is_separable)
+       {
+               programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
+                                                  tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
+                                                  0 /* varying_names */, 0 /* n_varying_names */);
+
+               programs[m_geometry_stage_index]                           = programs[m_fragment_stage_index];
+               programs[m_tesselation_control_stage_index]     = programs[m_fragment_stage_index];
+               programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
+               programs[m_vertex_stage_index]                             = programs[m_fragment_stage_index];
+       }
+       else
+       {
+               programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
+               programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
+               programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
+               programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
+                                                                                                                         true);
+               programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
+       }
+
+       /* Get subroutine indices */
+       for (GLuint i = 0; i < n_subroutines; ++i)
+       {
+               m_subroutine_indices[i].m_fragment_shader_stage =
+                       programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
+
+               m_subroutine_indices[i].m_geometry_shader_stage =
+                       programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
+
+               m_subroutine_indices[i].m_tesselation_control_shader_stage =
+                       programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
+                                                                                                                                                       GL_TESS_CONTROL_SHADER);
+
+               m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
+                       programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
+                                                                                                                                                          GL_TESS_EVALUATION_SHADER);
+
+               m_subroutine_indices[i].m_vertex_shader_stage =
+                       programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
+       }
+
+       /* Get subroutine uniform locations */
+       m_subroutine_uniform_locations.m_fragment_shader_stage =
+               programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
+
+       m_subroutine_uniform_locations.m_geometry_shader_stage =
+               programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
+
+       m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
+               programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
+                                                                                                                                                                 GL_TESS_CONTROL_SHADER);
+
+       m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
+               programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
+                                                                                                                                                                        GL_TESS_EVALUATION_SHADER);
+
+       m_subroutine_uniform_locations.m_vertex_shader_stage =
+               programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
+}
+
+/** Generate program pipeline for current context and attach separable programs
+ *
+ * @param out_pipeline_id Id of generated pipeline
+ * @param programs        Collection of separable programs
+ **/
+void UniformPreservationTest::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
+{
+       /* GL entry points */
+       const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
+
+       /* Generate */
+       gl.genProgramPipelines(1, &out_pipeline_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
+
+       /* Bind */
+       gl.bindProgramPipeline(out_pipeline_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
+
+       /* Set up programs */
+       gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
+
+       gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
+
+       gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
+                                               programs[m_tesselation_control_stage_index]->m_program_object_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
+
+       gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
+                                               programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
+
+       gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
+}
+
+/** Test specific case
+ *
+ * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
+ *
+ * @return True if test pass, false otherwise
+ **/
+bool UniformPreservationTest::testCase(const glw::GLuint bit_field[5])
+{
+       /* Storage for subroutine indices */
+       subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
+       subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
+
+       /* Prepare subroutine_indices with bit fields */
+       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
+       {
+               subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
+       };
+
+       /* Update subroutine uniforms, each context gets different set */
+       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+       {
+               m_shared_contexts[i]->makeCurrent();
+               updateCurrentSubroutineSet(subroutine_indices[i]);
+       }
+
+       m_base_context->getRenderContext().makeCurrent();
+       updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
+
+       /* Capture subroutine uniforms */
+       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+       {
+               m_shared_contexts[i]->makeCurrent();
+               captureCurrentSubroutineSet(captured_subroutine_indices[i]);
+       }
+
+       m_base_context->getRenderContext().makeCurrent();
+       captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
+
+       /* Verify that captured uniforms match expected values */
+       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
+       {
+               if (subroutine_indices[i] != captured_subroutine_indices[i])
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Error."
+                                                          << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
+                                                          << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
+                                                          << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
+                                                          << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
+                                                          << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
+                                                          << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
+                                                          << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
+                                                          << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
+                                                          << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
+                                                          << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage
+                                                          << tcu::TestLog::EndMessage;
+
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+/** Test a program or pipeline
+ *
+ * @param programs     An array of 5 programs\ pointers, as in preparePrograms
+ * @param is_separable Selects if monolithic or separable programs should be used
+ * @param test_cases   Collection of test cases
+ * @param n_test_cases Number of test cases
+ *
+ * @return True if all cases pass, false otherwise
+ **/
+bool UniformPreservationTest::testProgram(Utils::program** programs, bool is_separable,
+                                                                                 const glw::GLuint test_cases[][5], glw::GLuint n_test_cases)
+{
+       /* Set program/pipeline as current for all contexts */
+       if (false == is_separable)
+       {
+               programs[0]->use();
+
+               for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+               {
+                       m_shared_contexts[i]->makeCurrent();
+                       programs[0]->use();
+               }
+       }
+       else
+       {
+               /* GL entry points */
+               const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
+
+               /* Make sure that program pipeline will be used */
+               gl.useProgram(0);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
+
+               prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
+
+               for (GLuint i = 0; i < m_n_shared_contexts; ++i)
+               {
+                       m_shared_contexts[i]->makeCurrent();
+
+                       /* Make sure that program pipeline will be used */
+                       gl.useProgram(0);
+                       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
+
+                       prepareProgramPipeline(m_program_pipelines[i], programs);
+               }
+       }
+
+       /* Execute test */
+       bool result = true;
+       for (GLuint i = 0; i < n_test_cases; ++i)
+       {
+               if (false == testCase(test_cases[i]))
+               {
+                       result = false;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+/** Set up subroutine uniforms for current program or pipeline
+ *
+ * @param set Set of subroutine indices
+ **/
+void UniformPreservationTest::updateCurrentSubroutineSet(const subroutineUniformSet& set)
+{
+       /* GL entry points */
+       const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
+
+       /* Fragment */
+       gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
+
+       /* Geometry */
+       gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
+
+       /* Tess ctrl */
+       gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
+
+       /* Tess eval */
+       gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
+
+       /* Vertex */
+       gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
+}
+
+/** Constructor.
+ *
+ *  @param context Rendering context.
+ **/
+MultipleContextsTests::MultipleContextsTests(tcu::TestContext& testCtx, glu::ApiType apiType)
+       : tcu::TestCaseGroup(testCtx, "multiple_contexts", "Verifies \"shader_subroutine\" functionality")
+       , m_apiType(apiType)
+{
+       /* Left blank on purpose */
+}
+
+/** Initializes a texture_storage_multisample test group.
+ *
+ **/
+void MultipleContextsTests::init(void)
+{
+       addChild(new UniformPreservationTest(m_testCtx, m_apiType));
+}
+
+} /* glcts namespace */
diff --git a/external/openglcts/modules/common/glcMultipleContextsTests.hpp b/external/openglcts/modules/common/glcMultipleContextsTests.hpp
new file mode 100644 (file)
index 0000000..867e153
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _GLCMULTIPLECONTEXTSTESTS_HPP
+#define _GLCMULTIPLECONTEXTSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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  glcMultipleContextsTests.hpp
+ * \brief
+ */ /*-------------------------------------------------------------------*/
+
+#include "glcTestCase.hpp"
+#include "glwDefs.hpp"
+#include <queue>
+
+#include "tcuTestLog.hpp"
+
+namespace glcts
+{
+
+/** Group class for Shader Subroutine conformance tests */
+class MultipleContextsTests : public tcu::TestCaseGroup
+{
+public:
+       /* Public methods */
+       MultipleContextsTests(tcu::TestContext& testCtx, glu::ApiType apiType);
+       virtual ~MultipleContextsTests()
+       {
+       }
+
+       virtual void init(void);
+
+private:
+       /* Private methods */
+       MultipleContextsTests(const MultipleContextsTests&);
+       MultipleContextsTests& operator=(const MultipleContextsTests&);
+
+       /* Private members */
+       glu::ApiType m_apiType;
+};
+
+} /* gl4cts namespace */
+
+#endif // _GLCMULTIPLECONTEXTSTESTS_HPP
index 0fc4d53..e918e67 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "glcNoDefaultContextPackage.hpp"
 #include "glcContextFlagsTests.hpp"
+#include "glcMultipleContextsTests.hpp"
 #include "glcNoErrorTests.hpp"
 #include "glcRobustnessTests.hpp"
 #include "gluRenderContext.hpp"
@@ -88,6 +89,10 @@ void NoDefaultContextPackage::init(void)
        gl30Group->addChild(new glcts::NoErrorTests(getTestContext(), glu::ApiType::core(3, 0)));
        addChild(gl30Group);
 
+       tcu::TestCaseGroup* gl40Group = new tcu::TestCaseGroup(getTestContext(), "gl40", "");
+       gl40Group->addChild(new glcts::MultipleContextsTests(getTestContext(), glu::ApiType::core(4, 0)));
+       addChild(gl40Group);
+
        tcu::TestCaseGroup* gl45Group = new tcu::TestCaseGroup(getTestContext(), "gl45", "");
        gl45Group->addChild(new glcts::RobustnessTests(getTestContext(), glu::ApiType::core(4, 5)));
        gl45Group->addChild(new glcts::ContextFlagsTests(getTestContext(), glu::ApiType::core(4, 5)));
index 0ef75b3..67806b8 100644 (file)
@@ -9838,740 +9838,6 @@ void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint boo
        } /* for (all drawn points) */
 }
 
-/* Constants used by FunctionalTest20_21 */
-const GLuint FunctionalTest20_21::m_n_shared_contexts                             = 4;
-const GLuint FunctionalTest20_21::m_fragment_stage_index                          = 0;
-const GLuint FunctionalTest20_21::m_geometry_stage_index                          = 1;
-const GLuint FunctionalTest20_21::m_tesselation_control_stage_index    = 2;
-const GLuint FunctionalTest20_21::m_tesselation_evaluation_stage_index = 3;
-const GLuint FunctionalTest20_21::m_vertex_stage_index                            = 4;
-
-/** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
- *
- * @param bit_field          Selects source of of index for each stage
- * @param subroutine_indices Array of two indices sets
- **/
-void FunctionalTest20_21::subroutineUniformSet::set(GLuint bit_field, const subroutineUniformSet subroutine_indices[2])
-{
-       GLuint vertex_stage                                     = ((bit_field & (0x01 << 0)) >> 0);
-       GLuint tesselation_control_stage        = ((bit_field & (0x01 << 1)) >> 1);
-       GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2);
-       GLuint geometry_stage                           = ((bit_field & (0x01 << 3)) >> 3);
-       GLuint fragment_stage                           = ((bit_field & (0x01 << 4)) >> 4);
-
-       m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage;
-       m_tesselation_control_shader_stage =
-               subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage;
-       m_tesselation_evaluation_shader_stage =
-               subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage;
-       m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage;
-       m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage;
-}
-
-/** Negated comparison of two sets
- *
- * @param arg Instance that will be compared to this
- *
- * @return false when both objects are equal, true otherwise
- **/
-bool FunctionalTest20_21::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
-{
-       if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) ||
-               (arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) ||
-               (arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) ||
-               (arg.m_geometry_shader_stage != m_geometry_shader_stage) ||
-               (arg.m_fragment_shader_stage != m_fragment_shader_stage))
-       {
-               return true;
-       }
-
-       return false;
-}
-
-/** Constructor.
- *
- *  @param context Rendering context.
- *
- **/
-FunctionalTest20_21::FunctionalTest20_21(deqp::Context& context)
-       : TestCase(context, "multiple_contexts",
-                          "Verifies that shader uniforms are preserved when rendering context is switched.")
-{
-       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
-       {
-               m_program_pipelines[i] = 0;
-       }
-
-       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-       {
-               m_shared_contexts[i] = 0;
-       }
-}
-
-/** Deinitializes all GL objects that may have been created during
- *  test execution.
- **/
-void FunctionalTest20_21::deinit()
-{
-       /* GL entry points */
-       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
-
-       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
-       {
-               if (0 != m_program_pipelines[i])
-               {
-                       gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
-                       m_program_pipelines[i] = 0;
-               }
-       }
-
-       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-       {
-               if (0 != m_shared_contexts[i])
-               {
-                       delete m_shared_contexts[i];
-                       m_shared_contexts[i] = 0;
-               }
-       }
-
-       m_context.getRenderContext().makeCurrent();
-}
-
-/** Executes test iteration.
- *
- *  @return Returns STOP
- */
-tcu::TestNode::IterateResult FunctionalTest20_21::iterate()
-{
-       /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
-       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
-       {
-               throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
-       }
-
-       /* Test cases, values stored here are used as bit fields */
-       static const GLuint test_cases[][m_n_shared_contexts + 1] = {
-               { 0, 1, 2, 3, 4 },              { 1, 2, 3, 4, 0 },              { 2, 3, 4, 0, 1 },              { 3, 4, 0, 1, 2 },
-               { 4, 0, 1, 2, 3 },              { 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 },
-               { 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 },
-       };
-       static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
-
-       /* Prepare contexts */
-       initSharedContexts();
-
-       /* Test result */
-       bool result = true;
-
-       /* Program pointers */
-       Utils::program* program_pointers[5];
-
-       /* Test monolithic program */
-       {
-               /* Prepare program */
-               Utils::program program(m_context);
-
-               program_pointers[m_fragment_stage_index] = &program;
-
-               prepareProgram(program_pointers, false);
-
-               /* Execute test */
-               if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
-               {
-                       m_context.getTestContext().getLog() << tcu::TestLog::Message
-                                                                                               << "Last error message was caused by monolithic program."
-                                                                                               << tcu::TestLog::EndMessage;
-
-                       result = false;
-               }
-       }
-
-       /* Test separable programs */
-       if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
-       {
-               /* Prepare programs */
-               Utils::program vertex_program(m_context);
-               Utils::program tesselation_control_program(m_context);
-               Utils::program tesselation_evaluation_program(m_context);
-               Utils::program geometry_program(m_context);
-               Utils::program fragment_program(m_context);
-
-               program_pointers[m_fragment_stage_index]                           = &fragment_program;
-               program_pointers[m_geometry_stage_index]                           = &geometry_program;
-               program_pointers[m_tesselation_control_stage_index]     = &tesselation_control_program;
-               program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
-               program_pointers[m_vertex_stage_index]                             = &vertex_program;
-
-               prepareProgram(program_pointers, true);
-
-               /* Execute test */
-               if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
-               {
-                       m_context.getTestContext().getLog() << tcu::TestLog::Message
-                                                                                               << "Last error message was caused by separable program."
-                                                                                               << tcu::TestLog::EndMessage;
-                       result = false;
-               }
-       }
-
-       /* All done */
-       if (true == result)
-       {
-               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-       }
-       else
-       {
-               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
-       }
-
-       return tcu::TestNode::STOP;
-}
-
-/** Query state of subroutine uniforms of current program/pipeline
- *
- * @param set Storage for results
- **/
-void FunctionalTest20_21::captureCurrentSubroutineSet(subroutineUniformSet& set)
-{
-       /* GL entry points */
-       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
-
-       /* Fragment */
-       gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
-                                                          &set.m_fragment_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
-
-       /* Geometry */
-       gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
-                                                          &set.m_geometry_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
-
-       /* Tess ctrl */
-       gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
-                                                          m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
-                                                          &set.m_tesselation_control_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
-
-       /* Tess eval */
-       gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
-                                                          m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
-                                                          &set.m_tesselation_evaluation_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
-
-       /* Vertex */
-       gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
-                                                          &set.m_vertex_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
-}
-
-/** Get shaders' source code
- *
- * @param out_vertex_shader_code                 Vertex source code
- * @param out_tesselation_control_shader_code    Tess ctrl source code
- * @param out_tesselation_evaluation_shader_code Tess eval source code
- * @param out_geometry_shader_code               Geometry source code
- * @param out_fragment_shader_code               Fragment source code
- **/
-void FunctionalTest20_21::getShaders(const glw::GLchar*& out_vertex_shader_code,
-                                                                        const glw::GLchar*& out_tesselation_control_shader_code,
-                                                                        const glw::GLchar*& out_tesselation_evaluation_shader_code,
-                                                                        const glw::GLchar*& out_geometry_shader_code,
-                                                                        const glw::GLchar*& out_fragment_shader_code)
-{
-       static const GLchar* vertex_shader_code = "#version 400 core\n"
-                                                                                         "#extension GL_ARB_shader_subroutine : require\n"
-                                                                                         "\n"
-                                                                                         "precision highp float;\n"
-                                                                                         "\n"
-                                                                                         "// Subroutine type\n"
-                                                                                         "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
-                                                                                         "\n"
-                                                                                         "// Subroutine definition\n"
-                                                                                         "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
-                                                                                         "{\n"
-                                                                                         "    return left + right;\n"
-                                                                                         "}\n"
-                                                                                         "\n"
-                                                                                         "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
-                                                                                         "{\n"
-                                                                                         "    return left * right;\n"
-                                                                                         "}\n"
-                                                                                         "\n"
-                                                                                         "// Sub routine uniform\n"
-                                                                                         "subroutine uniform routine_type routine;\n"
-                                                                                         "\n"
-                                                                                         "// Input data\n"
-                                                                                         "uniform vec4 uni_vs_left;\n"
-                                                                                         "uniform vec4 uni_vs_right;\n"
-                                                                                         "\n"
-                                                                                         "// Output\n"
-                                                                                         "out vec4 vs_tcs_result;\n"
-                                                                                         "\n"
-                                                                                         "void main()\n"
-                                                                                         "{\n"
-                                                                                         "    vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
-                                                                                         "}\n"
-                                                                                         "\n";
-
-       static const GLchar* tesselation_control_shader_code =
-               "#version 400 core\n"
-               "#extension GL_ARB_shader_subroutine : require\n"
-               "\n"
-               "precision highp float;\n"
-               "\n"
-               "layout(vertices = 1) out;\n"
-               "\n"
-               "// Subroutine type\n"
-               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
-               "\n"
-               "// Subroutine definition\n"
-               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left + right;\n"
-               "}\n"
-               "\n"
-               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left * right;\n"
-               "}\n"
-               "\n"
-               "// Sub routine uniform\n"
-               "subroutine uniform routine_type routine;\n"
-               "\n"
-               "// Input data\n"
-               "uniform vec4 uni_tcs_left;\n"
-               "uniform vec4 uni_tcs_right;\n"
-               "\n"
-               "in vec4 vs_tcs_result[];\n"
-               "\n"
-               "// Output\n"
-               "out vec4 tcs_tes_result[];\n"
-               "\n"
-               "void main()\n"
-               "{\n"
-               "    gl_TessLevelOuter[0] = 1.0;\n"
-               "    gl_TessLevelOuter[1] = 1.0;\n"
-               "    gl_TessLevelOuter[2] = 1.0;\n"
-               "    gl_TessLevelOuter[3] = 1.0;\n"
-               "    gl_TessLevelInner[0] = 1.0;\n"
-               "    gl_TessLevelInner[1] = 1.0;\n"
-               "\n"
-               "    tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
-               "}\n"
-               "\n";
-
-       static const GLchar* tesselation_evaluation_shader_code =
-               "#version 400 core\n"
-               "#extension GL_ARB_shader_subroutine : require\n"
-               "\n"
-               "precision highp float;\n"
-               "\n"
-               "layout(isolines, point_mode) in;\n"
-               "\n"
-               "// Subroutine type\n"
-               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
-               "\n"
-               "// Subroutine definition\n"
-               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left + right;\n"
-               "}\n"
-               "\n"
-               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left * right;\n"
-               "}\n"
-               "\n"
-               "// Sub routine uniform\n"
-               "subroutine uniform routine_type routine;\n"
-               "\n"
-               "// Input data\n"
-               "uniform vec4 uni_tes_left;\n"
-               "uniform vec4 uni_tes_right;\n"
-               "\n"
-               "in vec4 tcs_tes_result[];\n"
-               "\n"
-               "// Output\n"
-               "out vec4 tes_gs_result;\n"
-               "\n"
-               "void main()\n"
-               "{\n"
-               "    tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
-               "}\n"
-               "\n";
-
-       static const GLchar* geometry_shader_code =
-               "#version 400 core\n"
-               "#extension GL_ARB_shader_subroutine : require\n"
-               "\n"
-               "precision highp float;\n"
-               "\n"
-               "layout(points)                   in;\n"
-               "layout(points, max_vertices = 1) out;\n"
-               "\n"
-               "// Subroutine type\n"
-               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
-               "\n"
-               "// Subroutine definition\n"
-               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left + right;\n"
-               "}\n"
-               "\n"
-               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left * right;\n"
-               "}\n"
-               "\n"
-               "// Sub routine uniform\n"
-               "subroutine uniform routine_type routine;\n"
-               "\n"
-               "// Input data\n"
-               "uniform vec4 uni_gs_left;\n"
-               "uniform vec4 uni_gs_right;\n"
-               "\n"
-               "in vec4 tes_gs_result[];\n"
-               "\n"
-               "// Output\n"
-               "out vec4 gs_fs_result;\n"
-               "\n"
-               "void main()\n"
-               "{\n"
-               "    gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
-               "}\n"
-               "\n";
-
-       static const GLchar* fragmenty_shader_code =
-               "#version 400 core\n"
-               "#extension GL_ARB_shader_subroutine : require\n"
-               "\n"
-               "precision highp float;\n"
-               "\n"
-               "// Subroutine type\n"
-               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
-               "\n"
-               "// Subroutine definition\n"
-               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left + right;\n"
-               "}\n"
-               "\n"
-               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
-               "{\n"
-               "    return left * right;\n"
-               "}\n"
-               "\n"
-               "// Sub routine uniform\n"
-               "subroutine uniform routine_type routine;\n"
-               "\n"
-               "// Input data\n"
-               "uniform vec4 uni_fs_left;\n"
-               "uniform vec4 uni_fs_right;\n"
-               "\n"
-               "in vec4 gs_fs_result;\n"
-               "\n"
-               "// Output\n"
-               "out vec4 fs_out_result;\n"
-               "\n"
-               "void main()\n"
-               "{\n"
-               "    fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
-               "}\n"
-               "\n";
-
-       out_vertex_shader_code                             = vertex_shader_code;
-       out_tesselation_control_shader_code     = tesselation_control_shader_code;
-       out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
-       out_geometry_shader_code                           = geometry_shader_code;
-       out_fragment_shader_code                           = fragmenty_shader_code;
-}
-
-/** Create <m_n_shared_contexts> shared contexts
- *
- **/
-void FunctionalTest20_21::initSharedContexts()
-{
-       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-       {
-               m_shared_contexts[i] = m_context.createSharedContext();
-       }
-}
-
-/** Prepare program(s)
- *
- * @param programs     An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5
- * @param is_separable Select if monolithic or separable programs should be prepared
- **/
-void FunctionalTest20_21::prepareProgram(Utils::program** programs, bool is_separable)
-{
-       /* Get shader sources */
-       const GLchar* vertex_shader_code;
-       const GLchar* tesselation_control_shader_code;
-       const GLchar* tesselation_evaluation_shader_code;
-       const GLchar* geometry_shader_code;
-       const GLchar* fragmenty_shader_code;
-
-       getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
-                          geometry_shader_code, fragmenty_shader_code);
-
-       /* Subroutines and uniform names */
-       static const GLchar* subroutine_names[] = { "add", "multiply" };
-       static const GLuint  n_subroutines              = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
-
-       static const GLchar* subroutine_uniform_name = "routine";
-
-       /* Build program */
-       if (false == is_separable)
-       {
-               programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
-                                                  tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
-                                                  0 /* varying_names */, 0 /* n_varying_names */);
-
-               programs[m_geometry_stage_index]                           = programs[m_fragment_stage_index];
-               programs[m_tesselation_control_stage_index]     = programs[m_fragment_stage_index];
-               programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
-               programs[m_vertex_stage_index]                             = programs[m_fragment_stage_index];
-       }
-       else
-       {
-               programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
-               programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
-               programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
-               programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
-                                                                                                                         true);
-               programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
-       }
-
-       /* Get subroutine indices */
-       for (GLuint i = 0; i < n_subroutines; ++i)
-       {
-               m_subroutine_indices[i].m_fragment_shader_stage =
-                       programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
-
-               m_subroutine_indices[i].m_geometry_shader_stage =
-                       programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
-
-               m_subroutine_indices[i].m_tesselation_control_shader_stage =
-                       programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
-                                                                                                                                                       GL_TESS_CONTROL_SHADER);
-
-               m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
-                       programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
-                                                                                                                                                          GL_TESS_EVALUATION_SHADER);
-
-               m_subroutine_indices[i].m_vertex_shader_stage =
-                       programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
-       }
-
-       /* Get subroutine uniform locations */
-       m_subroutine_uniform_locations.m_fragment_shader_stage =
-               programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
-
-       m_subroutine_uniform_locations.m_geometry_shader_stage =
-               programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
-
-       m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
-               programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
-                                                                                                                                                                 GL_TESS_CONTROL_SHADER);
-
-       m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
-               programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
-                                                                                                                                                                        GL_TESS_EVALUATION_SHADER);
-
-       m_subroutine_uniform_locations.m_vertex_shader_stage =
-               programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
-}
-
-/** Generate program pipeline for current context and attach separable programs
- *
- * @param out_pipeline_id Id of generated pipeline
- * @param programs        Collection of separable programs
- **/
-void FunctionalTest20_21::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
-{
-       /* GL entry points */
-       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
-
-       /* Generate */
-       gl.genProgramPipelines(1, &out_pipeline_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
-
-       /* Bind */
-       gl.bindProgramPipeline(out_pipeline_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
-
-       /* Set up programs */
-       gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
-
-       gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
-
-       gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
-                                               programs[m_tesselation_control_stage_index]->m_program_object_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
-
-       gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
-                                               programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
-
-       gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
-}
-
-/** Test specific case
- *
- * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
- *
- * @return True if test pass, false otherwise
- **/
-bool FunctionalTest20_21::testCase(const glw::GLuint bit_field[5])
-{
-       /* Storage for subroutine indices */
-       subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
-       subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
-
-       /* Prepare subroutine_indices with bit fields */
-       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
-       {
-               subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
-       };
-
-       /* Update subroutine uniforms, each context gets different set */
-       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-       {
-               m_shared_contexts[i]->makeCurrent();
-               updateCurrentSubroutineSet(subroutine_indices[i]);
-       }
-
-       m_context.getRenderContext().makeCurrent();
-       updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
-
-       /* Capture subroutine uniforms */
-       for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-       {
-               m_shared_contexts[i]->makeCurrent();
-               captureCurrentSubroutineSet(captured_subroutine_indices[i]);
-       }
-
-       m_context.getRenderContext().makeCurrent();
-       captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
-
-       /* Verify that captured uniforms match expected values */
-       for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
-       {
-               if (subroutine_indices[i] != captured_subroutine_indices[i])
-               {
-                       m_context.getTestContext().getLog()
-                               << tcu::TestLog::Message << "Error."
-                               << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
-                               << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
-                               << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
-                               << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
-                               << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
-                               << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
-                               << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
-                               << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
-                               << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
-                               << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage << tcu::TestLog::EndMessage;
-
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-/** Test a program or pipeline
- *
- * @param programs     An array of 5 programs\ pointers, as in preparePrograms
- * @param is_separable Selects if monolithic or separable programs should be used
- * @param test_cases   Collection of test cases
- * @param n_test_cases Number of test cases
- *
- * @return True if all cases pass, false otherwise
- **/
-bool FunctionalTest20_21::testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
-                                                                         glw::GLuint n_test_cases)
-{
-       /* Set program/pipeline as current for all contexts */
-       if (false == is_separable)
-       {
-               programs[0]->use();
-
-               for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-               {
-                       m_shared_contexts[i]->makeCurrent();
-                       programs[0]->use();
-               }
-       }
-       else
-       {
-               /* GL entry points */
-               const glw::Functions& gl = m_context.getRenderContext().getFunctions();
-
-               /* Make sure that program pipeline will be used */
-               gl.useProgram(0);
-               GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
-
-               prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
-
-               for (GLuint i = 0; i < m_n_shared_contexts; ++i)
-               {
-                       m_shared_contexts[i]->makeCurrent();
-
-                       /* Make sure that program pipeline will be used */
-                       gl.useProgram(0);
-                       GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
-
-                       prepareProgramPipeline(m_program_pipelines[i], programs);
-               }
-       }
-
-       /* Execute test */
-       bool result = true;
-       for (GLuint i = 0; i < n_test_cases; ++i)
-       {
-               if (false == testCase(test_cases[i]))
-               {
-                       result = false;
-                       break;
-               }
-       }
-
-       return result;
-}
-
-/** Set up subroutine uniforms for current program or pipeline
- *
- * @param set Set of subroutine indices
- **/
-void FunctionalTest20_21::updateCurrentSubroutineSet(const subroutineUniformSet& set)
-{
-       /* GL entry points */
-       const glw::Functions& gl = m_context.getRenderContext().getFunctions();
-
-       /* Fragment */
-       gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
-
-       /* Geometry */
-       gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
-
-       /* Tess ctrl */
-       gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
-
-       /* Tess eval */
-       gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
-
-       /* Vertex */
-       gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
-       GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
-}
-
 /** Constructor.
  *
  *  @param context Rendering context.
@@ -14518,7 +13784,6 @@ void ShaderSubroutineTests::init(void)
        addChild(new ShaderSubroutine::FunctionalTest16(m_context));
        addChild(new ShaderSubroutine::FunctionalTest17(m_context));
        addChild(new ShaderSubroutine::FunctionalTest18_19(m_context));
-       addChild(new ShaderSubroutine::FunctionalTest20_21(m_context));
        addChild(new ShaderSubroutine::NegativeTest1(m_context));
        addChild(new ShaderSubroutine::NegativeTest2(m_context));
        addChild(new ShaderSubroutine::NegativeTest3(m_context));
index 60c605a..99ca816 100644 (file)
@@ -1038,70 +1038,6 @@ private:
 };
 
 /**
- * * Create multiple contexts and verify that subroutine uniforms values
- *   are preserved for each program stage when switching rendering context.
- *
- * OpenGL 4.1 or ARB_separate_shader_objects support required
- * * Same as above, but use pipelines instead of monolithic program.
- **/
-class FunctionalTest20_21 : public deqp::TestCase
-{
-public:
-       /* Public methods */
-       FunctionalTest20_21(deqp::Context& context);
-
-       virtual void                                             deinit();
-       virtual tcu::TestNode::IterateResult iterate();
-
-private:
-       /* Private types */
-       struct subroutineUniformSet
-       {
-               bool operator!=(const subroutineUniformSet& arg) const;
-               void set(glw::GLuint bit_field, const subroutineUniformSet subroutine_indices[2]);
-
-               glw::GLuint m_vertex_shader_stage;
-               glw::GLuint m_tesselation_control_shader_stage;
-               glw::GLuint m_tesselation_evaluation_shader_stage;
-               glw::GLuint m_geometry_shader_stage;
-               glw::GLuint m_fragment_shader_stage;
-       };
-
-       /* Private methods */
-       void captureCurrentSubroutineSet(subroutineUniformSet& set);
-
-       void getShaders(const glw::GLchar*& out_vertex_shader_code, const glw::GLchar*& out_tesselation_control_shader_code,
-                                       const glw::GLchar*& out_tesselation_evaluation_shader_code,
-                                       const glw::GLchar*& out_geometry_shader_code, const glw::GLchar*& out_fragment_shader_code);
-
-       void initSharedContexts();
-
-       void prepareProgram(Utils::program** programs, bool is_separable);
-
-       void prepareProgramPipeline(glw::GLuint& pipeline_id, Utils::program** programs);
-
-       bool testCase(const glw::GLuint bit_field[5]);
-
-       bool testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
-                                        glw::GLuint n_test_cases);
-
-       void updateCurrentSubroutineSet(const subroutineUniformSet& set);
-
-       /* Private fields */
-       static const glw::GLuint m_n_shared_contexts;
-       static const glw::GLuint m_fragment_stage_index;
-       static const glw::GLuint m_geometry_stage_index;
-       static const glw::GLuint m_tesselation_control_stage_index;
-       static const glw::GLuint m_tesselation_evaluation_stage_index;
-       static const glw::GLuint m_vertex_stage_index;
-
-       glw::GLuint                      m_program_pipelines[5];
-       glu::RenderContext*  m_shared_contexts[4];
-       subroutineUniformSet m_subroutine_indices[2];
-       subroutineUniformSet m_subroutine_uniform_locations;
-};
-
-/**
  *  Test whether all INVALID_OPERATION, INVALID_VALUE and INVALID_ENUM
  *  errors related to subroutines usage are properly generated.
  **/
index 71b6723..c1281dc 100644 (file)
@@ -23,6 +23,7 @@ const char* mustpassDir = "gl_cts/data/mustpass/gl/khronos_mustpass_noctx/4.6.0.
 
 static const RunParams khronos_mustpass_gl_nocontext_first_cfg[] = {
        { glu::ApiType::core(3, 0), "khr-master", DE_NULL, "unspecified", 1, DE_NULL, 64, 64 },
+       { glu::ApiType::core(4, 0), "khr-master", DE_NULL, "unspecified", 1, DE_NULL, 64, 64 },
        { glu::ApiType::core(4, 5), "khr-master", DE_NULL, "unspecified", 1, DE_NULL, 64, 64 },
 };
 
index a1c1ba4..828b2cc 100644 (file)
@@ -76,6 +76,7 @@ MODULES = [
        Module("GTF-GL31",              "GL31"),
        Module("GTF-GL30",              "GL30"),
        Module("KHR-NOCTX-GL30","GL30"),
+       Module("KHR-NOCTX-GL40","GL40"),
        Module("KHR-NOCTX-GL45","GL45"),
 ]
 GLCTS_BIN_NAME = "glcts"
@@ -102,7 +103,7 @@ def getModulesPath (buildCfg):
 
 def getCaseListFileName (module, caseListType):
        mname = module.name
-       if mname == "KHR-NOCTX-ES2" or mname == "KHR-NOCTX-ES32" or mname == "KHR-NOCTX-GL30" or mname == "KHR-NOCTX-GL45":
+       if mname == "KHR-NOCTX-ES2" or mname == "KHR-NOCTX-ES32" or mname == "KHR-NOCTX-GL30" or mname == "KHR-NOCTX-GL40" or mname == "KHR-NOCTX-GL45":
                mname =  "KHR-NoContext"
        return "%s-cases.%s" % (mname, caseListType)
 
index 24ee524..c3531a2 100644 (file)
@@ -1013,6 +1013,7 @@ GL_MODULES                                                        = OrderedDict([
                ])
 
 NOCTX_GL30_KHR_MODULE                  = getModuleByName("KHR-NOCTX-GL30")
+NOCTX_GL40_KHR_MODULE                  = getModuleByName("KHR-NOCTX-GL40")
 NOCTX_GL45_KHR_MODULE                  = getModuleByName("KHR-NOCTX-GL45")
 
 GLCTS_NOCTX_GL30_KHR_PKG                       = Package(module = NOCTX_GL30_KHR_MODULE, configurations = [
@@ -1024,6 +1025,15 @@ GLCTS_NOCTX_GL30_KHR_PKG                 = Package(module = NOCTX_GL30_KHR_MODULE, configurati
                                        filters                 = [include("gl30-khr-master.txt")]),
        ])
 
+GLCTS_NOCTX_GL40_KHR_PKG                       = Package(module = NOCTX_GL40_KHR_MODULE, configurations = [
+               # Master
+               Configuration(name                      = "khr-master",
+                                       surfacewidth    = "64",
+                                       surfaceheight   = "64",
+                                       baseseed                = "1",
+                                       filters                 = [include("gl40-khr-master.txt")]),
+       ])
+
 GLCTS_NOCTX_GL45_KHR_PKG                       = Package(module = NOCTX_GL45_KHR_MODULE, configurations = [
                # Master
                Configuration(name                      = "khr-master",
@@ -1060,7 +1070,7 @@ def generateGLMustpass():
                        gl_packages.append(pkg1)
 
                mustpass = [Mustpass(project = GL_CTS_KHR_MP_PROJECT, version = "4.6.0.x", isCurrent=True, packages = gl_packages),
-                                       Mustpass(project = GL_CTS_NOCTX_PROJECT, version = "4.6.0.x", isCurrent=True, packages = [GLCTS_NOCTX_GL30_KHR_PKG, GLCTS_NOCTX_GL45_KHR_PKG]),
+                                       Mustpass(project = GL_CTS_NOCTX_PROJECT, version = "4.6.0.x", isCurrent=True, packages = [GLCTS_NOCTX_GL30_KHR_PKG, GLCTS_NOCTX_GL40_KHR_PKG, GLCTS_NOCTX_GL45_KHR_PKG]),
                                        ]
                return mustpass
 
index e96d2f8..21d103f 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "deDynamicLibrary.hpp"
 #include "deSTLUtil.hpp"
+#include "deSharedPtr.hpp"
 
 #include <string>
 #include <string>
@@ -129,7 +130,7 @@ private:
 class RenderContext : public GLRenderContext
 {
 public:
-                                                                               RenderContext                   (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
+                                                                               RenderContext                   (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config, const glu::RenderContext* sharedContext = DE_NULL);
        virtual                                                         ~RenderContext                  (void);
 
        virtual glu::ContextType                        getType                                 (void) const { return m_renderConfig.type;              }
@@ -147,13 +148,13 @@ public:
        virtual void                                            makeCurrent                             (void);
 
 private:
-       void                                                            create                                  (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
+       void                                                            create                                  (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config, const glu::RenderContext* sharedContext);
        void                                                            destroy                                 (void);
 
        const glu::RenderConfig                         m_renderConfig;
        const NativeWindowFactory* const        m_nativeWindowFactory;  // Stored in case window must be re-created
 
-       NativeDisplay*                                          m_display;
+       de::SharedPtr<NativeDisplay>            m_display;
        NativeWindow*                                           m_window;
        NativePixmap*                                           m_pixmap;
 
@@ -161,13 +162,14 @@ private:
        EGLConfig                                                       m_eglConfig;
        EGLSurface                                                      m_eglSurface;
        EGLContext                                                      m_eglContext;
+       EGLContext                                                      m_eglSharedContext;
 
        tcu::RenderTarget                                       m_glRenderTarget;
        de::DynamicLibrary*                                     m_dynamicGLLibrary;
        glw::Functions                                          m_glFunctions;
 };
 
-RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
+RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config, const glu::RenderContext* sharedContext)
        : m_renderConfig                (config)
        , m_nativeWindowFactory (windowFactory)
        , m_display                             (DE_NULL)
@@ -177,6 +179,7 @@ RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const
        , m_eglDisplay                  (EGL_NO_DISPLAY)
        , m_eglSurface                  (EGL_NO_SURFACE)
        , m_eglContext                  (EGL_NO_CONTEXT)
+       , m_eglSharedContext    (EGL_NO_CONTEXT)
 
        , m_dynamicGLLibrary    (DE_NULL)
 {
@@ -184,7 +187,7 @@ RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const
 
        try
        {
-               create(displayFactory, windowFactory, pixmapFactory, config);
+               create(displayFactory, windowFactory, pixmapFactory, config, sharedContext);
        }
        catch (...)
        {
@@ -206,7 +209,6 @@ RenderContext::~RenderContext(void)
 
        delete m_window;
        delete m_pixmap;
-       delete m_display;
        delete m_dynamicGLLibrary;
 }
 
@@ -305,15 +307,22 @@ glw::GenericFuncType RenderContext::getProcAddress (const char* name) const
        return (glw::GenericFuncType)m_display->getLibrary().getProcAddress(name);
 }
 
-void RenderContext::create (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
+void RenderContext::create (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config, const glu::RenderContext *sharedContext)
 {
        glu::RenderConfig::SurfaceType  surfaceType     = config.surfaceType;
 
        DE_ASSERT(displayFactory);
 
-       m_display               = displayFactory->createDisplay();
-       m_eglDisplay    = eglu::getDisplay(*m_display);
+       if (DE_NULL == sharedContext)
+               m_display = de::SharedPtr<NativeDisplay>(displayFactory->createDisplay());
+       else
+       {
+               const RenderContext* context = dynamic_cast<const RenderContext*>(sharedContext);
+               m_eglSharedContext                       = context->m_eglContext;
+               m_display                                        = context->m_display;
+       }
 
+       m_eglDisplay    = eglu::getDisplay(*m_display);
        const Library& egl = m_display->getLibrary();
 
        {
@@ -345,7 +354,7 @@ void RenderContext::create (const NativeDisplayFactory* displayFactory, const Na
                {
                        if (windowFactory)
                        {
-                               const WindowSurfacePair windowSurface = createWindow(m_display, windowFactory, m_eglDisplay, m_eglConfig, config);
+                               const WindowSurfacePair windowSurface = createWindow(m_display.get(), windowFactory, m_eglDisplay, m_eglConfig, config);
                                m_window                = windowSurface.first;
                                m_eglSurface    = windowSurface.second;
                        }
@@ -358,7 +367,7 @@ void RenderContext::create (const NativeDisplayFactory* displayFactory, const Na
                {
                        if (pixmapFactory)
                        {
-                               const PixmapSurfacePair pixmapSurface = createPixmap(m_display, pixmapFactory, m_eglDisplay, m_eglConfig, config);
+                               const PixmapSurfacePair pixmapSurface = createPixmap(m_display.get(), pixmapFactory, m_eglDisplay, m_eglConfig, config);
                                m_pixmap                = pixmapSurface.first;
                                m_eglSurface    = pixmapSurface.second;
                        }
@@ -375,7 +384,7 @@ void RenderContext::create (const NativeDisplayFactory* displayFactory, const Na
                        throw tcu::InternalError("Invalid surface type");
        }
 
-       m_eglContext = createGLContext(egl, m_eglDisplay, m_eglConfig, config.type, config.resetNotificationStrategy);
+       m_eglContext = createGLContext(egl, m_eglDisplay, m_eglConfig, config.type, m_eglSharedContext, config.resetNotificationStrategy);
 
        EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
 
@@ -473,7 +482,8 @@ void RenderContext::destroy (void)
                if (m_eglContext != EGL_NO_CONTEXT)
                        EGLU_CHECK_CALL(egl, destroyContext(m_eglDisplay, m_eglContext));
 
-               EGLU_CHECK_CALL(egl, terminate(m_eglDisplay));
+               if (m_eglSharedContext == EGL_NO_CONTEXT)
+                       EGLU_CHECK_CALL(egl, terminate(m_eglDisplay));
 
                m_eglDisplay    = EGL_NO_DISPLAY;
                m_eglSurface    = EGL_NO_SURFACE;
@@ -482,12 +492,10 @@ void RenderContext::destroy (void)
 
        delete m_window;
        delete m_pixmap;
-       delete m_display;
        delete m_dynamicGLLibrary;
 
        m_window                        = DE_NULL;
        m_pixmap                        = DE_NULL;
-       m_display                       = DE_NULL;
        m_dynamicGLLibrary      = DE_NULL;
 }
 
@@ -521,7 +529,7 @@ void RenderContext::postIterate (void)
 
                        try
                        {
-                               WindowSurfacePair windowSurface = createWindow(m_display, m_nativeWindowFactory, m_eglDisplay, m_eglConfig, m_renderConfig);
+                               WindowSurfacePair windowSurface = createWindow(m_display.get(), m_nativeWindowFactory, m_eglDisplay, m_eglConfig, m_renderConfig);
                                m_window                = windowSurface.first;
                                m_eglSurface    = windowSurface.second;
 
@@ -587,7 +595,7 @@ GLContextFactory::GLContextFactory (const NativeDisplayFactoryRegistry& displayF
 {
 }
 
-glu::RenderContext* GLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const
+glu::RenderContext* GLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine, const glu::RenderContext *sharedContext) const
 {
        const NativeDisplayFactory& displayFactory = selectNativeDisplayFactory(m_displayFactoryRegistry, cmdLine);
 
@@ -612,7 +620,7 @@ glu::RenderContext* GLContextFactory::createContext (const glu::RenderConfig& co
                pixmapFactory = DE_NULL;
        }
 
-       return new RenderContext(&displayFactory, windowFactory, pixmapFactory, config);
+       return new RenderContext(&displayFactory, windowFactory, pixmapFactory, config, sharedContext);
 }
 
 } // eglu
index 53617bf..2452306 100644 (file)
@@ -49,7 +49,7 @@ class GLContextFactory : public glu::ContextFactory
 {
 public:
                                                                                        GLContextFactory        (const NativeDisplayFactoryRegistry& displayFactoryRegistry);
-       virtual glu::RenderContext*                             createContext           (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const;
+       virtual glu::RenderContext*                             createContext           (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine, const glu::RenderContext *sharedContext) const;
 
 private:
        const NativeDisplayFactoryRegistry&             m_displayFactoryRegistry;
index cca5681..9c0a308 100644 (file)
@@ -80,6 +80,7 @@ EGLContext createGLContext (const Library&                                    egl,
                                                        EGLDisplay                                              display,
                                                        EGLContext                                              eglConfig,
                                                        const glu::ContextType&                 contextType,
+                                                       eglw::EGLContext                                sharedContext,
                                                        glu::ResetNotificationStrategy  resetNotificationStrategy)
 {
        const bool                      khrCreateContextSupported                       = hasExtension(egl, display, "EGL_KHR_create_context");
@@ -193,7 +194,7 @@ EGLContext createGLContext (const Library&                                  egl,
        attribList.push_back(EGL_NONE);
 
        EGLU_CHECK_CALL(egl, bindAPI(api));
-       context = egl.createContext(display, eglConfig, EGL_NO_CONTEXT, &(attribList[0]));
+       context = egl.createContext(display, eglConfig, sharedContext, &(attribList[0]));
        EGLU_CHECK_MSG(egl, "eglCreateContext()");
 
        return context;
index be55740..fb26fb1 100644 (file)
@@ -45,6 +45,7 @@ eglw::EGLContext      createGLContext                 (const eglw::Library&                   egl,
                                                                                         eglw::EGLDisplay                               display,
                                                                                         eglw::EGLConfig                                config,
                                                                                         const glu::ContextType&                contextType,
+                                                                                        eglw::EGLContext                               sharedContext = EGL_NO_CONTEXT,
                                                                                         glu::ResetNotificationStrategy resetNotificationStrategy = glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED);
 
 eglw::EGLConfig                chooseConfig                    (const eglw::Library&                   egl,
index 4c75ae5..54b42f5 100644 (file)
@@ -57,11 +57,12 @@ public:
         * Only single context will be active concurrently and it will be accessed
         * only from the calling thread.
         *
-        * \param config        Rendering context configuration
-        * \param cmdLine       Command line for extra arguments
+        * \param config                Rendering context configuration
+        * \param cmdLine               Command line for extra arguments
+        * \param sharedContext Context with which objects should be shared
         * \return Rendering context wrapper object.
         *//*--------------------------------------------------------------------*/
-       virtual RenderContext*  createContext           (const RenderConfig& config, const tcu::CommandLine& cmdLine) const = 0;
+       virtual RenderContext*  createContext           (const RenderConfig& config, const tcu::CommandLine& cmdLine, const glu::RenderContext* sharedContext) const = 0;
 
 private:
                                                        ContextFactory          (const ContextFactory&);
index f1469ac..e71848a 100644 (file)
@@ -180,7 +180,7 @@ FboRenderContext::FboRenderContext (const ContextFactory& factory, const RenderC
                nativeRenderConfig.type                         = config.type;
                nativeRenderConfig.windowVisibility     = config.windowVisibility;
                // \note All other properties are defaults, mostly DONT_CARE
-               m_context = factory.createContext(nativeRenderConfig, cmdLine);
+               m_context = factory.createContext(nativeRenderConfig, cmdLine, DE_NULL);
                createFramebuffer(config);
        }
        catch (...)
index 3b3b6fc..6bb3e4a 100644 (file)
@@ -130,7 +130,7 @@ static ContextFlags parseContextFlags (const std::string& flagsStr)
        return flags;
 }
 
-RenderContext* createRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config)
+RenderContext* createRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config, const RenderContext* sharedContext)
 {
        const ContextFactoryRegistry&   registry                = platform.getGLPlatform().getContextFactoryRegistry();
        const char*                                             factoryName             = cmdLine.getGLContextType();
@@ -161,9 +161,13 @@ RenderContext* createRenderContext (tcu::Platform& platform, const tcu::CommandL
                factory = registry.getDefaultFactory();
 
        if (cmdLine.getSurfaceType() == tcu::SURFACETYPE_FBO)
+       {
+               if (sharedContext)
+                       TCU_FAIL("Shared context not implemented for  FBO surface type");
                return new FboRenderContext(*factory, config, cmdLine);
+       }
        else
-               return factory->createContext(config, cmdLine);
+               return factory->createContext(config, cmdLine, sharedContext);
 }
 
 RenderContext* createDefaultRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType)
index 0c6871c..e17cb59 100644 (file)
@@ -232,7 +232,7 @@ private:
 
 // Utilities
 
-RenderContext*         createRenderContext                             (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config);
+RenderContext*         createRenderContext                             (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config, const RenderContext* sharedContext = DE_NULL);
 RenderContext*         createDefaultRenderContext              (tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType);
 
 void                           initCoreFunctions                               (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
index 0194772..29a45e3 100644 (file)
@@ -82,8 +82,9 @@ class GlxContextFactory : public glu::ContextFactory
 public:
                                                        GlxContextFactory       (EventState& eventState);
                                                        ~GlxContextFactory      (void);
-       RenderContext*                  createContext           (const RenderConfig&    config,
-                                                                                                const CommandLine&             cmdLine) const;
+       RenderContext*                  createContext           (const RenderConfig&       config,
+                                                                                                const CommandLine&                cmdLine,
+                                                                                                const glu::RenderContext* sharedContext) const;
 
        EventState&                             getEventState           (void) const { return m_eventState;}
 
@@ -119,6 +120,7 @@ public:
        Visual*                                 getXVisual                      (void) { return m_visual; }
        GLXContext                              createContext           (const GlxContextFactory&               factory,
                                                                                                 const ContextType&                             contextType,
+                                                                                                const glu::RenderContext*              sharedContext,
                                                                                                 glu::ResetNotificationStrategy resetNotificationStrategy);
        GLXWindow                               createWindow            (::Window xWindow);
        GlxDisplay&                             getGlxDisplay           (void) { return m_display; }
@@ -171,7 +173,9 @@ class GlxRenderContext : public RenderContext
 {
 public:
                                                                                GlxRenderContext        (const GlxContextFactory&       factory,
-                                                                                                                        const RenderConfig&            config);
+                                                                                                                        const RenderConfig&            config,
+                                                                                                                        const glu::RenderContext*      sharedContext
+                                                                                                                        );
                                                                                ~GlxRenderContext       (void);
        virtual ContextType                                     getType                         (void) const;
        virtual void                                            postIterate                     (void);
@@ -179,6 +183,7 @@ public:
        void                                                            clearCurrent            (void);
        virtual const glw::Functions&           getFunctions            (void) const;
        virtual const tcu::RenderTarget&        getRenderTarget         (void) const;
+       const GLXContext&                                       getGLXContext           (void) const;
 
 private:
        GlxDisplay                                                      m_glxDisplay;
@@ -214,11 +219,12 @@ GlxContextFactory::GlxContextFactory (EventState& eventState)
        XSetErrorHandler(tcuLnxX11GlxErrorHandler);
 }
 
-RenderContext* GlxContextFactory::createContext (const RenderConfig&   config,
-                                                                                                const CommandLine&             cmdLine) const
+RenderContext* GlxContextFactory::createContext (const RenderConfig&           config,
+                                                                                                const CommandLine&                     cmdLine,
+                                                                                                const glu::RenderContext*      sharedContext) const
 {
        DE_UNREF(cmdLine);
-       GlxRenderContext* const renderContext = new GlxRenderContext(*this, config);
+       GlxRenderContext* const renderContext = new GlxRenderContext(*this, config, sharedContext);
        return renderContext;
 }
 
@@ -304,6 +310,7 @@ int GlxVisual::getAttrib (int attribute)
 
 GLXContext GlxVisual::createContext (const GlxContextFactory&          factory,
                                                                         const ContextType&                             contextType,
+                                                                        const glu::RenderContext*              sharedContext,
                                                                         glu::ResetNotificationStrategy resetNotificationStrategy)
 {
        std::vector<int>        attribs;
@@ -391,8 +398,11 @@ GLXContext GlxVisual::createContext (const GlxContextFactory&              factory,
        // Terminate attrib list
        attribs.push_back(None);
 
+       const GlxRenderContext* sharedGlxRenderContext = dynamic_cast<const GlxRenderContext*>(sharedContext);
+       const GLXContext& sharedGLXContext = sharedGlxRenderContext ? sharedGlxRenderContext->getGLXContext() : DE_NULL;
+
        return TCU_CHECK_GLX(factory.m_glXCreateContextAttribsARB(
-                                                        getXDisplay(), m_fbConfig, DE_NULL, True, &attribs[0]));
+                                                        getXDisplay(), m_fbConfig, sharedGLXContext, True, &attribs[0]));
 }
 
 GLXWindow GlxVisual::createWindow (::Window xWindow)
@@ -683,11 +693,12 @@ struct GlxFunctionLoader : public glw::FunctionLoader
 };
 
 GlxRenderContext::GlxRenderContext (const GlxContextFactory&   factory,
-                                                                       const RenderConfig&                     config)
+                                                                       const RenderConfig&                     config,
+                                                                       const glu::RenderContext*       sharedContext)
        : m_glxDisplay          (factory.getEventState(), DE_NULL)
        , m_glxVisual           (chooseVisual(m_glxDisplay, config))
        , m_type                        (config.type)
-       , m_GLXContext          (m_glxVisual.createContext(factory, config.type, config.resetNotificationStrategy))
+       , m_GLXContext          (m_glxVisual.createContext(factory, config.type, sharedContext, config.resetNotificationStrategy))
        , m_glxDrawable         (createDrawable(m_glxVisual, config))
        , m_renderTarget        (m_glxDrawable->getWidth(), m_glxDrawable->getHeight(),
                                                 PixelFormat(m_glxVisual.getAttrib(GLX_RED_SIZE),
@@ -745,6 +756,11 @@ const glw::Functions& GlxRenderContext::getFunctions (void) const
        return m_functions;
 }
 
+const GLXContext& GlxRenderContext::getGLXContext (void) const
+{
+       return m_GLXContext;
+}
+
 MovePtr<ContextFactory> createContextFactory (EventState& eventState)
 {
        return MovePtr<ContextFactory>(new GlxContextFactory(eventState));
index d466185..2db64f9 100644 (file)
@@ -34,7 +34,7 @@ NullGLContextFactory::NullGLContextFactory (void)
 {
 }
 
-glu::RenderContext* NullGLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
+glu::RenderContext* NullGLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&, const glu::RenderContext*) const
 {
        return new RenderContext(config);
 }
index 3f0e975..ee05c5c 100644 (file)
@@ -35,7 +35,7 @@ class NullGLContextFactory : public glu::ContextFactory
 {
 public:
                                                NullGLContextFactory    (void);
-       glu::RenderContext*     createContext                   (const glu::RenderConfig& config, const tcu::CommandLine&) const;
+       glu::RenderContext*     createContext                   (const glu::RenderConfig& config, const tcu::CommandLine&, const glu::RenderContext*) const;
 };
 
 } // null
index 6e8ec31..0bbca82 100644 (file)
@@ -401,6 +401,7 @@ PixelFormatInfo Core::getPixelFormatInfo (HDC deviceCtx, int pixelFormat) const
 
 Context::Context (const Core*                                          core,
                                  HDC                                                           deviceCtx,
+                                 const Context*                                        sharedContext,
                                  glu::ContextType                                      ctxType,
                                  int                                                           pixelFormat,
                                  glu::ResetNotificationStrategy        resetNotificationStrategy)
@@ -414,6 +415,7 @@ Context::Context (const Core*                                               core,
        // Context version and profile
        {
                int     profileBit      = 0;
+               HGLRC sharedCtx = DE_NULL;
                int minor               = ctxType.getMinorVersion();
                int major               = ctxType.getMajorVersion();
 
@@ -505,11 +507,15 @@ Context::Context (const Core*                                             core,
                        throw ResourceError("Failed to set pixel format");
        }
 
+       HGLRC sharedCtx = DE_NULL;
+       if (DE_NULL != sharedContext)
+               sharedCtx = sharedContext->m_context;
+
        // Terminate attribList
        attribList.push_back(0);
 
        // Create context
-       m_context = wgl.createContextAttribsARB(deviceCtx, (HGLRC)0, &attribList[0]);
+       m_context = wgl.createContextAttribsARB(deviceCtx, sharedCtx, &attribList[0]);
 
        if (!m_context)
                TCU_THROW(ResourceError, "Failed to create WGL context");
index cafae1c..6f50632 100644 (file)
@@ -197,6 +197,7 @@ class Context
 public:
                                                Context                         (const Core*                                    core,
                                                                                         HDC                                                    deviceCtx,
+                                                                                        const Context*                                 sharedContext,
                                                                                         glu::ContextType                               ctxType,
                                                                                         int                                                    pixelFormat,
                                                                                         glu::ResetNotificationStrategy resetNotificationStrategy);
index 17c6bc8..2521129 100644 (file)
@@ -65,7 +65,7 @@ private:
 class WGLContext : public glu::RenderContext
 {
 public:
-                                                                       WGLContext                      (HINSTANCE instance, const wgl::Core& wglCore, const glu::RenderConfig& config);
+                                                                       WGLContext                      (HINSTANCE instance, const wgl::Core& wglCore, const WGLContext* sharedContext, const glu::RenderConfig& config);
                                                                        ~WGLContext                     (void);
 
        glu::ContextType                                getType                         (void) const    { return m_contextType;                 }
@@ -90,7 +90,7 @@ private:
        glw::Functions                                  m_functions;
 };
 
-WGLContext::WGLContext (HINSTANCE instance, const wgl::Core& wglCore, const glu::RenderConfig& config)
+WGLContext::WGLContext (HINSTANCE instance, const wgl::Core& wglCore, const WGLContext* sharedContext, const glu::RenderConfig& config)
        : m_contextType (config.type)
        , m_window              (instance,
                                         config.width   != glu::RenderConfig::DONT_CARE ? config.width  : DEFAULT_WINDOW_WIDTH,
@@ -112,7 +112,11 @@ WGLContext::WGLContext (HINSTANCE instance, const wgl::Core& wglCore, const glu:
        if (pixelFormat < 0)
                throw NotSupportedError("Compatible WGL pixel format not found");
 
-       m_context = new wgl::Context(&wglCore, deviceCtx, config.type, pixelFormat, config.resetNotificationStrategy);
+       const wgl::Context* sharedCtx = DE_NULL;
+       if (DE_NULL != sharedContext)
+               sharedCtx = sharedContext->m_context;
+
+       m_context = new wgl::Context(&wglCore, deviceCtx, sharedCtx, config.type, pixelFormat, config.resetNotificationStrategy);
 
        try
        {
@@ -174,9 +178,11 @@ ContextFactory::ContextFactory (HINSTANCE instance)
 {
 }
 
-glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
+glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig&  config, const tcu::CommandLine&,
+                                                                                                  const glu::RenderContext* sharedContext) const
 {
-       return new WGLContext(m_instance, m_wglCore, config);
+       const WGLContext* sharedWGLContext = static_cast<const WGLContext*>(sharedContext);
+       return new WGLContext(m_instance, m_wglCore, sharedWGLContext, config);
 }
 
 } // wgl
index b3301e1..2994cba 100644 (file)
@@ -36,7 +36,8 @@ class ContextFactory : public glu::ContextFactory
 {
 public:
                                                                ContextFactory  (HINSTANCE instance);
-       virtual glu::RenderContext*     createContext   (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const;
+       virtual glu::RenderContext*     createContext   (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine,
+                                                                                                const glu::RenderContext* sharedContext) const;
 
 private:
        const HINSTANCE                         m_instance;