Commit 66fb8206 by Martin Radev Committed by Commit Bot

Add ES3.1 API constants

The newly added capability constants are handled in the corresponding glGet functions. Also, getBooleani_v has been added. BUG=angleproject:1442 TEST=angle_deqp_gtest_gles31_tests --gtest_filter=*functional_state_query_integer_max_* TEST=angle_deqp_gtest_gles31_tests --gtest_filter=*state_query_indexed_max_compute_work_group_size* TEST=angle_unittests TEST=angle_end2end_tests Change-Id: I846e006307563ae81d8b6c62cf261417e15186c7 Reviewed-on: https://chromium-review.googlesource.com/362270Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent f54b14fc
......@@ -598,33 +598,72 @@ Caps::Caps()
maxLODBias(0),
maxCubeMapTextureSize(0),
maxRenderbufferSize(0),
minAliasedPointSize(0),
maxAliasedPointSize(0),
minAliasedLineWidth(0),
maxAliasedLineWidth(0),
// Table 20.40
maxDrawBuffers(0),
maxFramebufferWidth(0),
maxFramebufferHeight(0),
maxFramebufferSamples(0),
maxColorAttachments(0),
maxViewportWidth(0),
maxViewportHeight(0),
minAliasedPointSize(0),
maxAliasedPointSize(0),
minAliasedLineWidth(0),
// Table 6.29
maxSampleMaskWords(0),
maxColorTextureSamples(0),
maxDepthTextureSamples(0),
maxIntegerSamples(0),
maxServerWaitTimeout(0),
// Table 20.41
maxVertexAttribRelativeOffset(0),
maxVertexAttribBindings(0),
maxVertexAttribStride(0),
maxElementsIndices(0),
maxElementsVertices(0),
maxServerWaitTimeout(0),
// Table 6.31
// Table 20.43
maxVertexAttributes(0),
maxVertexUniformComponents(0),
maxVertexUniformVectors(0),
maxVertexUniformBlocks(0),
maxVertexOutputComponents(0),
maxVertexTextureImageUnits(0),
// Table 6.32
maxVertexAtomicCounterBuffers(0),
maxVertexAtomicCounters(0),
maxVertexImageUniforms(0),
maxVertexShaderStorageBlocks(0),
// Table 20.44
maxFragmentUniformComponents(0),
maxFragmentUniformVectors(0),
maxFragmentUniformBlocks(0),
maxFragmentInputComponents(0),
maxTextureImageUnits(0),
maxFragmentAtomicCounterBuffers(0),
maxFragmentAtomicCounters(0),
maxFragmentImageUniforms(0),
maxFragmentShaderStorageBlocks(0),
minProgramTextureGatherOffset(0),
maxProgramTextureGatherOffset(0),
minProgramTexelOffset(0),
maxProgramTexelOffset(0),
// Table 6.33
// Table 20.45
maxComputeWorkGroupInvocations(0),
maxComputeUniformBlocks(0),
maxComputeTextureImageUnits(0),
maxComputeSharedMemorySize(0),
maxComputeUniformComponents(0),
maxComputeAtomicCounterBuffers(0),
maxComputeAtomicCounters(0),
maxComputeImageUniforms(0),
maxCombinedComputeUniformComponents(0),
maxComputeShaderStorageBlocks(0),
// Table 20.46
maxUniformBufferBindings(0),
maxUniformBlockSize(0),
uniformBufferOffsetAlignment(0),
......@@ -634,13 +673,35 @@ Caps::Caps()
maxVaryingComponents(0),
maxVaryingVectors(0),
maxCombinedTextureImageUnits(0),
// Table 6.34
maxCombinedShaderOutputResources(0),
// Table 20.47
maxUniformLocations(0),
maxAtomicCounterBufferBindings(0),
maxAtomicCounterBufferSize(0),
maxCombinedAtomicCounterBuffers(0),
maxCombinedAtomicCounters(0),
maxImageUnits(0),
maxCombinedImageUniforms(0),
maxShaderStorageBufferBindings(0),
maxShaderStorageBlockSize(0),
maxCombinedShaderStorageBlocks(0),
shaderStorageBufferOffsetAlignment(0),
// Table 20.48
maxTransformFeedbackInterleavedComponents(0),
maxTransformFeedbackSeparateAttributes(0),
maxTransformFeedbackSeparateComponents(0),
// Table 6.35
// Table 20.49
maxSamples(0)
{
for (size_t i = 0; i < 3; ++i)
{
maxComputeWorkGroupCount[i] = 0;
maxComputeWorkGroupSize[i] = 0;
}
}
}
......
......@@ -14,6 +14,7 @@
#include <set>
#include <string>
#include <vector>
#include <array>
namespace gl
{
......@@ -353,7 +354,7 @@ struct Caps
{
Caps();
// Table 6.28, implementation dependent values
// ES 3.1 (April 29, 2015) 20.39: implementation dependent values
GLuint64 maxElementIndex;
GLuint max3DTextureSize;
GLuint max2DTextureSize;
......@@ -361,16 +362,29 @@ struct Caps
GLfloat maxLODBias;
GLuint maxCubeMapTextureSize;
GLuint maxRenderbufferSize;
GLuint maxDrawBuffers;
GLuint maxColorAttachments;
GLuint maxViewportWidth;
GLuint maxViewportHeight;
GLfloat minAliasedPointSize;
GLfloat maxAliasedPointSize;
GLfloat minAliasedLineWidth;
GLfloat maxAliasedLineWidth;
// Table 6.29, implementation dependent values (cont.)
// ES 3.1 (April 29, 2015) 20.40: implementation dependent values (cont.)
GLuint maxDrawBuffers;
GLuint maxFramebufferWidth;
GLuint maxFramebufferHeight;
GLuint maxFramebufferSamples;
GLuint maxColorAttachments;
GLuint maxViewportWidth;
GLuint maxViewportHeight;
GLuint maxSampleMaskWords;
GLuint maxColorTextureSamples;
GLuint maxDepthTextureSamples;
GLuint maxIntegerSamples;
GLuint64 maxServerWaitTimeout;
// ES 3.1 (April 29, 2015) Table 20.41: Implementation dependent values (cont.)
GLint maxVertexAttribRelativeOffset;
GLint maxVertexAttribBindings;
GLint maxVertexAttribStride;
GLuint maxElementsIndices;
GLuint maxElementsVertices;
std::vector<GLenum> compressedTextureFormats;
......@@ -388,26 +402,49 @@ struct Caps
TypePrecision fragmentHighpInt;
TypePrecision fragmentMediumpInt;
TypePrecision fragmentLowpInt;
GLuint64 maxServerWaitTimeout;
// Table 6.31, implementation dependent vertex shader limits
// ES 3.1 (April 29, 2015) Table 20.43: Implementation dependent Vertex shader limits
GLuint maxVertexAttributes;
GLuint maxVertexUniformComponents;
GLuint maxVertexUniformVectors;
GLuint maxVertexUniformBlocks;
GLuint maxVertexOutputComponents;
GLuint maxVertexTextureImageUnits;
GLuint maxVertexAtomicCounterBuffers;
GLuint maxVertexAtomicCounters;
GLuint maxVertexImageUniforms;
GLuint maxVertexShaderStorageBlocks;
// Table 6.32, implementation dependent fragment shader limits
// ES 3.1 (April 29, 2015) Table 20.44: Implementation dependent Fragment shader limits
GLuint maxFragmentUniformComponents;
GLuint maxFragmentUniformVectors;
GLuint maxFragmentUniformBlocks;
GLuint maxFragmentInputComponents;
GLuint maxTextureImageUnits;
GLuint maxFragmentAtomicCounterBuffers;
GLuint maxFragmentAtomicCounters;
GLuint maxFragmentImageUniforms;
GLuint maxFragmentShaderStorageBlocks;
GLint minProgramTextureGatherOffset;
GLuint maxProgramTextureGatherOffset;
GLint minProgramTexelOffset;
GLint maxProgramTexelOffset;
// Table 6.33, implementation dependent aggregate shader limits
// ES 3.1 (April 29, 2015) Table 20.45: implementation dependent compute shader limits
std::array<GLuint, 3> maxComputeWorkGroupCount;
std::array<GLuint, 3> maxComputeWorkGroupSize;
GLuint maxComputeWorkGroupInvocations;
GLuint maxComputeUniformBlocks;
GLuint maxComputeTextureImageUnits;
GLuint maxComputeSharedMemorySize;
GLuint maxComputeUniformComponents;
GLuint maxComputeAtomicCounterBuffers;
GLuint maxComputeAtomicCounters;
GLuint maxComputeImageUniforms;
GLuint maxCombinedComputeUniformComponents;
GLuint maxComputeShaderStorageBlocks;
// ES 3.1 (April 29, 2015) Table 20.46: implementation dependent aggregate shader limits
GLuint maxUniformBufferBindings;
GLuint64 maxUniformBlockSize;
GLuint uniformBufferOffsetAlignment;
......@@ -417,13 +454,27 @@ struct Caps
GLuint maxVaryingComponents;
GLuint maxVaryingVectors;
GLuint maxCombinedTextureImageUnits;
// Table 6.34, implementation dependent transform feedback limits
GLuint maxCombinedShaderOutputResources;
// ES 3.1 (April 29, 2015) Table 20.47: implementation dependent aggregate shader limits (cont.)
GLuint maxUniformLocations;
GLuint maxAtomicCounterBufferBindings;
GLuint maxAtomicCounterBufferSize;
GLuint maxCombinedAtomicCounterBuffers;
GLuint maxCombinedAtomicCounters;
GLuint maxImageUnits;
GLuint maxCombinedImageUniforms;
GLuint maxShaderStorageBufferBindings;
GLuint maxShaderStorageBlockSize;
GLuint maxCombinedShaderStorageBlocks;
GLuint shaderStorageBufferOffsetAlignment;
// ES 3.1 (April 29, 2015) Table 20.48: implementation dependent transform feedback limits
GLuint maxTransformFeedbackInterleavedComponents;
GLuint maxTransformFeedbackSeparateAttributes;
GLuint maxTransformFeedbackSeparateComponents;
// Table 6.35, Framebuffer Dependent Values
// ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
GLuint maxSamples;
};
......
......@@ -37,6 +37,7 @@
#include "libANGLE/validationES.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/EGLImplFactory.h"
#include "libANGLE/queryconversions.h"
namespace
{
......@@ -1366,7 +1367,129 @@ void Context::getIntegerv(GLenum pname, GLint *params)
case GL_GPU_DISJOINT_EXT:
*params = mImplementation->getGPUDisjoint();
break;
case GL_MAX_FRAMEBUFFER_WIDTH:
*params = mCaps.maxFramebufferWidth;
break;
case GL_MAX_FRAMEBUFFER_HEIGHT:
*params = mCaps.maxFramebufferHeight;
break;
case GL_MAX_FRAMEBUFFER_SAMPLES:
*params = mCaps.maxFramebufferSamples;
break;
case GL_MAX_SAMPLE_MASK_WORDS:
*params = mCaps.maxSampleMaskWords;
break;
case GL_MAX_COLOR_TEXTURE_SAMPLES:
*params = mCaps.maxColorTextureSamples;
break;
case GL_MAX_DEPTH_TEXTURE_SAMPLES:
*params = mCaps.maxDepthTextureSamples;
break;
case GL_MAX_INTEGER_SAMPLES:
*params = mCaps.maxIntegerSamples;
break;
case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
*params = mCaps.maxVertexAttribRelativeOffset;
break;
case GL_MAX_VERTEX_ATTRIB_BINDINGS:
*params = mCaps.maxVertexAttribBindings;
break;
case GL_MAX_VERTEX_ATTRIB_STRIDE:
*params = mCaps.maxVertexAttribStride;
break;
case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
*params = mCaps.maxVertexAtomicCounterBuffers;
break;
case GL_MAX_VERTEX_ATOMIC_COUNTERS:
*params = mCaps.maxVertexAtomicCounters;
break;
case GL_MAX_VERTEX_IMAGE_UNIFORMS:
*params = mCaps.maxVertexImageUniforms;
break;
case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
*params = mCaps.maxVertexShaderStorageBlocks;
break;
case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
*params = mCaps.maxFragmentAtomicCounterBuffers;
break;
case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
*params = mCaps.maxFragmentAtomicCounters;
break;
case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
*params = mCaps.maxFragmentImageUniforms;
break;
case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
*params = mCaps.maxFragmentShaderStorageBlocks;
break;
case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
*params = mCaps.minProgramTextureGatherOffset;
break;
case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
*params = mCaps.maxProgramTextureGatherOffset;
break;
case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
*params = mCaps.maxComputeWorkGroupInvocations;
break;
case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
*params = mCaps.maxComputeUniformBlocks;
break;
case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
*params = mCaps.maxComputeTextureImageUnits;
break;
case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
*params = mCaps.maxComputeSharedMemorySize;
break;
case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
*params = mCaps.maxComputeUniformComponents;
break;
case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
*params = mCaps.maxComputeAtomicCounterBuffers;
break;
case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
*params = mCaps.maxComputeAtomicCounters;
break;
case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
*params = mCaps.maxComputeImageUniforms;
break;
case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
*params = mCaps.maxCombinedComputeUniformComponents;
break;
case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
*params = mCaps.maxComputeShaderStorageBlocks;
break;
case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
*params = mCaps.maxCombinedShaderOutputResources;
break;
case GL_MAX_UNIFORM_LOCATIONS:
*params = mCaps.maxUniformLocations;
break;
case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
*params = mCaps.maxAtomicCounterBufferBindings;
break;
case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
*params = mCaps.maxAtomicCounterBufferSize;
break;
case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
*params = mCaps.maxCombinedAtomicCounterBuffers;
break;
case GL_MAX_COMBINED_ATOMIC_COUNTERS:
*params = mCaps.maxCombinedAtomicCounters;
break;
case GL_MAX_IMAGE_UNITS:
*params = mCaps.maxImageUnits;
break;
case GL_MAX_COMBINED_IMAGE_UNIFORMS:
*params = mCaps.maxCombinedImageUniforms;
break;
case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
*params = mCaps.maxShaderStorageBufferBindings;
break;
case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
*params = mCaps.maxCombinedShaderStorageBlocks;
break;
case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
*params = mCaps.shaderStorageBufferOffsetAlignment;
break;
default:
mGLState.getIntegerv(mState, pname, params);
break;
......@@ -1399,6 +1522,10 @@ void Context::getInteger64v(GLenum pname, GLint64 *params)
case GL_TIMESTAMP_EXT:
*params = mImplementation->getTimestamp();
break;
case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
*params = mCaps.maxShaderStorageBlockSize;
break;
default:
UNREACHABLE();
break;
......@@ -1410,22 +1537,76 @@ void Context::getPointerv(GLenum pname, void **params) const
mGLState.getPointerv(pname, params);
}
bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
void Context::getIntegeri_v(GLenum target, GLuint index, GLint *data)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
GLenum nativeType;
unsigned int numParams;
bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
ASSERT(queryStatus);
if (nativeType == GL_INT)
{
switch (target)
{
case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
ASSERT(index < 3u);
*data = mCaps.maxComputeWorkGroupCount[index];
break;
case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
ASSERT(index < 3u);
*data = mCaps.maxComputeWorkGroupSize[index];
break;
default:
mGLState.getIntegeri_v(target, index, data);
}
}
else
{
CastIndexedStateValues(this, nativeType, target, index, numParams, data);
}
}
void Context::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
// Indexed integer queries all refer to current state, so this function is a
// mere passthrough.
return mGLState.getIndexedIntegerv(target, index, data);
GLenum nativeType;
unsigned int numParams;
bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
ASSERT(queryStatus);
if (nativeType == GL_INT_64_ANGLEX)
{
mGLState.getInteger64i_v(target, index, data);
}
else
{
CastIndexedStateValues(this, nativeType, target, index, numParams, data);
}
}
bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
void Context::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
// Indexed integer queries all refer to current state, so this function is a
// mere passthrough.
return mGLState.getIndexedInteger64v(target, index, data);
GLenum nativeType;
unsigned int numParams;
bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
ASSERT(queryStatus);
if (nativeType == GL_BOOL)
{
mGLState.getBooleani_v(target, index, data);
}
else
{
CastIndexedStateValues(this, nativeType, target, index, numParams, data);
}
}
Error Context::drawArrays(GLenum mode, GLint first, GLsizei count)
......
......@@ -202,9 +202,9 @@ class Context final : public ValidationContext
void getIntegerv(GLenum pname, GLint *params);
void getInteger64v(GLenum pname, GLint64 *params);
void getPointerv(GLenum pname, void **params) const;
bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
void getIntegeri_v(GLenum target, GLuint index, GLint *data);
void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
void activeTexture(GLenum texture);
void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
......
......@@ -369,7 +369,9 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
return true;
}
if (getClientMajorVersion() < 3)
const GLVersion &glVersion = mState.getGLVersion();
if (!glVersion.isES3OrGreater())
{
return false;
}
......@@ -445,6 +447,63 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
}
}
if (!glVersion.isES31())
{
return false;
}
switch (pname)
{
case GL_MAX_FRAMEBUFFER_WIDTH:
case GL_MAX_FRAMEBUFFER_HEIGHT:
case GL_MAX_FRAMEBUFFER_SAMPLES:
case GL_MAX_SAMPLE_MASK_WORDS:
case GL_MAX_COLOR_TEXTURE_SAMPLES:
case GL_MAX_DEPTH_TEXTURE_SAMPLES:
case GL_MAX_INTEGER_SAMPLES:
case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
case GL_MAX_VERTEX_ATTRIB_BINDINGS:
case GL_MAX_VERTEX_ATTRIB_STRIDE:
case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
case GL_MAX_VERTEX_ATOMIC_COUNTERS:
case GL_MAX_VERTEX_IMAGE_UNIFORMS:
case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
case GL_MAX_UNIFORM_LOCATIONS:
case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
case GL_MAX_COMBINED_ATOMIC_COUNTERS:
case GL_MAX_IMAGE_UNITS:
case GL_MAX_COMBINED_IMAGE_UNIFORMS:
case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
*type = GL_INT;
*numParams = 1;
return true;
case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
*type = GL_INT_64_ANGLEX;
*numParams = 1;
return true;
}
return false;
}
......@@ -452,7 +511,9 @@ bool ValidationContext::getIndexedQueryParameterInfo(GLenum target,
GLenum *type,
unsigned int *numParams)
{
if (getClientMajorVersion() < 3)
const GLVersion &glVersion = mState.getGLVersion();
if (!glVersion.isES3OrGreater())
{
return false;
}
......@@ -477,6 +538,22 @@ bool ValidationContext::getIndexedQueryParameterInfo(GLenum target,
}
}
if (!glVersion.isES31())
{
return false;
}
switch (target)
{
case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
{
*type = GL_INT;
*numParams = 1;
return true;
}
}
return false;
}
......
......@@ -1797,7 +1797,7 @@ void State::getPointerv(GLenum pname, void **params) const
}
}
bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
void State::getIntegeri_v(GLenum target, GLuint index, GLint *data)
{
switch (target)
{
......@@ -1814,13 +1814,12 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
}
break;
default:
return false;
UNREACHABLE();
break;
}
return true;
}
bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
switch (target)
{
......@@ -1849,10 +1848,14 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
}
break;
default:
return false;
UNREACHABLE();
break;
}
}
return true;
void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
{
UNREACHABLE();
}
bool State::hasMappedBuffer(GLenum target) const
......
......@@ -291,8 +291,9 @@ class State : angle::NonCopyable
void getFloatv(GLenum pname, GLfloat *params);
void getIntegerv(const ContextState &data, GLenum pname, GLint *params);
void getPointerv(GLenum pname, void **params) const;
bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
void getIntegeri_v(GLenum target, GLuint index, GLint *data);
void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
bool hasMappedBuffer(GLenum target) const;
......@@ -479,4 +480,3 @@ class State : angle::NonCopyable
} // namespace gl
#endif // LIBANGLE_STATE_H_
......@@ -154,4 +154,77 @@ template void CastStateValues<GLuint>(Context *, GLenum, GLenum, unsigned int, G
template void CastStateValues<GLfloat>(Context *, GLenum, GLenum, unsigned int, GLfloat *);
template void CastStateValues<GLint64>(Context *, GLenum, GLenum, unsigned int, GLint64 *);
template <typename QueryT>
void CastIndexedStateValues(Context *context,
GLenum nativeType,
GLenum pname,
GLuint index,
unsigned int numParams,
QueryT *outParams)
{
if (nativeType == GL_INT)
{
std::vector<GLint> intParams(numParams, 0);
context->getIntegeri_v(pname, index, intParams.data());
for (unsigned int i = 0; i < numParams; ++i)
{
outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
}
}
else if (nativeType == GL_BOOL)
{
std::vector<GLboolean> boolParams(numParams, GL_FALSE);
context->getBooleani_v(pname, index, boolParams.data());
for (unsigned int i = 0; i < numParams; ++i)
{
outParams[i] =
(boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
}
}
else if (nativeType == GL_INT_64_ANGLEX)
{
std::vector<GLint64> int64Params(numParams, 0);
context->getInteger64i_v(pname, index, int64Params.data());
for (unsigned int i = 0; i < numParams; ++i)
{
outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
}
}
else
UNREACHABLE();
}
template void CastIndexedStateValues<GLboolean>(Context *,
GLenum,
GLenum,
GLuint index,
unsigned int,
GLboolean *);
template void CastIndexedStateValues<GLint>(Context *,
GLenum,
GLenum,
GLuint index,
unsigned int,
GLint *);
template void CastIndexedStateValues<GLuint>(Context *,
GLenum,
GLenum,
GLuint index,
unsigned int,
GLuint *);
template void CastIndexedStateValues<GLfloat>(Context *,
GLenum,
GLenum,
GLuint index,
unsigned int,
GLfloat *);
template void CastIndexedStateValues<GLint64>(Context *,
GLenum,
GLenum,
GLuint index,
unsigned int,
GLint64 *);
}
......@@ -31,6 +31,14 @@ template <typename QueryT>
void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams);
// The GL state query API types are: bool, int, uint, float, int64
template <typename QueryT>
void CastIndexedStateValues(Context *context,
GLenum nativeType,
GLenum pname,
GLuint index,
unsigned int numParams,
QueryT *outParams);
}
#endif // LIBANGLE_QUERY_CONVERSIONS_H_
......@@ -120,6 +120,13 @@ static GLint QuerySingleGLInt(const FunctionsGL *functions, GLenum name)
return result;
}
static GLint QuerySingleIndexGLInt(const FunctionsGL *functions, GLenum name, GLuint index)
{
GLint result;
functions->getIntegeri_v(name, index, &result);
return result;
}
static GLint QueryGLIntRange(const FunctionsGL *functions, GLenum name, size_t index)
{
GLint result[2] = {};
......@@ -592,6 +599,164 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_texture_multisample"))
{
caps->maxFramebufferWidth = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_WIDTH);
caps->maxFramebufferHeight = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_HEIGHT);
caps->maxFramebufferSamples = QuerySingleGLInt(functions, GL_MAX_FRAMEBUFFER_SAMPLES);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(3, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_texture_multisample"))
{
caps->maxSampleMaskWords = QuerySingleGLInt(functions, GL_MAX_SAMPLE_MASK_WORDS);
caps->maxColorTextureSamples = QuerySingleGLInt(functions, GL_MAX_COLOR_TEXTURE_SAMPLES);
caps->maxDepthTextureSamples = QuerySingleGLInt(functions, GL_MAX_DEPTH_TEXTURE_SAMPLES);
caps->maxIntegerSamples = QuerySingleGLInt(functions, GL_MAX_INTEGER_SAMPLES);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_vertex_attrib_binding"))
{
caps->maxVertexAttribRelativeOffset =
QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
caps->maxVertexAttribBindings = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_BINDINGS);
caps->maxVertexAttribStride = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATTRIB_STRIDE);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_shader_storage_buffer_object"))
{
caps->maxCombinedShaderOutputResources =
QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES);
caps->maxFragmentShaderStorageBlocks =
QuerySingleGLInt(functions, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
caps->maxVertexShaderStorageBlocks =
QuerySingleGLInt(functions, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
caps->maxShaderStorageBufferBindings =
QuerySingleGLInt(functions, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
caps->maxShaderStorageBlockSize =
QuerySingleGLInt64(functions, GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
caps->maxCombinedShaderStorageBlocks =
QuerySingleGLInt(functions, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS);
caps->shaderStorageBufferOffsetAlignment =
QuerySingleGLInt(functions, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_compute_shader"))
{
for (GLuint index = 0u; index < 3u; ++index)
{
caps->maxComputeWorkGroupCount[index] =
QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_COUNT, index);
caps->maxComputeWorkGroupSize[index] =
QuerySingleIndexGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_SIZE, index);
}
caps->maxComputeWorkGroupInvocations =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS);
caps->maxComputeUniformBlocks = QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_BLOCKS);
caps->maxComputeTextureImageUnits =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS);
caps->maxComputeSharedMemorySize =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
caps->maxComputeUniformComponents =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_UNIFORM_COMPONENTS);
caps->maxComputeAtomicCounterBuffers =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
caps->maxComputeAtomicCounters =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_ATOMIC_COUNTERS);
caps->maxComputeImageUniforms = QuerySingleGLInt(functions, GL_MAX_COMPUTE_IMAGE_UNIFORMS);
caps->maxCombinedComputeUniformComponents =
QuerySingleGLInt(functions, GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS);
caps->maxComputeShaderStorageBlocks =
QuerySingleGLInt(functions, GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 3)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_explicit_uniform_location"))
{
caps->maxUniformLocations = QuerySingleGLInt(functions, GL_MAX_UNIFORM_LOCATIONS);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 0)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_texture_gather"))
{
caps->minProgramTextureGatherOffset =
QuerySingleGLInt(functions, GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET);
caps->maxProgramTextureGatherOffset =
QuerySingleGLInt(functions, GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_shader_image_load_store"))
{
caps->maxVertexImageUniforms = QuerySingleGLInt(functions, GL_MAX_VERTEX_IMAGE_UNIFORMS);
caps->maxFragmentImageUniforms =
QuerySingleGLInt(functions, GL_MAX_FRAGMENT_IMAGE_UNIFORMS);
caps->maxImageUnits = QuerySingleGLInt(functions, GL_MAX_IMAGE_UNITS);
caps->maxCombinedImageUniforms =
QuerySingleGLInt(functions, GL_MAX_COMBINED_IMAGE_UNIFORMS);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
if (functions->isAtLeastGL(gl::Version(4, 2)) || functions->isAtLeastGLES(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_shader_atomic_counters"))
{
caps->maxVertexAtomicCounterBuffers =
QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS);
caps->maxVertexAtomicCounters = QuerySingleGLInt(functions, GL_MAX_VERTEX_ATOMIC_COUNTERS);
caps->maxFragmentAtomicCounterBuffers =
QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS);
caps->maxFragmentAtomicCounters =
QuerySingleGLInt(functions, GL_MAX_FRAGMENT_ATOMIC_COUNTERS);
caps->maxAtomicCounterBufferBindings =
QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
caps->maxAtomicCounterBufferSize =
QuerySingleGLInt(functions, GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE);
caps->maxCombinedAtomicCounterBuffers =
QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS);
caps->maxCombinedAtomicCounters =
QuerySingleGLInt(functions, GL_MAX_COMBINED_ATOMIC_COUNTERS);
}
else
{
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
// TODO(geofflang): The gl-uniform-arrays WebGL conformance test struggles to complete on time
// if the max uniform vectors is too large. Artificially limit the maximum until the test is
// updated.
......
......@@ -13,6 +13,7 @@
#include <GLES2/gl2.h>
#include <GLES3/gl3.h>
#include <GLES3/gl31.h>
namespace egl
{
......
......@@ -2160,4 +2160,78 @@ bool ValidateFlushMappedBufferRange(Context *context,
return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
}
bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index)
{
GLenum nativeType;
unsigned int numParams;
if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
const Caps &caps = context->getCaps();
switch (pname)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
if (index >= caps.maxTransformFeedbackSeparateAttributes)
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
break;
case GL_UNIFORM_BUFFER_START:
case GL_UNIFORM_BUFFER_SIZE:
case GL_UNIFORM_BUFFER_BINDING:
if (index >= caps.maxUniformBufferBindings)
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
break;
case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
if (index >= 3u)
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
// pname is valid, but there are no parameters to return
if (numParams == 0)
{
return false;
}
return true;
}
bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
{
if (!context->getGLVersion().isES3OrGreater())
{
context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
return false;
}
return ValidateIndexedStateQuery(context, target, index);
}
bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
{
if (!context->getGLVersion().isES3OrGreater())
{
context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.0"));
return false;
}
return ValidateIndexedStateQuery(context, target, index);
}
} // namespace gl
......@@ -309,6 +309,12 @@ bool ValidateFlushMappedBufferRange(Context *context,
GLintptr offset,
GLsizeiptr length);
bool ValidateIndexedStateQuery(ValidationContext *context, GLenum pname, GLuint index);
bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data);
bool ValidateGetInteger64i_v(ValidationContext *context,
GLenum target,
GLuint index,
GLint64 *data);
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES3_H_
//
// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
#include "libANGLE/validationES3.h"
#include "libANGLE/validationES31.h"
#include "libANGLE/Context.h"
using namespace angle;
namespace gl
{
bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
{
if (!context->getGLVersion().isES31())
{
context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
return false;
}
if (!ValidateIndexedStateQuery(context, target, index))
{
return false;
}
return true;
}
} // namespace gl
//
// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// validationES31.h: Validation functions for OpenGL ES 3.1 entry point parameters
#ifndef LIBANGLE_VALIDATION_ES31_H_
#define LIBANGLE_VALIDATION_ES31_H_
#include <GLES3/gl31.h>
namespace gl
{
class Context;
bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data);
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES31_H_
......@@ -197,6 +197,8 @@
'libANGLE/validationES2.h',
'libANGLE/validationES3.cpp',
'libANGLE/validationES3.h',
'libANGLE/validationES31.cpp',
'libANGLE/validationES31.h',
'third_party/murmurhash/MurmurHash3.cpp',
'third_party/murmurhash/MurmurHash3.h',
],
......
......@@ -657,7 +657,7 @@ GLboolean GL_APIENTRY IsVertexArray(GLuint array)
return GL_FALSE;
}
void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data)
void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data)
{
EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
target, index, data);
......@@ -665,76 +665,11 @@ void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientMajorVersion() < 3)
if (!context->skipValidation() && !ValidateGetIntegeri_v(context, target, index, data))
{
context->handleError(Error(GL_INVALID_OPERATION));
return;
}
const Caps &caps = context->getCaps();
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
if (index >= caps.maxTransformFeedbackSeparateAttributes)
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
break;
case GL_UNIFORM_BUFFER_START:
case GL_UNIFORM_BUFFER_SIZE:
case GL_UNIFORM_BUFFER_BINDING:
if (index >= caps.maxCombinedUniformBlocks)
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM));
return;
}
if (!(context->getIndexedIntegerv(target, index, data)))
{
GLenum nativeType;
unsigned int numParams = 0;
if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
if (numParams == 0)
{
return; // it is known that pname is valid, but there are no parameters to return
}
if (nativeType == GL_INT_64_ANGLEX)
{
GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
GLint64 *int64Params = new GLint64[numParams];
context->getIndexedInteger64v(target, index, int64Params);
for (unsigned int i = 0; i < numParams; ++i)
{
GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
data[i] = static_cast<GLint>(clampedValue);
}
delete [] int64Params;
}
else
{
UNREACHABLE();
}
}
context->getIntegeri_v(target, index, data);
}
}
......@@ -2156,71 +2091,11 @@ void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientMajorVersion() < 3)
if (!context->skipValidation() && !ValidateGetInteger64i_v(context, target, index, data))
{
context->handleError(Error(GL_INVALID_OPERATION));
return;
}
const Caps &caps = context->getCaps();
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
if (index >= caps.maxTransformFeedbackSeparateAttributes)
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
break;
case GL_UNIFORM_BUFFER_START:
case GL_UNIFORM_BUFFER_SIZE:
case GL_UNIFORM_BUFFER_BINDING:
if (index >= caps.maxUniformBufferBindings)
{
context->handleError(Error(GL_INVALID_VALUE));
return;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM));
return;
}
if (!(context->getIndexedInteger64v(target, index, data)))
{
GLenum nativeType;
unsigned int numParams = 0;
if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
if (numParams == 0)
return; // it is known that pname is valid, but there are no parameters to return
if (nativeType == GL_INT)
{
GLint *intParams = new GLint[numParams];
context->getIndexedIntegerv(target, index, intParams);
for (unsigned int i = 0; i < numParams; ++i)
{
data[i] = static_cast<GLint64>(intParams[i]);
}
delete [] intParams;
}
else
{
UNREACHABLE();
}
}
context->getInteger64i_v(target, index, data);
}
}
......
......@@ -12,7 +12,7 @@
#include "libANGLE/Context.h"
#include "libANGLE/Error.h"
#include "libANGLE/validationES3.h"
#include "libANGLE/validationES31.h"
#include "common/debug.h"
......@@ -1006,14 +1006,15 @@ void GL_APIENTRY GetBooleani_v(GLenum target, GLuint index, GLboolean *data)
{
EVENT("(GLenum target = 0x%X, GLuint index = %u, GLboolean* data = 0x%0.8p)", target, index,
data);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation())
if (!context->skipValidation() && !ValidateGetBooleani_v(context, target, index, data))
{
context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
return;
}
UNIMPLEMENTED();
context->getBooleani_v(target, index, data);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment