Commit 2b97681b by Jamie Madill

Extract validation from VertexDataManager.cpp to the API.

We can check for buffer overflow at draw validation time, before processing any vertex data. BUG=angle:571 Change-Id: I4f49629b98c17ca28e25baed74cad4ae5341b20f Reviewed-on: https://chromium-review.googlesource.com/210647Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org>
parent 1fecbc85
...@@ -50,6 +50,7 @@ class Buffer : public RefCountObject ...@@ -50,6 +50,7 @@ class Buffer : public RefCountObject
void markTransformFeedbackUsage(); void markTransformFeedbackUsage();
rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; }
const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; }
private: private:
DISALLOW_COPY_AND_ASSIGN(Buffer); DISALLOW_COPY_AND_ASSIGN(Buffer);
......
...@@ -1761,7 +1761,9 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan ...@@ -1761,7 +1761,9 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
} }
} }
void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances) void Context::drawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei instances,
const rx::RangeUI &indexRange)
{ {
ASSERT(mState.getCurrentProgramId() != 0); ASSERT(mState.getCurrentProgramId() != 0);
...@@ -1795,6 +1797,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid ...@@ -1795,6 +1797,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid
VertexArray *vao = mState.getVertexArray(); VertexArray *vao = mState.getVertexArray();
rx::TranslatedIndexData indexInfo; rx::TranslatedIndexData indexInfo;
indexInfo.indexRange = indexRange;
GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
if (err != GL_NO_ERROR) if (err != GL_NO_ERROR)
{ {
......
...@@ -194,7 +194,9 @@ class Context ...@@ -194,7 +194,9 @@ class Context
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); void drawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei instances,
const rx::RangeUI &indexRange);
void sync(bool block); // flush/finish void sync(bool block); // flush/finish
void recordError(const Error &error); void recordError(const Error &error);
......
...@@ -1294,7 +1294,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -1294,7 +1294,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
if (context) if (context)
{ {
if (!ValidateDrawArrays(context, mode, first, count)) if (!ValidateDrawArrays(context, mode, first, count, 0))
{ {
return; return;
} }
...@@ -1329,12 +1329,13 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv ...@@ -1329,12 +1329,13 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
if (context) if (context)
{ {
if (!ValidateDrawElements(context, mode, count, type, indices)) rx::RangeUI indexRange;
if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
{ {
return; return;
} }
context->drawElements(mode, count, type, indices, 0); context->drawElements(mode, count, type, indices, 0, indexRange);
} }
} }
...@@ -1347,12 +1348,13 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t ...@@ -1347,12 +1348,13 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t
if (context) if (context)
{ {
if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount)) rx::RangeUI indexRange;
if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, &indexRange))
{ {
return; return;
} }
context->drawElements(mode, count, type, indices, primcount); context->drawElements(mode, count, type, indices, primcount, indexRange);
} }
} }
......
...@@ -16,6 +16,37 @@ ...@@ -16,6 +16,37 @@
namespace rx namespace rx
{ {
template <class IndexType>
static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count)
{
unsigned int minIndex = indices[0];
unsigned int maxIndex = indices[0];
for (GLsizei i = 1; i < count; i++)
{
if (minIndex > indices[i]) minIndex = indices[i];
if (maxIndex < indices[i]) maxIndex = indices[i];
}
return RangeUI(minIndex, maxIndex);
}
RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count)
{
switch (type)
{
case GL_UNSIGNED_BYTE:
return ComputeTypedRange(static_cast<const GLubyte*>(indices), count);
case GL_UNSIGNED_INT:
return ComputeTypedRange(static_cast<const GLuint*>(indices), count);
case GL_UNSIGNED_SHORT:
return ComputeTypedRange(static_cast<const GLushort*>(indices), count);
default:
UNREACHABLE();
return RangeUI();
}
}
void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range,
unsigned int streamOffset) unsigned int streamOffset)
{ {
......
...@@ -28,6 +28,8 @@ class IndexRangeCache ...@@ -28,6 +28,8 @@ class IndexRangeCache
void invalidateRange(unsigned int offset, unsigned int size); void invalidateRange(unsigned int offset, unsigned int size);
void clear(); void clear();
static RangeUI ComputeRange(GLenum type, const GLvoid *indices, GLsizei count);
private: private:
struct IndexRange struct IndexRange
{ {
......
...@@ -20,42 +20,7 @@ ...@@ -20,42 +20,7 @@
namespace rx namespace rx
{ {
IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output)
{
mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
{
delete mStreamingBufferShort;
mStreamingBufferShort = NULL;
}
mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
{
delete mStreamingBufferInt;
mStreamingBufferInt = NULL;
}
if (!mStreamingBufferShort)
{
// Make sure both buffers are deleted.
delete mStreamingBufferInt;
mStreamingBufferInt = NULL;
ERR("Failed to allocate the streaming index buffer(s).");
}
mCountingBuffer = NULL;
}
IndexDataManager::~IndexDataManager()
{
delete mStreamingBufferShort;
delete mStreamingBufferInt;
delete mCountingBuffer;
}
static void convertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output)
{ {
if (sourceType == GL_UNSIGNED_BYTE) if (sourceType == GL_UNSIGNED_BYTE)
{ {
...@@ -94,35 +59,36 @@ static void convertIndices(GLenum sourceType, GLenum destinationType, const void ...@@ -94,35 +59,36 @@ static void convertIndices(GLenum sourceType, GLenum destinationType, const void
else UNREACHABLE(); else UNREACHABLE();
} }
template <class IndexType> IndexDataManager::IndexDataManager(Renderer *renderer)
static RangeUI computeRange(const IndexType *indices, GLsizei count) : mRenderer(renderer)
{ {
unsigned int minIndex = indices[0]; mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
unsigned int maxIndex = indices[0]; if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
{
SafeDelete(mStreamingBufferShort);
}
mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
{
SafeDelete(mStreamingBufferInt);
}
for (GLsizei i = 1; i < count; i++) if (!mStreamingBufferShort)
{ {
if (minIndex > indices[i]) minIndex = indices[i]; // Make sure both buffers are deleted.
if (maxIndex < indices[i]) maxIndex = indices[i]; SafeDelete(mStreamingBufferInt);
ERR("Failed to allocate the streaming index buffer(s).");
} }
return RangeUI(minIndex, maxIndex); mCountingBuffer = NULL;
} }
static RangeUI computeRange(GLenum type, const GLvoid *indices, GLsizei count) IndexDataManager::~IndexDataManager()
{ {
switch (type) SafeDelete(mStreamingBufferShort);
{ SafeDelete(mStreamingBufferInt);
case GL_UNSIGNED_BYTE: SafeDelete(mCountingBuffer);
return computeRange(static_cast<const GLubyte*>(indices), count);
case GL_UNSIGNED_INT:
return computeRange(static_cast<const GLuint*>(indices), count);
case GL_UNSIGNED_SHORT:
return computeRange(static_cast<const GLushort*>(indices), count);
default:
UNREACHABLE();
return RangeUI();
}
} }
GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
...@@ -184,9 +150,8 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -184,9 +150,8 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
{ {
streamOffset = offset; streamOffset = offset;
if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->indexRange, NULL)) if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL))
{ {
translated->indexRange = computeRange(type, indices, count);
buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset); buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset);
} }
} }
...@@ -194,17 +159,12 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -194,17 +159,12 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
{ {
indexBuffer = staticBuffer; indexBuffer = staticBuffer;
if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->indexRange, &streamOffset)) if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset))
{ {
streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes; streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes;
translated->indexRange = computeRange(type, indices, count);
staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset);
} }
} }
else
{
translated->indexRange = computeRange(type, indices, count);
}
// Avoid D3D11's primitive restart index value // Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
...@@ -263,7 +223,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer ...@@ -263,7 +223,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
return GL_OUT_OF_MEMORY; return GL_OUT_OF_MEMORY;
} }
convertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output); ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output);
if (!indexBuffer->unmapBuffer()) if (!indexBuffer->unmapBuffer())
{ {
......
...@@ -144,13 +144,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], ...@@ -144,13 +144,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
else else
{ {
int totalCount = StreamingBufferElementCount(attribs[i], count, instances); int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
ASSERT(!bufferImpl || ElementsInBuffer(attribs[i], bufferImpl->getSize()) >= totalCount);
// [OpenGL ES 3.0.2] section 2.9.4 page 40:
// We can return INVALID_OPERATION if our vertex attribute does not have enough backing data.
if (bufferImpl && ElementsInBuffer(attribs[i], bufferImpl->getSize()) < totalCount)
{
return GL_INVALID_OPERATION;
}
if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances)) if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances))
{ {
...@@ -217,13 +211,7 @@ GLenum VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, ...@@ -217,13 +211,7 @@ GLenum VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
GLsizei instances) GLsizei instances)
{ {
gl::Buffer *buffer = attrib.buffer.get(); gl::Buffer *buffer = attrib.buffer.get();
ASSERT(buffer || attrib.pointer);
if (!buffer && attrib.pointer == NULL)
{
// This is an application error that would normally result in a crash, but we catch it and return an error
ERR("An enabled vertex array has no buffer and no pointer.");
return GL_INVALID_OPERATION;
}
BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/TransformFeedback.h" #include "libGLESv2/TransformFeedback.h"
#include "libGLESv2/VertexArray.h" #include "libGLESv2/VertexArray.h"
#include "libGLESv2/renderer/BufferImpl.h"
#include "common/mathutil.h" #include "common/mathutil.h"
#include "common/utilities.h" #include "common/utilities.h"
...@@ -1301,7 +1302,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi ...@@ -1301,7 +1302,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return true; return true;
} }
static bool ValidateDrawBase(const gl::State &state, GLenum mode, GLsizei count) static bool ValidateDrawBase(const gl::State &state, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount)
{ {
switch (mode) switch (mode)
{ {
...@@ -1357,11 +1358,55 @@ static bool ValidateDrawBase(const gl::State &state, GLenum mode, GLsizei count) ...@@ -1357,11 +1358,55 @@ static bool ValidateDrawBase(const gl::State &state, GLenum mode, GLsizei count)
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
// Buffer validations
const VertexArray *vao = state.getVertexArray();
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1);
if (attribActive && attrib.enabled)
{
gl::Buffer *buffer = attrib.buffer.get();
if (buffer)
{
GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
GLint64 maxVertexElement = 0;
if (attrib.divisor > 0)
{
maxVertexElement = static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
}
else
{
maxVertexElement = static_cast<GLint64>(maxVertex);
}
GLint64 attribDataSize = maxVertexElement * attribStride;
// [OpenGL ES 3.0.2] section 2.9.4 page 40:
// We can return INVALID_OPERATION if our vertex attribute does not have
// enough backing data.
if (attribDataSize > buffer->getSize())
{
return gl::error(GL_INVALID_OPERATION, false);
}
}
else if (attrib.pointer == NULL)
{
// This is an application error that would normally result in a crash,
// but we catch it and return an error
ERR("An enabled vertex array has no buffer and no pointer.");
return gl::error(GL_INVALID_OPERATION, false);
}
}
}
// No-op if zero count // No-op if zero count
return (count > 0); return (count > 0);
} }
bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count) bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{ {
if (first < 0) if (first < 0)
{ {
...@@ -1379,7 +1424,7 @@ bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GL ...@@ -1379,7 +1424,7 @@ bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GL
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
if (!ValidateDrawBase(state, mode, count)) if (!ValidateDrawBase(state, mode, count, count, primcount))
{ {
return false; return false;
} }
...@@ -1394,7 +1439,7 @@ bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint ...@@ -1394,7 +1439,7 @@ bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint
return gl::error(GL_INVALID_VALUE, false); return gl::error(GL_INVALID_VALUE, false);
} }
if (!ValidateDrawArrays(context, mode, first, count)) if (!ValidateDrawArrays(context, mode, first, count, primcount))
{ {
return false; return false;
} }
...@@ -1403,7 +1448,8 @@ bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint ...@@ -1403,7 +1448,8 @@ bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint
return (primcount > 0); return (primcount > 0);
} }
bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut)
{ {
switch (type) switch (type)
{ {
...@@ -1436,13 +1482,32 @@ bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count ...@@ -1436,13 +1482,32 @@ bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
gl::VertexArray *vao = state.getVertexArray(); const gl::VertexArray *vao = state.getVertexArray();
if (!indices && !vao->getElementArrayBuffer()) const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
if (!indices && !elementArrayBuffer)
{ {
return gl::error(GL_INVALID_OPERATION, false); return gl::error(GL_INVALID_OPERATION, false);
} }
if (!ValidateDrawBase(state, mode, count)) // Use max index to validate if our vertex buffers are large enough for the pull.
// TODO: offer fast path, with disabled index validation.
// TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
if (elementArrayBuffer)
{
unsigned int offset = reinterpret_cast<unsigned int>(indices);
if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
{
const void *dataPointer = elementArrayBuffer->getImplementation()->getData();
const uint8_t *offsetPointer = static_cast<const uint8_t *>(dataPointer) + offset;
*indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count);
}
}
else
{
*indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count);
}
if (!ValidateDrawBase(state, mode, count, static_cast<GLsizei>(indexRangeOut->end), primcount))
{ {
return false; return false;
} }
...@@ -1450,15 +1515,17 @@ bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count ...@@ -1450,15 +1515,17 @@ bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count
return true; return true;
} }
bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, bool ValidateDrawElementsInstanced(const gl::Context *context,
const GLvoid *indices, GLsizei primcount) GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount,
rx::RangeUI *indexRangeOut)
{ {
if (primcount < 0) if (primcount < 0)
{ {
return gl::error(GL_INVALID_VALUE, false); return gl::error(GL_INVALID_VALUE, false);
} }
if (!ValidateDrawElements(context, mode, count, type, indices)) if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
{ {
return false; return false;
} }
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#ifndef LIBGLESV2_VALIDATION_ES_H #ifndef LIBGLESV2_VALIDATION_ES_H
#define LIBGLESV2_VALIDATION_ES_H #define LIBGLESV2_VALIDATION_ES_H
#include "common/mathutil.h"
namespace gl namespace gl
{ {
...@@ -59,11 +61,14 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi ...@@ -59,11 +61,14 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height,
GLint border, GLenum *textureInternalFormatOut); GLint border, GLenum *textureInternalFormatOut);
bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count); bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut);
bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount); const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut);
bool ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, GLenum attachment, bool ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, GLenum attachment,
GLuint texture, GLint level); GLuint texture, GLint level);
......
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