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 44namespace glu 45{ 46 47namespace es3plus 48{ 49 50using std::vector; 51using std::string; 52 53class Context 54{ 55public: 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 78Context::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 142Context::~Context (void) 143{ 144 if (defaultVAO) 145 gl.deleteVertexArrays(1, &defaultVAO); 146} 147 148void Context::addExtension (const char* name) 149{ 150 if (!extensions.empty()) 151 extensions += " "; 152 extensions += name; 153 154 extensionList.push_back(name); 155} 156 157static de::ThreadLocal tls_context; 158 159void setCurrentContext (Context* context) 160{ 161 tls_context.set(context); 162} 163 164inline Context* getCurrentContext (void) 165{ 166 return (Context*)tls_context.get(); 167} 168 169static 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 182static 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 202static 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 222static 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 238static 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 251static 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 262static 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 274static 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 410static 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 426static 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 447static 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 461static 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 472static 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 490static 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 503static 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 619ES3PlusWrapperContext::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 672ES3PlusWrapperContext::~ES3PlusWrapperContext (void) 673{ 674 delete m_wrapperCtx; 675 delete m_context; 676} 677 678ContextType ES3PlusWrapperContext::getType (void) const 679{ 680 return ContextType(ApiType::es(3,2), m_context->getType().getFlags()); 681} 682 683} // glu 684