683 lines
21 KiB
C++
683 lines
21 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES Utilities
|
|
* ------------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief OpenGL ES 3plus wrapper context.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "gluES3PlusWrapperContext.hpp"
|
|
#include "gluRenderContext.hpp"
|
|
#include "gluRenderConfig.hpp"
|
|
#include "glwInitFunctions.hpp"
|
|
#include "glwFunctionLoader.hpp"
|
|
#include "gluContextFactory.hpp"
|
|
#include "gluContextInfo.hpp"
|
|
#include "gluShaderUtil.hpp"
|
|
#include "deThreadLocal.hpp"
|
|
#include "deSTLUtil.hpp"
|
|
#include "deUniquePtr.hpp"
|
|
#include "glwEnums.hpp"
|
|
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
#include <map>
|
|
|
|
namespace glu
|
|
{
|
|
|
|
namespace es3plus
|
|
{
|
|
|
|
using std::vector;
|
|
using std::string;
|
|
|
|
class Context
|
|
{
|
|
public:
|
|
Context (const glu::RenderContext& ctx);
|
|
~Context (void);
|
|
|
|
void addExtension (const char* name);
|
|
|
|
const glw::Functions& gl; //!< GL 4.3 core context functions.
|
|
|
|
// Wrapper state.
|
|
string vendor;
|
|
string version;
|
|
string renderer;
|
|
string shadingLanguageVersion;
|
|
string extensions;
|
|
vector<string> extensionList;
|
|
bool primitiveRestartEnabled;
|
|
|
|
deUint32 defaultVAO;
|
|
bool defaultVAOBound;
|
|
|
|
const glu::GLSLVersion nativeGLSLVersion;
|
|
};
|
|
|
|
Context::Context (const glu::RenderContext& ctx)
|
|
: gl (ctx.getFunctions())
|
|
, vendor ("drawElements")
|
|
, version ("OpenGL ES 3.2")
|
|
, renderer ((const char*)gl.getString(GL_RENDERER))
|
|
, shadingLanguageVersion ("OpenGL ES GLSL ES 3.2")
|
|
, primitiveRestartEnabled (false)
|
|
, defaultVAO (0)
|
|
, defaultVAOBound (false)
|
|
, nativeGLSLVersion (glu::getContextTypeGLSLVersion(ctx.getType()))
|
|
{
|
|
const de::UniquePtr<glu::ContextInfo> ctxInfo(glu::ContextInfo::create(ctx));
|
|
|
|
gl.genVertexArrays(1, &defaultVAO);
|
|
if (gl.getError() != GL_NO_ERROR || defaultVAO == 0)
|
|
throw tcu::InternalError("Failed to allocate VAO for emulation");
|
|
|
|
gl.bindVertexArray(defaultVAO);
|
|
if (gl.getError() != GL_NO_ERROR)
|
|
throw tcu::InternalError("Failed to bind default VAO");
|
|
defaultVAOBound = true;
|
|
|
|
gl.enable(GL_PROGRAM_POINT_SIZE);
|
|
gl.getError(); // supress potential errors, feature is not critical
|
|
|
|
gl.enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
|
gl.getError(); // suppress
|
|
|
|
// Extensions
|
|
addExtension("GL_OES_texture_stencil8");
|
|
addExtension("GL_OES_sample_shading");
|
|
addExtension("GL_OES_sample_variables");
|
|
addExtension("GL_OES_shader_multisample_interpolation");
|
|
addExtension("GL_OES_shader_image_atomic");
|
|
addExtension("GL_OES_texture_storage_multisample_2d_array");
|
|
|
|
// Enable only if base ctx supports these or compatible GL_NV_blend_equation_advanced ext
|
|
if (ctxInfo->isExtensionSupported("GL_NV_blend_equation_advanced") ||
|
|
ctxInfo->isExtensionSupported("GL_KHR_blend_equation_advanced"))
|
|
{
|
|
addExtension("GL_KHR_blend_equation_advanced");
|
|
}
|
|
if (ctxInfo->isExtensionSupported("GL_NV_blend_equation_advanced_coherent") ||
|
|
ctxInfo->isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"))
|
|
{
|
|
addExtension("GL_KHR_blend_equation_advanced_coherent");
|
|
}
|
|
|
|
addExtension("GL_EXT_shader_io_blocks");
|
|
addExtension("GL_EXT_geometry_shader");
|
|
addExtension("GL_EXT_geometry_point_size");
|
|
addExtension("GL_EXT_tessellation_shader");
|
|
addExtension("GL_EXT_tessellation_point_size");
|
|
addExtension("GL_EXT_gpu_shader5");
|
|
addExtension("GL_KHR_debug");
|
|
addExtension("GL_EXT_texture_cube_map_array");
|
|
addExtension("GL_EXT_shader_implicit_conversions");
|
|
addExtension("GL_EXT_primitive_bounding_box");
|
|
addExtension("GL_EXT_texture_sRGB_decode");
|
|
addExtension("GL_EXT_texture_border_clamp");
|
|
addExtension("GL_EXT_texture_buffer");
|
|
addExtension("GL_EXT_draw_buffers_indexed");
|
|
}
|
|
|
|
Context::~Context (void)
|
|
{
|
|
if (defaultVAO)
|
|
gl.deleteVertexArrays(1, &defaultVAO);
|
|
}
|
|
|
|
void Context::addExtension (const char* name)
|
|
{
|
|
if (!extensions.empty())
|
|
extensions += " ";
|
|
extensions += name;
|
|
|
|
extensionList.push_back(name);
|
|
}
|
|
|
|
static de::ThreadLocal tls_context;
|
|
|
|
void setCurrentContext (Context* context)
|
|
{
|
|
tls_context.set(context);
|
|
}
|
|
|
|
inline Context* getCurrentContext (void)
|
|
{
|
|
return (Context*)tls_context.get();
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY getIntegerv (deUint32 pname, deInt32* params)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (pname == GL_NUM_EXTENSIONS && params)
|
|
*params = (deInt32)context->extensionList.size();
|
|
else
|
|
context->gl.getIntegerv(pname, params);
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL const glw::GLubyte* GLW_APIENTRY getString (deUint32 name)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
switch (name)
|
|
{
|
|
case GL_VENDOR: return (const glw::GLubyte*)context->vendor.c_str();
|
|
case GL_VERSION: return (const glw::GLubyte*)context->version.c_str();
|
|
case GL_RENDERER: return (const glw::GLubyte*)context->renderer.c_str();
|
|
case GL_SHADING_LANGUAGE_VERSION: return (const glw::GLubyte*)context->shadingLanguageVersion.c_str();
|
|
case GL_EXTENSIONS: return (const glw::GLubyte*)context->extensions.c_str();
|
|
default: return context->gl.getString(name);
|
|
}
|
|
}
|
|
else
|
|
return DE_NULL;
|
|
}
|
|
|
|
static GLW_APICALL const glw::GLubyte* GLW_APIENTRY getStringi (deUint32 name, deUint32 index)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (name == GL_EXTENSIONS)
|
|
{
|
|
if ((size_t)index < context->extensionList.size())
|
|
return (const glw::GLubyte*)context->extensionList[index].c_str();
|
|
else
|
|
return context->gl.getStringi(name, ~0u);
|
|
}
|
|
else
|
|
return context->gl.getStringi(name, index);
|
|
}
|
|
else
|
|
return DE_NULL;
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY enable (deUint32 cap)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (cap == GL_PRIMITIVE_RESTART_FIXED_INDEX)
|
|
{
|
|
context->primitiveRestartEnabled = true;
|
|
// \todo [2013-09-30 pyry] Call to glPrimitiveRestartIndex() is required prior to all draw calls!
|
|
}
|
|
else
|
|
context->gl.enable(cap);
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY disable (deUint32 cap)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (cap == GL_PRIMITIVE_RESTART_FIXED_INDEX)
|
|
context->primitiveRestartEnabled = false;
|
|
else
|
|
context->gl.disable(cap);
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY bindVertexArray (deUint32 array)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
context->gl.bindVertexArray(array == 0 ? context->defaultVAO : array);
|
|
context->defaultVAOBound = (array == 0);
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY hint (deUint32 target, deUint32 mode)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (target != GL_GENERATE_MIPMAP_HINT)
|
|
context->gl.hint(target, mode);
|
|
// \todo [2013-09-30 pyry] Verify mode.
|
|
}
|
|
}
|
|
|
|
static void translateShaderSource (deUint32 shaderType, std::ostream& dst, const std::string& src, const std::vector<std::string>& filteredExtensions, GLSLVersion version)
|
|
{
|
|
bool foundVersion = false;
|
|
std::istringstream istr (src);
|
|
std::string line;
|
|
int srcLineNdx = 1;
|
|
bool preprocessorSection = true;
|
|
|
|
while (std::getline(istr, line, '\n'))
|
|
{
|
|
if (preprocessorSection && !line.empty() && line[0] != '#')
|
|
{
|
|
preprocessorSection = false;
|
|
|
|
// ARB_separate_shader_objects requires gl_PerVertex to be explicitly declared
|
|
if (shaderType == GL_VERTEX_SHADER)
|
|
{
|
|
dst << "out gl_PerVertex {\n"
|
|
<< " vec4 gl_Position;\n"
|
|
<< " float gl_PointSize;\n"
|
|
<< " float gl_ClipDistance[];\n"
|
|
<< "};\n"
|
|
<< "#line " << (srcLineNdx + 1) << "\n";
|
|
}
|
|
else if (shaderType == GL_TESS_CONTROL_SHADER)
|
|
{
|
|
dst << "#extension GL_ARB_tessellation_shader : enable\n"
|
|
<< "in gl_PerVertex {\n"
|
|
<< " highp vec4 gl_Position;\n"
|
|
<< " highp float gl_PointSize;\n"
|
|
<< "} gl_in[gl_MaxPatchVertices];\n"
|
|
<< "out gl_PerVertex {\n"
|
|
<< " highp vec4 gl_Position;\n"
|
|
<< " highp float gl_PointSize;\n"
|
|
<< "} gl_out[];\n"
|
|
<< "#line " << (srcLineNdx + 1) << "\n";
|
|
}
|
|
else if (shaderType == GL_TESS_EVALUATION_SHADER)
|
|
{
|
|
dst << "#extension GL_ARB_tessellation_shader : enable\n"
|
|
<< "in gl_PerVertex {\n"
|
|
<< " highp vec4 gl_Position;\n"
|
|
<< " highp float gl_PointSize;\n"
|
|
<< "} gl_in[gl_MaxPatchVertices];\n"
|
|
<< "out gl_PerVertex {\n"
|
|
<< " highp vec4 gl_Position;\n"
|
|
<< " highp float gl_PointSize;\n"
|
|
<< "};\n"
|
|
<< "#line " << (srcLineNdx + 1) << "\n";
|
|
}
|
|
else if (shaderType == GL_GEOMETRY_SHADER)
|
|
{
|
|
dst << "in gl_PerVertex {\n"
|
|
<< " highp vec4 gl_Position;\n"
|
|
<< " highp float gl_PointSize;\n"
|
|
<< "} gl_in[];\n"
|
|
<< "out gl_PerVertex {\n"
|
|
<< " highp vec4 gl_Position;\n"
|
|
<< " highp float gl_PointSize;\n"
|
|
<< "};\n"
|
|
<< "#line " << (srcLineNdx + 1) << "\n";
|
|
}
|
|
|
|
// GL_EXT_primitive_bounding_box tessellation no-op fallback
|
|
if (shaderType == GL_TESS_CONTROL_SHADER)
|
|
{
|
|
dst << "#define gl_BoundingBoxEXT _dummy_unused_output_for_primitive_bbox\n"
|
|
<< "patch out vec4 _dummy_unused_output_for_primitive_bbox[2];\n"
|
|
<< "#line " << (srcLineNdx + 1) << "\n";
|
|
}
|
|
}
|
|
|
|
if (line == "#version 310 es" || line == "#version 320 es")
|
|
{
|
|
foundVersion = true;
|
|
dst << glu::getGLSLVersionDeclaration(version) << "\n";
|
|
}
|
|
else if (line == "#version 300 es")
|
|
{
|
|
foundVersion = true;
|
|
dst << "#version 330\n";
|
|
}
|
|
else if (line.substr(0, 10) == "precision ")
|
|
{
|
|
const size_t precPos = 10;
|
|
const size_t precEndPos = line.find(' ', precPos);
|
|
const size_t endPos = line.find(';');
|
|
|
|
if (precEndPos != std::string::npos && endPos != std::string::npos && endPos > precEndPos+1)
|
|
{
|
|
const size_t typePos = precEndPos+1;
|
|
const std::string precision = line.substr(precPos, precEndPos-precPos);
|
|
const std::string type = line.substr(typePos, endPos-typePos);
|
|
const bool precOk = precision == "lowp" || precision == "mediump" || precision == "highp";
|
|
|
|
if (precOk &&
|
|
(type == "image2D" || type == "uimage2D" || type == "iimage2D" ||
|
|
type == "imageCube" || type == "uimageCube" || type == "iimageCube" ||
|
|
type == "image3D" || type == "iimage3D" || type == "uimage3D" ||
|
|
type == "image2DArray" || type == "iimage2DArray" || type == "uimage2DArray" ||
|
|
type == "imageCubeArray" || type == "iimageCubeArray" || type == "uimageCubeArray"))
|
|
dst << "// "; // Filter out statement
|
|
}
|
|
|
|
dst << line << "\n";
|
|
}
|
|
else if (line.substr(0, 11) == "#extension ")
|
|
{
|
|
const size_t extNamePos = 11;
|
|
const size_t extNameEndPos = line.find_first_of(" :", extNamePos);
|
|
const size_t behaviorPos = line.find_first_not_of(" :", extNameEndPos);
|
|
|
|
if (extNameEndPos != std::string::npos && behaviorPos != std::string::npos)
|
|
{
|
|
const std::string extName = line.substr(extNamePos, extNameEndPos-extNamePos);
|
|
const std::string behavior = line.substr(behaviorPos);
|
|
const bool filteredExtension = de::contains(filteredExtensions.begin(), filteredExtensions.end(), extName);
|
|
const bool validBehavior = behavior == "require" || behavior == "enable" || behavior == "warn" || behavior == "disable";
|
|
|
|
if (filteredExtension && validBehavior)
|
|
dst << "// "; // Filter out extension
|
|
}
|
|
dst << line << "\n";
|
|
}
|
|
else if (line.substr(0, 21) == "layout(blend_support_")
|
|
dst << "// " << line << "\n";
|
|
else
|
|
dst << line << "\n";
|
|
|
|
srcLineNdx += 1;
|
|
}
|
|
|
|
DE_ASSERT(foundVersion);
|
|
DE_UNREF(foundVersion);
|
|
}
|
|
|
|
static std::string translateShaderSources (deUint32 shaderType, deInt32 count, const char* const* strings, const int* length, const std::vector<std::string>& filteredExtensions, GLSLVersion version)
|
|
{
|
|
std::ostringstream srcIn;
|
|
std::ostringstream srcOut;
|
|
|
|
for (int ndx = 0; ndx < count; ndx++)
|
|
{
|
|
const int len = length && length[ndx] >= 0 ? length[ndx] : (int)strlen(strings[ndx]);
|
|
srcIn << std::string(strings[ndx], strings[ndx] + len);
|
|
}
|
|
|
|
translateShaderSource(shaderType, srcOut, srcIn.str(), filteredExtensions, version);
|
|
|
|
return srcOut.str();
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY shaderSource (deUint32 shader, deInt32 count, const char* const* strings, const int* length)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (count > 0 && strings)
|
|
{
|
|
deInt32 shaderType = GL_NONE;
|
|
context->gl.getShaderiv(shader, GL_SHADER_TYPE, &shaderType);
|
|
{
|
|
const std::string translatedSrc = translateShaderSources(shaderType, count, strings, length, context->extensionList, context->nativeGLSLVersion);
|
|
const char* srcPtr = translatedSrc.c_str();
|
|
context->gl.shaderSource(shader, 1, &srcPtr, DE_NULL);
|
|
}
|
|
}
|
|
else
|
|
context->gl.shaderSource(shader, count, strings, length);
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY bindFramebuffer (deUint32 target, deUint32 framebuffer)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
context->gl.bindFramebuffer(target, framebuffer);
|
|
|
|
// Emulate ES behavior where sRGB conversion is only controlled by color buffer format.
|
|
if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER)
|
|
((framebuffer != 0) ? context->gl.enable : context->gl.disable)(GL_FRAMEBUFFER_SRGB);
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY blendBarrierKHR (void)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
// \todo [2014-03-18 pyry] Use BlendBarrierNV() if supported
|
|
context->gl.finish();
|
|
}
|
|
}
|
|
|
|
static GLW_APICALL deUint32 GLW_APIENTRY createShaderProgramv (deUint32 type, deInt32 count, const char* const* strings)
|
|
{
|
|
Context* context = getCurrentContext();
|
|
|
|
if (context)
|
|
{
|
|
if (count > 0 && strings)
|
|
{
|
|
const std::string translatedSrc = translateShaderSources(type, count, strings, DE_NULL, context->extensionList, context->nativeGLSLVersion);
|
|
const char* srcPtr = translatedSrc.c_str();
|
|
return context->gl.createShaderProgramv(type, 1, &srcPtr);
|
|
}
|
|
else
|
|
return context->gl.createShaderProgramv(type, count, strings);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static GLW_APICALL void GLW_APIENTRY dummyPrimitiveBoundingBox (float minX, float minY, float minZ, float minW, float maxX, float maxY, float maxZ, float maxW)
|
|
{
|
|
// dummy no-op. No-op is a valid implementation. States queries are not emulated.
|
|
DE_UNREF(minX);
|
|
DE_UNREF(minY);
|
|
DE_UNREF(minZ);
|
|
DE_UNREF(minW);
|
|
DE_UNREF(maxX);
|
|
DE_UNREF(maxY);
|
|
DE_UNREF(maxZ);
|
|
DE_UNREF(maxW);
|
|
}
|
|
|
|
static void initFunctions (glw::Functions* dst, const glw::Functions& src)
|
|
{
|
|
// Functions directly passed to GL context.
|
|
#include "gluES3PlusWrapperFuncs.inl"
|
|
|
|
// Wrapped functions.
|
|
dst->bindVertexArray = bindVertexArray;
|
|
dst->disable = disable;
|
|
dst->enable = enable;
|
|
dst->getIntegerv = getIntegerv;
|
|
dst->getString = getString;
|
|
dst->getStringi = getStringi;
|
|
dst->hint = hint;
|
|
dst->shaderSource = shaderSource;
|
|
dst->createShaderProgramv = createShaderProgramv;
|
|
dst->bindFramebuffer = bindFramebuffer;
|
|
|
|
// Extension functions
|
|
{
|
|
using std::map;
|
|
|
|
class ExtFuncLoader : public glw::FunctionLoader
|
|
{
|
|
public:
|
|
ExtFuncLoader (const map<string, glw::GenericFuncType>& extFuncs)
|
|
: m_extFuncs(extFuncs)
|
|
{
|
|
}
|
|
|
|
glw::GenericFuncType get (const char* name) const
|
|
{
|
|
map<string, glw::GenericFuncType>::const_iterator pos = m_extFuncs.find(name);
|
|
return pos != m_extFuncs.end() ? pos->second : DE_NULL;
|
|
}
|
|
|
|
private:
|
|
const map<string, glw::GenericFuncType>& m_extFuncs;
|
|
};
|
|
|
|
map<string, glw::GenericFuncType> extFuncMap;
|
|
const ExtFuncLoader extFuncLoader (extFuncMap);
|
|
|
|
// OES_sample_shading
|
|
extFuncMap["glMinSampleShadingOES"] = (glw::GenericFuncType)src.minSampleShading;
|
|
|
|
// OES_texture_storage_multisample_2d_array
|
|
extFuncMap["glTexStorage3DMultisampleOES"] = (glw::GenericFuncType)src.texStorage3DMultisample;
|
|
|
|
// KHR_blend_equation_advanced
|
|
extFuncMap["glBlendBarrierKHR"] = (glw::GenericFuncType)blendBarrierKHR;
|
|
|
|
// EXT_tessellation_shader
|
|
extFuncMap["glPatchParameteriEXT"] = (glw::GenericFuncType)src.patchParameteri;
|
|
|
|
// EXT_geometry_shader
|
|
extFuncMap["glFramebufferTextureEXT"] = (glw::GenericFuncType)src.framebufferTexture;
|
|
|
|
// KHR_debug
|
|
extFuncMap["glDebugMessageControlKHR"] = (glw::GenericFuncType)src.debugMessageControl;
|
|
extFuncMap["glDebugMessageInsertKHR"] = (glw::GenericFuncType)src.debugMessageInsert;
|
|
extFuncMap["glDebugMessageCallbackKHR"] = (glw::GenericFuncType)src.debugMessageCallback;
|
|
extFuncMap["glGetDebugMessageLogKHR"] = (glw::GenericFuncType)src.getDebugMessageLog;
|
|
extFuncMap["glGetPointervKHR"] = (glw::GenericFuncType)src.getPointerv;
|
|
extFuncMap["glPushDebugGroupKHR"] = (glw::GenericFuncType)src.pushDebugGroup;
|
|
extFuncMap["glPopDebugGroupKHR"] = (glw::GenericFuncType)src.popDebugGroup;
|
|
extFuncMap["glObjectLabelKHR"] = (glw::GenericFuncType)src.objectLabel;
|
|
extFuncMap["glGetObjectLabelKHR"] = (glw::GenericFuncType)src.getObjectLabel;
|
|
extFuncMap["glObjectPtrLabelKHR"] = (glw::GenericFuncType)src.objectPtrLabel;
|
|
extFuncMap["glGetObjectPtrLabelKHR"] = (glw::GenericFuncType)src.getObjectPtrLabel;
|
|
|
|
// GL_EXT_primitive_bounding_box (dummy no-op)
|
|
extFuncMap["glPrimitiveBoundingBoxEXT"] = (glw::GenericFuncType)dummyPrimitiveBoundingBox;
|
|
|
|
// GL_EXT_texture_border_clamp
|
|
extFuncMap["glTexParameterIivEXT"] = (glw::GenericFuncType)src.texParameterIiv;
|
|
extFuncMap["glTexParameterIuivEXT"] = (glw::GenericFuncType)src.texParameterIuiv;
|
|
extFuncMap["glGetTexParameterIivEXT"] = (glw::GenericFuncType)src.getTexParameterIiv;
|
|
extFuncMap["glGetTexParameterIuivEXT"] = (glw::GenericFuncType)src.getTexParameterIuiv;
|
|
extFuncMap["glSamplerParameterIivEXT"] = (glw::GenericFuncType)src.samplerParameterIiv;
|
|
extFuncMap["glSamplerParameterIuivEXT"] = (glw::GenericFuncType)src.samplerParameterIuiv;
|
|
extFuncMap["glGetSamplerParameterIivEXT"] = (glw::GenericFuncType)src.getSamplerParameterIiv;
|
|
extFuncMap["glGetSamplerParameterIuivEXT"] = (glw::GenericFuncType)src.getSamplerParameterIuiv;
|
|
|
|
// GL_EXT_texture_buffer
|
|
extFuncMap["glTexBufferEXT"] = (glw::GenericFuncType)src.texBuffer;
|
|
extFuncMap["glTexBufferRangeEXT"] = (glw::GenericFuncType)src.texBufferRange;
|
|
|
|
// GL_EXT_draw_buffers_indexed
|
|
extFuncMap["glEnableiEXT"] = (glw::GenericFuncType)src.enablei;
|
|
extFuncMap["glDisableiEXT"] = (glw::GenericFuncType)src.disablei;
|
|
extFuncMap["glBlendEquationiEXT"] = (glw::GenericFuncType)src.blendEquationi;
|
|
extFuncMap["glBlendEquationSeparateiEXT"] = (glw::GenericFuncType)src.blendEquationSeparatei;
|
|
extFuncMap["glBlendFunciEXT"] = (glw::GenericFuncType)src.blendFunci;
|
|
extFuncMap["glBlendFuncSeparateiEXT"] = (glw::GenericFuncType)src.blendFuncSeparatei;
|
|
extFuncMap["glColorMaskiEXT"] = (glw::GenericFuncType)src.colorMaski;
|
|
extFuncMap["glIsEnablediEXT"] = (glw::GenericFuncType)src.isEnabledi;
|
|
|
|
{
|
|
int numExts = 0;
|
|
dst->getIntegerv(GL_NUM_EXTENSIONS, &numExts);
|
|
|
|
if (numExts > 0)
|
|
{
|
|
vector<const char*> extStr(numExts);
|
|
|
|
for (int ndx = 0; ndx < numExts; ndx++)
|
|
extStr[ndx] = (const char*)dst->getStringi(GL_EXTENSIONS, ndx);
|
|
|
|
glw::initExtensionsES(dst, &extFuncLoader, (int)extStr.size(), &extStr[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // es3plus
|
|
|
|
ES3PlusWrapperContext::ES3PlusWrapperContext (const ContextFactory& factory, const RenderConfig& config, const tcu::CommandLine& cmdLine)
|
|
: m_context (DE_NULL)
|
|
, m_wrapperCtx (DE_NULL)
|
|
{
|
|
// Flags that are valid for both core & es context. Currently only excludes CONTEXT_FORWARD_COMPATIBLE
|
|
const ContextFlags validContextFlags = CONTEXT_ROBUST | CONTEXT_DEBUG;
|
|
|
|
static const ContextType wrappableNativeTypes[] =
|
|
{
|
|
ContextType(ApiType::core(4,4), config.type.getFlags() & validContextFlags), // !< higher in the list, preferred
|
|
ContextType(ApiType::core(4,3), config.type.getFlags() & validContextFlags),
|
|
};
|
|
|
|
if (config.type.getAPI() != ApiType::es(3,2))
|
|
throw tcu::NotSupportedError("Unsupported context type (ES3.2 wrapper supports only ES3.2)");
|
|
|
|
// try to create any wrappable context
|
|
|
|
for (int nativeCtxNdx = 0; nativeCtxNdx < DE_LENGTH_OF_ARRAY(wrappableNativeTypes); ++nativeCtxNdx)
|
|
{
|
|
glu::ContextType nativeContext = wrappableNativeTypes[nativeCtxNdx];
|
|
|
|
try
|
|
{
|
|
glu::RenderConfig nativeConfig = config;
|
|
nativeConfig.type = nativeContext;
|
|
|
|
m_context = factory.createContext(nativeConfig, cmdLine);
|
|
m_wrapperCtx = new es3plus::Context(*m_context);
|
|
|
|
es3plus::setCurrentContext(m_wrapperCtx);
|
|
es3plus::initFunctions(&m_functions, m_context->getFunctions());
|
|
break;
|
|
}
|
|
catch (...)
|
|
{
|
|
es3plus::setCurrentContext(DE_NULL);
|
|
|
|
delete m_wrapperCtx;
|
|
delete m_context;
|
|
|
|
m_wrapperCtx = DE_NULL;
|
|
m_context = DE_NULL;
|
|
|
|
// throw only if all tries failed (that is, this was the last potential target)
|
|
if (nativeCtxNdx + 1 == DE_LENGTH_OF_ARRAY(wrappableNativeTypes))
|
|
throw;
|
|
else
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
ES3PlusWrapperContext::~ES3PlusWrapperContext (void)
|
|
{
|
|
delete m_wrapperCtx;
|
|
delete m_context;
|
|
}
|
|
|
|
ContextType ES3PlusWrapperContext::getType (void) const
|
|
{
|
|
return ContextType(ApiType::es(3,2), m_context->getType().getFlags());
|
|
}
|
|
|
|
} // glu
|