Commit 4f66748d by Olli Etuaho Committed by Commit Bot

Fix buffer mapping validation and refactor entry points

Checks for extension support are added to GetBufferPointervOES, mapBufferOES, unmapBufferOES, mapBufferRangeEXT and flushMappedBufferRangeEXT. The GetBufferPointerv function now checks if state is queried from buffer object zero. The code is also refactored so that validation happens in separate validation functions and the implementations are in Context functions. BUG=angleproject:1101 TEST=dEQP-GLES3.functional.negative_api.state.get_buffer_pointerv dEQP-GLES3.functional.*buffer*map* (no regression) Change-Id: I0f439abd12c92c51324f2e5a31bf621f61534306 Reviewed-on: https://chromium-review.googlesource.com/336164Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 9696316d
...@@ -2684,6 +2684,75 @@ void Context::compressedTexSubImage3D(GLenum target, ...@@ -2684,6 +2684,75 @@ void Context::compressedTexSubImage3D(GLenum target,
} }
} }
void Context::getBufferPointerv(GLenum target, GLenum /*pname*/, void **params)
{
Buffer *buffer = getState().getTargetBuffer(target);
ASSERT(buffer);
if (!buffer->isMapped())
{
*params = nullptr;
}
else
{
*params = buffer->getMapPointer();
}
}
GLvoid *Context::mapBuffer(GLenum target, GLenum access)
{
Buffer *buffer = getState().getTargetBuffer(target);
ASSERT(buffer);
Error error = buffer->map(access);
if (error.isError())
{
recordError(error);
return nullptr;
}
return buffer->getMapPointer();
}
GLboolean Context::unmapBuffer(GLenum target)
{
Buffer *buffer = getState().getTargetBuffer(target);
ASSERT(buffer);
GLboolean result;
Error error = buffer->unmap(&result);
if (error.isError())
{
recordError(error);
return GL_FALSE;
}
return result;
}
GLvoid *Context::mapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access)
{
Buffer *buffer = getState().getTargetBuffer(target);
ASSERT(buffer);
Error error = buffer->mapRange(offset, length, access);
if (error.isError())
{
recordError(error);
return nullptr;
}
return buffer->getMapPointer();
}
void Context::flushMappedBufferRange(GLenum /*target*/, GLintptr /*offset*/, GLsizeiptr /*length*/)
{
// We do not currently support a non-trivial implementation of FlushMappedBufferRange
}
void Context::syncStateForReadPixels() void Context::syncStateForReadPixels()
{ {
syncRendererState(mReadPixelsDirtyBits, mReadPixelsDirtyObjects); syncRendererState(mReadPixelsDirtyBits, mReadPixelsDirtyObjects);
......
...@@ -372,6 +372,12 @@ class Context final : public ValidationContext ...@@ -372,6 +372,12 @@ class Context final : public ValidationContext
Error flush(); Error flush();
Error finish(); Error finish();
void getBufferPointerv(GLenum target, GLenum pname, void **params);
GLvoid *mapBuffer(GLenum target, GLenum access);
GLboolean unmapBuffer(GLenum target);
GLvoid *mapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
void flushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
void beginTransformFeedback(GLenum primitiveMode); void beginTransformFeedback(GLenum primitiveMode);
bool hasActiveTransformFeedback(GLuint program) const; bool hasActiveTransformFeedback(GLuint program) const;
......
...@@ -2660,6 +2660,191 @@ bool ValidateCopyTexSubImage2D(Context *context, ...@@ -2660,6 +2660,191 @@ bool ValidateCopyTexSubImage2D(Context *context,
yoffset, 0, x, y, width, height, 0); yoffset, 0, x, y, width, height, 0);
} }
bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
{
if (!ValidBufferTarget(context, target))
{
context->recordError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
return false;
}
if (pname != GL_BUFFER_MAP_POINTER)
{
context->recordError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
return false;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
// GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
// target bound to zero generate an INVALID_OPERATION error."
// GLES 3.1 section 6.6 explicitly specifies this error.
if (!buffer)
{
context->recordError(
Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
return false;
}
return true;
}
bool ValidateUnmapBufferBase(Context *context, GLenum target)
{
if (!ValidBufferTarget(context, target))
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
return false;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (buffer == nullptr || !buffer->isMapped())
{
context->recordError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
return false;
}
return true;
}
bool ValidateMapBufferRangeBase(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access)
{
if (!ValidBufferTarget(context, target))
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
return false;
}
if (offset < 0 || length < 0)
{
context->recordError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
return false;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (!buffer)
{
context->recordError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
return false;
}
// Check for buffer overflow
size_t offsetSize = static_cast<size_t>(offset);
size_t lengthSize = static_cast<size_t>(length);
if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
{
context->recordError(
Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
return false;
}
// Check for invalid bits in the mask
GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
GL_MAP_UNSYNCHRONIZED_BIT;
if (access & ~(allAccessBits))
{
context->recordError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
return false;
}
if (length == 0)
{
context->recordError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
return false;
}
if (buffer->isMapped())
{
context->recordError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
return false;
}
// Check for invalid bit combinations
if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
{
context->recordError(
Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
return false;
}
GLbitfield writeOnlyBits =
GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
{
context->recordError(Error(GL_INVALID_OPERATION,
"Invalid access bits when mapping buffer for reading: 0x%X.",
access));
return false;
}
if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
{
context->recordError(Error(
GL_INVALID_OPERATION,
"The explicit flushing bit may only be set if the buffer is mapped for writing."));
return false;
}
return true;
}
bool ValidateFlushMappedBufferRangeBase(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length)
{
if (offset < 0 || length < 0)
{
context->recordError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
return false;
}
if (!ValidBufferTarget(context, target))
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
return false;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (buffer == nullptr)
{
context->recordError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
return false;
}
if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
{
context->recordError(Error(
GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
return false;
}
// Check for buffer overflow
size_t offsetSize = static_cast<size_t>(offset);
size_t lengthSize = static_cast<size_t>(length);
if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
{
context->recordError(
Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
return false;
}
return true;
}
bool ValidateGenBuffers(Context *context, GLint n, GLuint *) bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
{ {
return ValidateGenOrDelete(context, n); return ValidateGenOrDelete(context, n);
......
...@@ -235,6 +235,18 @@ bool ValidateCopyTexSubImage2D(Context *context, ...@@ -235,6 +235,18 @@ bool ValidateCopyTexSubImage2D(Context *context,
GLsizei width, GLsizei width,
GLsizei height); GLsizei height);
bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params);
bool ValidateUnmapBufferBase(Context *context, GLenum target);
bool ValidateMapBufferRangeBase(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
bool ValidateFlushMappedBufferRangeBase(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length);
bool ValidateGenBuffers(Context *context, GLint n, GLuint *buffers); bool ValidateGenBuffers(Context *context, GLint n, GLuint *buffers);
bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *buffers); bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *buffers);
bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *framebuffers); bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *framebuffers);
......
...@@ -1882,4 +1882,94 @@ bool ValidateCompressedTexSubImage2D(Context *context, ...@@ -1882,4 +1882,94 @@ bool ValidateCompressedTexSubImage2D(Context *context,
return true; return true;
} }
bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params)
{
if (!context->getExtensions().mapBuffer)
{
context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
return false;
}
return ValidateGetBufferPointervBase(context, target, pname, params);
}
bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access)
{
if (!context->getExtensions().mapBuffer)
{
context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
return false;
}
if (!ValidBufferTarget(context, target))
{
context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
return false;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (buffer == nullptr)
{
context->recordError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
return false;
}
if (access != GL_WRITE_ONLY_OES)
{
context->recordError(Error(GL_INVALID_ENUM, "Non-write buffer mapping not supported."));
return false;
}
if (buffer->isMapped())
{
context->recordError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
return false;
}
return true;
}
bool ValidateUnmapBufferOES(Context *context, GLenum target)
{
if (!context->getExtensions().mapBuffer)
{
context->recordError(Error(GL_INVALID_OPERATION, "Map buffer extension not available."));
return false;
}
return ValidateUnmapBufferBase(context, target);
}
bool ValidateMapBufferRangeEXT(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access)
{
if (!context->getExtensions().mapBufferRange)
{
context->recordError(
Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
return false;
}
return ValidateMapBufferRangeBase(context, target, offset, length, access);
}
bool ValidateFlushMappedBufferRangeEXT(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length)
{
if (!context->getExtensions().mapBufferRange)
{
context->recordError(
Error(GL_INVALID_OPERATION, "Map buffer range extension not available."));
return false;
}
return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
}
} // namespace gl } // namespace gl
...@@ -168,6 +168,19 @@ bool ValidateCompressedTexSubImage2D(Context *context, ...@@ -168,6 +168,19 @@ bool ValidateCompressedTexSubImage2D(Context *context,
GLsizei imageSize, GLsizei imageSize,
const GLvoid *data); const GLvoid *data);
bool ValidateGetBufferPointervOES(Context *context, GLenum target, GLenum pname, void **params);
bool ValidateMapBufferOES(Context *context, GLenum target, GLenum access);
bool ValidateUnmapBufferOES(Context *context, GLenum target);
bool ValidateMapBufferRangeEXT(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
bool ValidateFlushMappedBufferRangeEXT(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length);
} // namespace gl } // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_ #endif // LIBANGLE_VALIDATION_ES2_H_
...@@ -2009,4 +2009,55 @@ bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, G ...@@ -2009,4 +2009,55 @@ bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, G
return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param)); return ValidateSamplerParameteri(context, sampler, pname, static_cast<GLint>(param));
} }
bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
return false;
}
return ValidateGetBufferPointervBase(context, target, pname, params);
}
bool ValidateUnmapBuffer(Context *context, GLenum target)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
return ValidateUnmapBufferBase(context, target);
}
bool ValidateMapBufferRange(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
return false;
}
return ValidateMapBufferRangeBase(context, target, offset, length, access);
}
bool ValidateFlushMappedBufferRange(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
return false;
}
return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
}
} // namespace gl } // namespace gl
...@@ -294,6 +294,18 @@ bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode); ...@@ -294,6 +294,18 @@ bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode);
bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param); bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param);
bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param); bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param);
bool ValidateGetBufferPointerv(Context *context, GLenum target, GLenum pname, GLvoid **params);
bool ValidateUnmapBuffer(Context *context, GLenum target);
bool ValidateMapBufferRange(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
bool ValidateFlushMappedBufferRange(Context *context,
GLenum target,
GLintptr offset,
GLsizeiptr length);
} // namespace gl } // namespace gl
#endif // LIBANGLE_VALIDATION_ES3_H_ #endif // LIBANGLE_VALIDATION_ES3_H_
...@@ -826,28 +826,13 @@ void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void** params ...@@ -826,28 +826,13 @@ void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void** params
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidBufferTarget(context, target)) if (!context->skipValidation() &&
{ !ValidateGetBufferPointervOES(context, target, pname, params))
context->recordError(Error(GL_INVALID_ENUM));
return;
}
if (pname != GL_BUFFER_MAP_POINTER)
{ {
context->recordError(Error(GL_INVALID_ENUM));
return; return;
} }
Buffer *buffer = context->getState().getTargetBuffer(target); context->getBufferPointerv(target, pname, params);
if (!buffer || !buffer->isMapped())
{
*params = NULL;
}
else
{
*params = buffer->getMapPointer();
}
} }
} }
...@@ -858,43 +843,15 @@ void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access) ...@@ -858,43 +843,15 @@ void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidBufferTarget(context, target)) if (!context->skipValidation() && !ValidateMapBufferOES(context, target, access))
{ {
context->recordError(Error(GL_INVALID_ENUM)); return nullptr;
return NULL;
} }
Buffer *buffer = context->getState().getTargetBuffer(target); return context->mapBuffer(target, access);
if (buffer == NULL)
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
if (access != GL_WRITE_ONLY_OES)
{
context->recordError(Error(GL_INVALID_ENUM));
return NULL;
}
if (buffer->isMapped())
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
Error error = buffer->map(access);
if (error.isError())
{
context->recordError(error);
return NULL;
}
return buffer->getMapPointer();
} }
return NULL; return nullptr;
} }
GLboolean GL_APIENTRY UnmapBufferOES(GLenum target) GLboolean GL_APIENTRY UnmapBufferOES(GLenum target)
...@@ -904,29 +861,12 @@ GLboolean GL_APIENTRY UnmapBufferOES(GLenum target) ...@@ -904,29 +861,12 @@ GLboolean GL_APIENTRY UnmapBufferOES(GLenum target)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidBufferTarget(context, target)) if (!context->skipValidation() && !ValidateUnmapBufferOES(context, target))
{
context->recordError(Error(GL_INVALID_ENUM));
return GL_FALSE;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (buffer == NULL || !buffer->isMapped())
{
context->recordError(Error(GL_INVALID_OPERATION));
return GL_FALSE;
}
GLboolean result;
Error error = buffer->unmap(&result);
if (error.isError())
{ {
context->recordError(error);
return GL_FALSE; return GL_FALSE;
} }
return result; return context->unmapBuffer(target);
} }
return GL_FALSE; return GL_FALSE;
...@@ -940,91 +880,16 @@ void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr l ...@@ -940,91 +880,16 @@ void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr l
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidBufferTarget(context, target)) if (!context->skipValidation() &&
{ !ValidateMapBufferRangeEXT(context, target, offset, length, access))
context->recordError(Error(GL_INVALID_ENUM));
return NULL;
}
if (offset < 0 || length < 0)
{
context->recordError(Error(GL_INVALID_VALUE));
return NULL;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (buffer == NULL)
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
// Check for buffer overflow
size_t offsetSize = static_cast<size_t>(offset);
size_t lengthSize = static_cast<size_t>(length);
if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
{
context->recordError(Error(GL_INVALID_VALUE));
return NULL;
}
// Check for invalid bits in the mask
GLbitfield allAccessBits = GL_MAP_READ_BIT |
GL_MAP_WRITE_BIT |
GL_MAP_INVALIDATE_RANGE_BIT |
GL_MAP_INVALIDATE_BUFFER_BIT |
GL_MAP_FLUSH_EXPLICIT_BIT |
GL_MAP_UNSYNCHRONIZED_BIT;
if (access & ~(allAccessBits))
{
context->recordError(Error(GL_INVALID_VALUE));
return NULL;
}
if (length == 0 || buffer->isMapped())
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
// Check for invalid bit combinations
if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT |
GL_MAP_INVALIDATE_BUFFER_BIT |
GL_MAP_UNSYNCHRONIZED_BIT;
if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
return NULL;
}
Error error = buffer->mapRange(offset, length, access);
if (error.isError())
{ {
context->recordError(error); return nullptr;
return NULL;
} }
return buffer->getMapPointer(); return context->mapBufferRange(target, offset, length, access);
} }
return NULL; return nullptr;
} }
void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length)
...@@ -1034,44 +899,13 @@ void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsiz ...@@ -1034,44 +899,13 @@ void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsiz
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (offset < 0 || length < 0) if (!context->skipValidation() &&
{ !ValidateFlushMappedBufferRangeEXT(context, target, offset, length))
context->recordError(Error(GL_INVALID_VALUE));
return;
}
if (!ValidBufferTarget(context, target))
{
context->recordError(Error(GL_INVALID_ENUM));
return;
}
Buffer *buffer = context->getState().getTargetBuffer(target);
if (buffer == NULL)
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
// Check for buffer overflow
size_t offsetSize = static_cast<size_t>(offset);
size_t lengthSize = static_cast<size_t>(length);
if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
{ {
context->recordError(Error(GL_INVALID_VALUE));
return; return;
} }
// We do not currently support a non-trivial implementation of FlushMappedBufferRange context->flushMappedBufferRange(target, offset, length);
} }
} }
......
...@@ -325,13 +325,12 @@ GLboolean GL_APIENTRY UnmapBuffer(GLenum target) ...@@ -325,13 +325,12 @@ GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!context->skipValidation() && !ValidateUnmapBuffer(context, target))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return GL_FALSE; return GL_FALSE;
} }
return UnmapBufferOES(target); return context->unmapBuffer(target);
} }
return GL_FALSE; return GL_FALSE;
...@@ -344,13 +343,13 @@ void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) ...@@ -344,13 +343,13 @@ void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!context->skipValidation() &&
!ValidateGetBufferPointerv(context, target, pname, params))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
GetBufferPointervOES(target, pname, params); context->getBufferPointerv(target, pname, params);
} }
} }
...@@ -547,16 +546,16 @@ GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr le ...@@ -547,16 +546,16 @@ GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr le
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!context->skipValidation() &&
!ValidateMapBufferRange(context, target, offset, length, access))
{ {
context->recordError(Error(GL_INVALID_OPERATION)); return nullptr;
return NULL;
} }
return MapBufferRangeEXT(target, offset, length, access); return context->mapBufferRange(target, offset, length, access);
} }
return NULL; return nullptr;
} }
void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
...@@ -566,13 +565,13 @@ void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeip ...@@ -566,13 +565,13 @@ void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeip
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!context->skipValidation() &&
!ValidateFlushMappedBufferRange(context, target, offset, length))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
FlushMappedBufferRangeEXT(target, offset, length); context->flushMappedBufferRange(target, offset, length);
} }
} }
......
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
1101 WIN LINUX : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements = FAIL 1101 WIN LINUX : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements = FAIL
1101 WIN LINUX : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements_invalid_program = FAIL 1101 WIN LINUX : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements_invalid_program = FAIL
1101 WIN LINUX : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements_incomplete_primitive = FAIL 1101 WIN LINUX : dEQP-GLES3.functional.negative_api.vertex_array.draw_range_elements_incomplete_primitive = FAIL
1101 WIN LINUX : dEQP-GLES3.functional.negative_api.state.get_buffer_pointerv = FAIL
1093 WIN LINUX : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.scalar = FAIL 1093 WIN LINUX : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.scalar = FAIL
1093 WIN LINUX : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec2 = FAIL 1093 WIN LINUX : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec2 = FAIL
1093 WIN LINUX : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec3 = FAIL 1093 WIN LINUX : dEQP-GLES3.functional.shaders.builtin_functions.precision.tanh.highp_vertex.vec3 = FAIL
......
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