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