Merge gerrit/vulkan-cts-1.0.1 into gerrit/vulkan-cts-1.0-dev
[platform/upstream/VK-GL-CTS.git] / framework / opengl / gluES3PlusWrapperContext.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
3  * ------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief OpenGL ES 3plus wrapper context.
22  *//*--------------------------------------------------------------------*/
23
24 #include "gluES3PlusWrapperContext.hpp"
25 #include "gluRenderContext.hpp"
26 #include "gluRenderConfig.hpp"
27 #include "glwInitFunctions.hpp"
28 #include "glwFunctionLoader.hpp"
29 #include "gluContextFactory.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluShaderUtil.hpp"
32 #include "deThreadLocal.hpp"
33 #include "deSTLUtil.hpp"
34 #include "deUniquePtr.hpp"
35 #include "glwEnums.hpp"
36
37 #include <sstream>
38 #include <vector>
39 #include <string>
40 #include <cstring>
41 #include <algorithm>
42 #include <map>
43
44 namespace glu
45 {
46
47 namespace es3plus
48 {
49
50 using std::vector;
51 using std::string;
52
53 class Context
54 {
55 public:
56                                                                 Context                 (const glu::RenderContext& ctx);
57                                                                 ~Context                (void);
58
59         void                                            addExtension    (const char* name);
60
61         const glw::Functions&           gl;                     //!< GL 4.3 core context functions.
62
63         // Wrapper state.
64         string                                          vendor;
65         string                                          version;
66         string                                          renderer;
67         string                                          shadingLanguageVersion;
68         string                                          extensions;
69         vector<string>                          extensionList;
70         bool                                            primitiveRestartEnabled;
71
72         deUint32                                        defaultVAO;
73         bool                                            defaultVAOBound;
74
75         const glu::GLSLVersion          nativeGLSLVersion;
76 };
77
78 Context::Context (const glu::RenderContext& ctx)
79         : gl                                            (ctx.getFunctions())
80         , vendor                                        ("drawElements")
81         , version                                       ("OpenGL ES 3.2")
82         , renderer                                      ((const char*)gl.getString(GL_RENDERER))
83         , shadingLanguageVersion        ("OpenGL ES GLSL ES 3.2")
84         , primitiveRestartEnabled       (false)
85         , defaultVAO                            (0)
86         , defaultVAOBound                       (false)
87         , nativeGLSLVersion                     (glu::getContextTypeGLSLVersion(ctx.getType()))
88 {
89         const de::UniquePtr<glu::ContextInfo> ctxInfo(glu::ContextInfo::create(ctx));
90
91         gl.genVertexArrays(1, &defaultVAO);
92         if (gl.getError() != GL_NO_ERROR || defaultVAO == 0)
93                 throw tcu::InternalError("Failed to allocate VAO for emulation");
94
95         gl.bindVertexArray(defaultVAO);
96         if (gl.getError() != GL_NO_ERROR)
97                 throw tcu::InternalError("Failed to bind default VAO");
98         defaultVAOBound = true;
99
100         gl.enable(GL_PROGRAM_POINT_SIZE);
101         gl.getError(); // supress potential errors, feature is not critical
102
103         gl.enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
104         gl.getError(); // suppress
105
106         // Extensions
107         addExtension("GL_OES_texture_stencil8");
108         addExtension("GL_OES_sample_shading");
109         addExtension("GL_OES_sample_variables");
110         addExtension("GL_OES_shader_multisample_interpolation");
111         addExtension("GL_OES_shader_image_atomic");
112         addExtension("GL_OES_texture_storage_multisample_2d_array");
113
114         // Enable only if base ctx supports these or compatible GL_NV_blend_equation_advanced ext
115         if (ctxInfo->isExtensionSupported("GL_NV_blend_equation_advanced") ||
116                 ctxInfo->isExtensionSupported("GL_KHR_blend_equation_advanced"))
117         {
118                 addExtension("GL_KHR_blend_equation_advanced");
119         }
120         if (ctxInfo->isExtensionSupported("GL_NV_blend_equation_advanced_coherent") ||
121                 ctxInfo->isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"))
122         {
123                 addExtension("GL_KHR_blend_equation_advanced_coherent");
124         }
125
126         addExtension("GL_EXT_shader_io_blocks");
127         addExtension("GL_EXT_geometry_shader");
128         addExtension("GL_EXT_geometry_point_size");
129         addExtension("GL_EXT_tessellation_shader");
130         addExtension("GL_EXT_tessellation_point_size");
131         addExtension("GL_EXT_gpu_shader5");
132         addExtension("GL_KHR_debug");
133         addExtension("GL_EXT_texture_cube_map_array");
134         addExtension("GL_EXT_shader_implicit_conversions");
135         addExtension("GL_EXT_primitive_bounding_box");
136         addExtension("GL_EXT_texture_sRGB_decode");
137         addExtension("GL_EXT_texture_border_clamp");
138         addExtension("GL_EXT_texture_buffer");
139         addExtension("GL_EXT_draw_buffers_indexed");
140 }
141
142 Context::~Context (void)
143 {
144         if (defaultVAO)
145                 gl.deleteVertexArrays(1, &defaultVAO);
146 }
147
148 void Context::addExtension (const char* name)
149 {
150         if (!extensions.empty())
151                 extensions += " ";
152         extensions += name;
153
154         extensionList.push_back(name);
155 }
156
157 static de::ThreadLocal tls_context;
158
159 void setCurrentContext (Context* context)
160 {
161         tls_context.set(context);
162 }
163
164 inline Context* getCurrentContext (void)
165 {
166         return (Context*)tls_context.get();
167 }
168
169 static GLW_APICALL void GLW_APIENTRY getIntegerv (deUint32 pname, deInt32* params)
170 {
171         Context* context = getCurrentContext();
172
173         if (context)
174         {
175                 if (pname == GL_NUM_EXTENSIONS && params)
176                         *params = (deInt32)context->extensionList.size();
177                 else
178                         context->gl.getIntegerv(pname, params);
179         }
180 }
181
182 static GLW_APICALL const glw::GLubyte* GLW_APIENTRY getString (deUint32 name)
183 {
184         Context* context = getCurrentContext();
185
186         if (context)
187         {
188                 switch (name)
189                 {
190                         case GL_VENDOR:                                         return (const glw::GLubyte*)context->vendor.c_str();
191                         case GL_VERSION:                                        return (const glw::GLubyte*)context->version.c_str();
192                         case GL_RENDERER:                                       return (const glw::GLubyte*)context->renderer.c_str();
193                         case GL_SHADING_LANGUAGE_VERSION:       return (const glw::GLubyte*)context->shadingLanguageVersion.c_str();
194                         case GL_EXTENSIONS:                                     return (const glw::GLubyte*)context->extensions.c_str();
195                         default:                                                        return context->gl.getString(name);
196                 }
197         }
198         else
199                 return DE_NULL;
200 }
201
202 static GLW_APICALL const glw::GLubyte* GLW_APIENTRY getStringi (deUint32 name, deUint32 index)
203 {
204         Context* context = getCurrentContext();
205
206         if (context)
207         {
208                 if (name == GL_EXTENSIONS)
209                 {
210                         if ((size_t)index < context->extensionList.size())
211                                 return (const glw::GLubyte*)context->extensionList[index].c_str();
212                         else
213                                 return context->gl.getStringi(name, ~0u);
214                 }
215                 else
216                         return context->gl.getStringi(name, index);
217         }
218         else
219                 return DE_NULL;
220 }
221
222 static GLW_APICALL void GLW_APIENTRY enable (deUint32 cap)
223 {
224         Context* context = getCurrentContext();
225
226         if (context)
227         {
228                 if (cap == GL_PRIMITIVE_RESTART_FIXED_INDEX)
229                 {
230                         context->primitiveRestartEnabled = true;
231                         // \todo [2013-09-30 pyry] Call to glPrimitiveRestartIndex() is required prior to all draw calls!
232                 }
233                 else
234                         context->gl.enable(cap);
235         }
236 }
237
238 static GLW_APICALL void GLW_APIENTRY disable (deUint32 cap)
239 {
240         Context* context = getCurrentContext();
241
242         if (context)
243         {
244                 if (cap == GL_PRIMITIVE_RESTART_FIXED_INDEX)
245                         context->primitiveRestartEnabled = false;
246                 else
247                         context->gl.disable(cap);
248         }
249 }
250
251 static GLW_APICALL void GLW_APIENTRY bindVertexArray (deUint32 array)
252 {
253         Context* context = getCurrentContext();
254
255         if (context)
256         {
257                 context->gl.bindVertexArray(array == 0 ? context->defaultVAO : array);
258                 context->defaultVAOBound = (array == 0);
259         }
260 }
261
262 static GLW_APICALL void GLW_APIENTRY hint (deUint32 target, deUint32 mode)
263 {
264         Context* context = getCurrentContext();
265
266         if (context)
267         {
268                 if (target != GL_GENERATE_MIPMAP_HINT)
269                         context->gl.hint(target, mode);
270                 // \todo [2013-09-30 pyry] Verify mode.
271         }
272 }
273
274 static void translateShaderSource (deUint32 shaderType, std::ostream& dst, const std::string& src, const std::vector<std::string>& filteredExtensions, GLSLVersion version)
275 {
276         bool                            foundVersion            = false;
277         std::istringstream      istr                            (src);
278         std::string                     line;
279         int                                     srcLineNdx                      = 1;
280         bool                            preprocessorSection     = true;
281
282         while (std::getline(istr, line, '\n'))
283         {
284                 if (preprocessorSection && !line.empty() && line[0] != '#')
285                 {
286                         preprocessorSection = false;
287
288                         // ARB_separate_shader_objects requires gl_PerVertex to be explicitly declared
289                         if (shaderType == GL_VERTEX_SHADER)
290                         {
291                                 dst << "out gl_PerVertex {\n"
292                                         << "    vec4 gl_Position;\n"
293                                         << "    float gl_PointSize;\n"
294                                         << "    float gl_ClipDistance[];\n"
295                                         << "};\n"
296                                         << "#line " << (srcLineNdx + 1) << "\n";
297                         }
298                         else if (shaderType == GL_TESS_CONTROL_SHADER)
299                         {
300                                 dst << "#extension GL_ARB_tessellation_shader : enable\n"
301                                         << "in gl_PerVertex {\n"
302                                         << "    highp vec4 gl_Position;\n"
303                                         << "    highp float gl_PointSize;\n"
304                                         << "} gl_in[gl_MaxPatchVertices];\n"
305                                         << "out gl_PerVertex {\n"
306                                         << "    highp vec4 gl_Position;\n"
307                                         << "    highp float gl_PointSize;\n"
308                                         << "} gl_out[];\n"
309                                         << "#line " << (srcLineNdx + 1) << "\n";
310                         }
311                         else if (shaderType == GL_TESS_EVALUATION_SHADER)
312                         {
313                                 dst << "#extension GL_ARB_tessellation_shader : enable\n"
314                                         << "in gl_PerVertex {\n"
315                                         << "    highp vec4 gl_Position;\n"
316                                         << "    highp float gl_PointSize;\n"
317                                         << "} gl_in[gl_MaxPatchVertices];\n"
318                                         << "out gl_PerVertex {\n"
319                                         << "    highp vec4 gl_Position;\n"
320                                         << "    highp float gl_PointSize;\n"
321                                         << "};\n"
322                                         << "#line " << (srcLineNdx + 1) << "\n";
323                         }
324                         else if (shaderType == GL_GEOMETRY_SHADER)
325                         {
326                                 dst << "in gl_PerVertex {\n"
327                                         << "    highp vec4 gl_Position;\n"
328                                         << "    highp float gl_PointSize;\n"
329                                         << "} gl_in[];\n"
330                                         << "out gl_PerVertex {\n"
331                                         << "    highp vec4 gl_Position;\n"
332                                         << "    highp float gl_PointSize;\n"
333                                         << "};\n"
334                                         << "#line " << (srcLineNdx + 1) << "\n";
335                         }
336
337                         // GL_EXT_primitive_bounding_box tessellation no-op fallback
338                         if (shaderType == GL_TESS_CONTROL_SHADER)
339                         {
340                                 dst << "#define gl_BoundingBoxEXT _dummy_unused_output_for_primitive_bbox\n"
341                                         << "patch out vec4 _dummy_unused_output_for_primitive_bbox[2];\n"
342                                         << "#line " << (srcLineNdx + 1) << "\n";
343                         }
344                 }
345
346                 if (line == "#version 310 es" || line == "#version 320 es")
347                 {
348                         foundVersion = true;
349                         dst << glu::getGLSLVersionDeclaration(version) << "\n";
350                 }
351                 else if (line == "#version 300 es")
352                 {
353                         foundVersion = true;
354                         dst << "#version 330\n";
355                 }
356                 else if (line.substr(0, 10) == "precision ")
357                 {
358                         const size_t    precPos         = 10;
359                         const size_t    precEndPos      = line.find(' ', precPos);
360                         const size_t    endPos          = line.find(';');
361
362                         if (precEndPos != std::string::npos && endPos != std::string::npos && endPos > precEndPos+1)
363                         {
364                                 const size_t            typePos         = precEndPos+1;
365                                 const std::string       precision       = line.substr(precPos, precEndPos-precPos);
366                                 const std::string       type            = line.substr(typePos, endPos-typePos);
367                                 const bool                      precOk          = precision == "lowp" || precision == "mediump" || precision == "highp";
368
369                                 if (precOk &&
370                                         (type == "image2D" || type == "uimage2D" || type == "iimage2D" ||
371                                          type == "imageCube" || type == "uimageCube" || type == "iimageCube" ||
372                                          type == "image3D" || type == "iimage3D" || type == "uimage3D" ||
373                                          type == "image2DArray" || type == "iimage2DArray" || type == "uimage2DArray" ||
374                                          type == "imageCubeArray" || type == "iimageCubeArray" || type == "uimageCubeArray"))
375                                         dst << "// "; // Filter out statement
376                         }
377
378                         dst << line << "\n";
379                 }
380                 else if (line.substr(0, 11) == "#extension ")
381                 {
382                         const size_t    extNamePos              = 11;
383                         const size_t    extNameEndPos   = line.find_first_of(" :", extNamePos);
384                         const size_t    behaviorPos             = line.find_first_not_of(" :", extNameEndPos);
385
386                         if (extNameEndPos != std::string::npos && behaviorPos != std::string::npos)
387                         {
388                                 const std::string       extName                         = line.substr(extNamePos, extNameEndPos-extNamePos);
389                                 const std::string       behavior                        = line.substr(behaviorPos);
390                                 const bool                      filteredExtension       = de::contains(filteredExtensions.begin(), filteredExtensions.end(), extName);
391                                 const bool                      validBehavior           = behavior == "require" || behavior == "enable" || behavior == "warn" || behavior == "disable";
392
393                                 if (filteredExtension && validBehavior)
394                                         dst << "// "; // Filter out extension
395                         }
396                         dst << line << "\n";
397                 }
398                 else if (line.substr(0, 21) == "layout(blend_support_")
399                         dst << "// " << line << "\n";
400                 else
401                         dst << line << "\n";
402
403                 srcLineNdx += 1;
404         }
405
406         DE_ASSERT(foundVersion);
407         DE_UNREF(foundVersion);
408 }
409
410 static std::string translateShaderSources (deUint32 shaderType, deInt32 count, const char* const* strings, const int* length, const std::vector<std::string>& filteredExtensions, GLSLVersion version)
411 {
412         std::ostringstream      srcIn;
413         std::ostringstream      srcOut;
414
415         for (int ndx = 0; ndx < count; ndx++)
416         {
417                 const int len = length && length[ndx] >= 0 ? length[ndx] : (int)strlen(strings[ndx]);
418                 srcIn << std::string(strings[ndx], strings[ndx] + len);
419         }
420
421         translateShaderSource(shaderType, srcOut, srcIn.str(), filteredExtensions, version);
422
423         return srcOut.str();
424 }
425
426 static GLW_APICALL void GLW_APIENTRY shaderSource (deUint32 shader, deInt32 count, const char* const* strings, const int* length)
427 {
428         Context* context = getCurrentContext();
429
430         if (context)
431         {
432                 if (count > 0 && strings)
433                 {
434                         deInt32                         shaderType = GL_NONE;
435                         context->gl.getShaderiv(shader, GL_SHADER_TYPE, &shaderType);
436                         {
437                                 const std::string       translatedSrc   = translateShaderSources(shaderType, count, strings, length, context->extensionList, context->nativeGLSLVersion);
438                                 const char*                     srcPtr                  = translatedSrc.c_str();
439                                 context->gl.shaderSource(shader, 1, &srcPtr, DE_NULL);
440                         }
441                 }
442                 else
443                         context->gl.shaderSource(shader, count, strings, length);
444         }
445 }
446
447 static GLW_APICALL void GLW_APIENTRY bindFramebuffer (deUint32 target, deUint32 framebuffer)
448 {
449         Context* context = getCurrentContext();
450
451         if (context)
452         {
453                 context->gl.bindFramebuffer(target, framebuffer);
454
455                 // Emulate ES behavior where sRGB conversion is only controlled by color buffer format.
456                 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER)
457                         ((framebuffer != 0) ? context->gl.enable : context->gl.disable)(GL_FRAMEBUFFER_SRGB);
458         }
459 }
460
461 static GLW_APICALL void GLW_APIENTRY blendBarrierKHR (void)
462 {
463         Context* context = getCurrentContext();
464
465         if (context)
466         {
467                 // \todo [2014-03-18 pyry] Use BlendBarrierNV() if supported
468                 context->gl.finish();
469         }
470 }
471
472 static GLW_APICALL deUint32 GLW_APIENTRY createShaderProgramv (deUint32 type, deInt32 count, const char* const* strings)
473 {
474         Context* context = getCurrentContext();
475
476         if (context)
477         {
478                 if (count > 0 && strings)
479                 {
480                         const std::string       translatedSrc   = translateShaderSources(type, count, strings, DE_NULL, context->extensionList, context->nativeGLSLVersion);
481                         const char*                     srcPtr                  = translatedSrc.c_str();
482                         return context->gl.createShaderProgramv(type, 1, &srcPtr);
483                 }
484                 else
485                         return context->gl.createShaderProgramv(type, count, strings);
486         }
487         return 0;
488 }
489
490 static GLW_APICALL void GLW_APIENTRY dummyPrimitiveBoundingBox (float minX, float minY, float minZ, float minW, float maxX, float maxY, float maxZ, float maxW)
491 {
492         // dummy no-op. No-op is a valid implementation. States queries are not emulated.
493         DE_UNREF(minX);
494         DE_UNREF(minY);
495         DE_UNREF(minZ);
496         DE_UNREF(minW);
497         DE_UNREF(maxX);
498         DE_UNREF(maxY);
499         DE_UNREF(maxZ);
500         DE_UNREF(maxW);
501 }
502
503 static void initFunctions (glw::Functions* dst, const glw::Functions& src)
504 {
505         // Functions directly passed to GL context.
506 #include "gluES3PlusWrapperFuncs.inl"
507
508         // Wrapped functions.
509         dst->bindVertexArray            = bindVertexArray;
510         dst->disable                            = disable;
511         dst->enable                                     = enable;
512         dst->getIntegerv                        = getIntegerv;
513         dst->getString                          = getString;
514         dst->getStringi                         = getStringi;
515         dst->hint                                       = hint;
516         dst->shaderSource                       = shaderSource;
517         dst->createShaderProgramv       = createShaderProgramv;
518         dst->bindFramebuffer            = bindFramebuffer;
519
520         // Extension functions
521         {
522                 using std::map;
523
524                 class ExtFuncLoader : public glw::FunctionLoader
525                 {
526                 public:
527                         ExtFuncLoader (const map<string, glw::GenericFuncType>& extFuncs)
528                                 : m_extFuncs(extFuncs)
529                         {
530                         }
531
532                         glw::GenericFuncType get (const char* name) const
533                         {
534                                 map<string, glw::GenericFuncType>::const_iterator pos = m_extFuncs.find(name);
535                                 return pos != m_extFuncs.end() ? pos->second : DE_NULL;
536                         }
537
538                 private:
539                         const map<string, glw::GenericFuncType>& m_extFuncs;
540                 };
541
542                 map<string, glw::GenericFuncType>       extFuncMap;
543                 const ExtFuncLoader                                     extFuncLoader   (extFuncMap);
544
545                 // OES_sample_shading
546                 extFuncMap["glMinSampleShadingOES"]                     = (glw::GenericFuncType)src.minSampleShading;
547
548                 // OES_texture_storage_multisample_2d_array
549                 extFuncMap["glTexStorage3DMultisampleOES"]      = (glw::GenericFuncType)src.texStorage3DMultisample;
550
551                 // KHR_blend_equation_advanced
552                 extFuncMap["glBlendBarrierKHR"]                         = (glw::GenericFuncType)blendBarrierKHR;
553
554                 // EXT_tessellation_shader
555                 extFuncMap["glPatchParameteriEXT"]                      = (glw::GenericFuncType)src.patchParameteri;
556
557                 // EXT_geometry_shader
558                 extFuncMap["glFramebufferTextureEXT"]           = (glw::GenericFuncType)src.framebufferTexture;
559
560                 // KHR_debug
561                 extFuncMap["glDebugMessageControlKHR"]          = (glw::GenericFuncType)src.debugMessageControl;
562                 extFuncMap["glDebugMessageInsertKHR"]           = (glw::GenericFuncType)src.debugMessageInsert;
563                 extFuncMap["glDebugMessageCallbackKHR"]         = (glw::GenericFuncType)src.debugMessageCallback;
564                 extFuncMap["glGetDebugMessageLogKHR"]           = (glw::GenericFuncType)src.getDebugMessageLog;
565                 extFuncMap["glGetPointervKHR"]                          = (glw::GenericFuncType)src.getPointerv;
566                 extFuncMap["glPushDebugGroupKHR"]                       = (glw::GenericFuncType)src.pushDebugGroup;
567                 extFuncMap["glPopDebugGroupKHR"]                        = (glw::GenericFuncType)src.popDebugGroup;
568                 extFuncMap["glObjectLabelKHR"]                          = (glw::GenericFuncType)src.objectLabel;
569                 extFuncMap["glGetObjectLabelKHR"]                       = (glw::GenericFuncType)src.getObjectLabel;
570                 extFuncMap["glObjectPtrLabelKHR"]                       = (glw::GenericFuncType)src.objectPtrLabel;
571                 extFuncMap["glGetObjectPtrLabelKHR"]            = (glw::GenericFuncType)src.getObjectPtrLabel;
572
573                 // GL_EXT_primitive_bounding_box (dummy no-op)
574                 extFuncMap["glPrimitiveBoundingBoxEXT"]         = (glw::GenericFuncType)dummyPrimitiveBoundingBox;
575
576                 // GL_EXT_texture_border_clamp
577                 extFuncMap["glTexParameterIivEXT"]                      = (glw::GenericFuncType)src.texParameterIiv;
578                 extFuncMap["glTexParameterIuivEXT"]                     = (glw::GenericFuncType)src.texParameterIuiv;
579                 extFuncMap["glGetTexParameterIivEXT"]           = (glw::GenericFuncType)src.getTexParameterIiv;
580                 extFuncMap["glGetTexParameterIuivEXT"]          = (glw::GenericFuncType)src.getTexParameterIuiv;
581                 extFuncMap["glSamplerParameterIivEXT"]          = (glw::GenericFuncType)src.samplerParameterIiv;
582                 extFuncMap["glSamplerParameterIuivEXT"]         = (glw::GenericFuncType)src.samplerParameterIuiv;
583                 extFuncMap["glGetSamplerParameterIivEXT"]       = (glw::GenericFuncType)src.getSamplerParameterIiv;
584                 extFuncMap["glGetSamplerParameterIuivEXT"]      = (glw::GenericFuncType)src.getSamplerParameterIuiv;
585
586                 // GL_EXT_texture_buffer
587                 extFuncMap["glTexBufferEXT"]                            = (glw::GenericFuncType)src.texBuffer;
588                 extFuncMap["glTexBufferRangeEXT"]                       = (glw::GenericFuncType)src.texBufferRange;
589
590                 // GL_EXT_draw_buffers_indexed
591                 extFuncMap["glEnableiEXT"]                                      = (glw::GenericFuncType)src.enablei;
592                 extFuncMap["glDisableiEXT"]                                     = (glw::GenericFuncType)src.disablei;
593                 extFuncMap["glBlendEquationiEXT"]                       = (glw::GenericFuncType)src.blendEquationi;
594                 extFuncMap["glBlendEquationSeparateiEXT"]       = (glw::GenericFuncType)src.blendEquationSeparatei;
595                 extFuncMap["glBlendFunciEXT"]                           = (glw::GenericFuncType)src.blendFunci;
596                 extFuncMap["glBlendFuncSeparateiEXT"]           = (glw::GenericFuncType)src.blendFuncSeparatei;
597                 extFuncMap["glColorMaskiEXT"]                           = (glw::GenericFuncType)src.colorMaski;
598                 extFuncMap["glIsEnablediEXT"]                           = (glw::GenericFuncType)src.isEnabledi;
599
600                 {
601                         int     numExts = 0;
602                         dst->getIntegerv(GL_NUM_EXTENSIONS, &numExts);
603
604                         if (numExts > 0)
605                         {
606                                 vector<const char*> extStr(numExts);
607
608                                 for (int ndx = 0; ndx < numExts; ndx++)
609                                         extStr[ndx] = (const char*)dst->getStringi(GL_EXTENSIONS, ndx);
610
611                                 glw::initExtensionsES(dst, &extFuncLoader, (int)extStr.size(), &extStr[0]);
612                         }
613                 }
614         }
615 }
616
617 } // es3plus
618
619 ES3PlusWrapperContext::ES3PlusWrapperContext (const ContextFactory& factory, const RenderConfig& config, const tcu::CommandLine& cmdLine)
620         : m_context             (DE_NULL)
621         , m_wrapperCtx  (DE_NULL)
622 {
623         // Flags that are valid for both core & es context. Currently only excludes CONTEXT_FORWARD_COMPATIBLE
624         const ContextFlags validContextFlags = CONTEXT_ROBUST | CONTEXT_DEBUG;
625
626         static const ContextType wrappableNativeTypes[] =
627         {
628                 ContextType(ApiType::core(4,4), config.type.getFlags() & validContextFlags),    // !< higher in the list, preferred
629                 ContextType(ApiType::core(4,3), config.type.getFlags() & validContextFlags),
630         };
631
632         if (config.type.getAPI() != ApiType::es(3,2))
633                 throw tcu::NotSupportedError("Unsupported context type (ES3.2 wrapper supports only ES3.2)");
634
635         // try to create any wrappable context
636
637         for (int nativeCtxNdx = 0; nativeCtxNdx < DE_LENGTH_OF_ARRAY(wrappableNativeTypes); ++nativeCtxNdx)
638         {
639                 glu::ContextType nativeContext = wrappableNativeTypes[nativeCtxNdx];
640
641                 try
642                 {
643                         glu::RenderConfig nativeConfig = config;
644                         nativeConfig.type = nativeContext;
645
646                         m_context               = factory.createContext(nativeConfig, cmdLine);
647                         m_wrapperCtx    = new es3plus::Context(*m_context);
648
649                         es3plus::setCurrentContext(m_wrapperCtx);
650                         es3plus::initFunctions(&m_functions, m_context->getFunctions());
651                         break;
652                 }
653                 catch (...)
654                 {
655                         es3plus::setCurrentContext(DE_NULL);
656
657                         delete m_wrapperCtx;
658                         delete m_context;
659
660                         m_wrapperCtx = DE_NULL;
661                         m_context = DE_NULL;
662
663                         // throw only if all tries failed (that is, this was the last potential target)
664                         if (nativeCtxNdx + 1 == DE_LENGTH_OF_ARRAY(wrappableNativeTypes))
665                                 throw;
666                         else
667                                 continue;
668                 }
669         }
670 }
671
672 ES3PlusWrapperContext::~ES3PlusWrapperContext (void)
673 {
674         delete m_wrapperCtx;
675         delete m_context;
676 }
677
678 ContextType ES3PlusWrapperContext::getType (void) const
679 {
680         return ContextType(ApiType::es(3,2), m_context->getType().getFlags());
681 }
682
683 } // glu