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
Context(const glu::RenderContext & ctx)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
~Context(void)142 Context::~Context (void)
143 {
144 if (defaultVAO)
145 gl.deleteVertexArrays(1, &defaultVAO);
146 }
147
addExtension(const char * name)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
setCurrentContext(Context * context)159 void setCurrentContext (Context* context)
160 {
161 tls_context.set(context);
162 }
163
getCurrentContext(void)164 inline Context* getCurrentContext (void)
165 {
166 return (Context*)tls_context.get();
167 }
168
getIntegerv(deUint32 pname,deInt32 * params)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
getString(deUint32 name)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
getStringi(deUint32 name,deUint32 index)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
enable(deUint32 cap)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
disable(deUint32 cap)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
bindVertexArray(deUint32 array)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
hint(deUint32 target,deUint32 mode)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
translateShaderSource(deUint32 shaderType,std::ostream & dst,const std::string & src,const std::vector<std::string> & filteredExtensions,GLSLVersion version)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
translateShaderSources(deUint32 shaderType,deInt32 count,const char * const * strings,const int * length,const std::vector<std::string> & filteredExtensions,GLSLVersion version)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
shaderSource(deUint32 shader,deInt32 count,const char * const * strings,const int * length)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
bindFramebuffer(deUint32 target,deUint32 framebuffer)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
blendBarrierKHR(void)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
createShaderProgramv(deUint32 type,deInt32 count,const char * const * strings)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
dummyPrimitiveBoundingBox(float minX,float minY,float minZ,float minW,float maxX,float maxY,float maxZ,float maxW)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
initFunctions(glw::Functions * dst,const glw::Functions & src)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
ES3PlusWrapperContext(const ContextFactory & factory,const RenderConfig & config,const tcu::CommandLine & cmdLine)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
~ES3PlusWrapperContext(void)672 ES3PlusWrapperContext::~ES3PlusWrapperContext (void)
673 {
674 delete m_wrapperCtx;
675 delete m_context;
676 }
677
getType(void) const678 ContextType ES3PlusWrapperContext::getType (void) const
679 {
680 return ContextType(ApiType::es(3,2), m_context->getType().getFlags());
681 }
682
683 } // glu
684