diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp index b102bb543..b22dabe52 100644 --- a/src/libANGLE/Context.cpp +++ b/src/libANGLE/Context.cpp @@ -630,11 +630,14 @@ GLuint Context::createFramebuffer() return mState.mFramebuffers->createFramebuffer(); } -GLuint Context::createFenceNV() +void Context::genFencesNV(GLsizei n, GLuint *fences) { - GLuint handle = mFenceNVHandleAllocator.allocate(); - mFenceNVMap.assign(handle, new FenceNV(mImplementation->createFenceNV())); - return handle; + for (int i = 0; i < n; i++) + { + GLuint handle = mFenceNVHandleAllocator.allocate(); + mFenceNVMap.assign(handle, new FenceNV(mImplementation->createFenceNV())); + fences[i] = handle; + } } GLuint Context::createProgramPipeline() @@ -807,13 +810,18 @@ void Context::deleteFramebuffer(GLuint framebuffer) mState.mFramebuffers->deleteObject(this, framebuffer); } -void Context::deleteFenceNV(GLuint fence) +void Context::deleteFencesNV(GLsizei n, const GLuint *fences) { - FenceNV *fenceObject = nullptr; - if (mFenceNVMap.erase(fence, &fenceObject)) + for (int i = 0; i < n; i++) { - mFenceNVHandleAllocator.release(fence); - delete fenceObject; + GLuint fence = fences[i]; + + FenceNV *fenceObject = nullptr; + if (mFenceNVMap.erase(fence, &fenceObject)) + { + mFenceNVHandleAllocator.release(fence); + delete fenceObject; + } } } @@ -5645,4 +5653,99 @@ GLboolean Context::isProgramPipeline(GLuint pipeline) return (getProgramPipeline(pipeline) ? GL_TRUE : GL_FALSE); } +void Context::finishFenceNV(GLuint fence) +{ + FenceNV *fenceObject = getFenceNV(fence); + + ASSERT(fenceObject && fenceObject->isSet()); + handleError(fenceObject->finish()); +} + +void Context::getFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + FenceNV *fenceObject = getFenceNV(fence); + + ASSERT(fenceObject && fenceObject->isSet()); + + switch (pname) + { + case GL_FENCE_STATUS_NV: + { + // GL_NV_fence spec: + // Once the status of a fence has been finished (via FinishFenceNV) or tested and + // the returned status is TRUE (via either TestFenceNV or GetFenceivNV querying the + // FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. + GLboolean status = GL_TRUE; + if (fenceObject->getStatus() != GL_TRUE) + { + ANGLE_CONTEXT_TRY(fenceObject->test(&status)); + } + *params = status; + break; + } + + case GL_FENCE_CONDITION_NV: + { + *params = static_cast(fenceObject->getCondition()); + break; + } + + default: + UNREACHABLE(); + } +} + +void Context::getTranslatedShaderSource(GLuint shader, + GLsizei bufsize, + GLsizei *length, + GLchar *source) +{ + Shader *shaderObject = getShader(shader); + ASSERT(shaderObject); + shaderObject->getTranslatedSourceWithDebugInfo(this, bufsize, length, source); +} + +void Context::getnUniformfv(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) +{ + Program *programObject = getProgram(program); + ASSERT(programObject); + + programObject->getUniformfv(this, location, params); +} + +void Context::getnUniformiv(GLuint program, GLint location, GLsizei bufSize, GLint *params) +{ + Program *programObject = getProgram(program); + ASSERT(programObject); + + programObject->getUniformiv(this, location, params); +} + +GLboolean Context::isFenceNV(GLuint fence) +{ + FenceNV *fenceObject = getFenceNV(fence); + + if (fenceObject == nullptr) + { + return GL_FALSE; + } + + // GL_NV_fence spec: + // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an + // existing fence. + return fenceObject->isSet(); +} + +void Context::readnPixels(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufSize, + void *data) +{ + return readPixels(x, y, width, height, format, type, data); +} + } // namespace gl diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h index 7aef48d61..b383faccc 100644 --- a/src/libANGLE/Context.h +++ b/src/libANGLE/Context.h @@ -115,8 +115,11 @@ class Context final : public ValidationContext void deleteFramebuffer(GLuint framebuffer); // NV Fences are owned by the Context. - GLuint createFenceNV(); - void deleteFenceNV(GLuint fence); + void genFencesNV(GLsizei n, GLuint *fences); + void deleteFencesNV(GLsizei n, const GLuint *fences); + void finishFenceNV(GLuint fence); + void getFenceivNV(GLuint fence, GLenum pname, GLint *params); + GLboolean isFenceNV(GLuint fence); void bindTexture(GLenum target, GLuint handle); void bindReadFramebuffer(GLuint framebufferHandle); @@ -965,6 +968,18 @@ class Context final : public ValidationContext void genProgramPipelines(GLsizei n, GLuint *pipelines); GLboolean isProgramPipeline(GLuint pipeline); + void getTranslatedShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); + void getnUniformfv(GLuint program, GLint location, GLsizei bufSize, GLfloat *params); + void getnUniformiv(GLuint program, GLint location, GLsizei bufSize, GLint *params); + void readnPixels(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufSize, + void *data); + // Consumes the error. void handleError(const Error &error) override; diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h index bf71b9932..78023e594 100644 --- a/src/libANGLE/ErrorStrings.h +++ b/src/libANGLE/ErrorStrings.h @@ -67,6 +67,8 @@ ERRMSG(InvalidDepthRange, "Near value cannot be greater than far."); ERRMSG(InvalidDrawMode, "Invalid draw mode."); ERRMSG(InvalidDrawModeTransformFeedback, "Draw mode must match current transform feedback object's draw mode."); +ERRMSG(InvalidFence, "Invalid fence object."); +ERRMSG(InvalidFenceState, "Fence must be set."); ERRMSG(InvalidFillMode, "Invalid fill mode."); ERRMSG(InvalidFilterTexture, "Texture only supports NEAREST and LINEAR filtering."); ERRMSG(InvalidFormat, "Invalid format."); @@ -135,6 +137,7 @@ ERRMSG(NoSuchPath, "No such path object."); ERRMSG(NoTransformFeedbackOutputVariables, "The active program has specified no output variables to record."); ERRMSG(NoZeroDivisor, "At least one enabled attribute must have a divisor of zero."); +ERRMSG(NVFenceNotSupported, "GL_NV_fence is not supported"); ERRMSG(ObjectNotGenerated, "Object cannot be used because it has not been generated."); ERRMSG(OffsetMustBeMultipleOfType, "Offset must be a multiple of the passed in datatype."); ERRMSG(OffsetMustBeMultipleOfUint, diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp index 001c91add..362b9dac2 100644 --- a/src/libANGLE/validationES2.cpp +++ b/src/libANGLE/validationES2.cpp @@ -15,6 +15,7 @@ #include "common/utilities.h" #include "libANGLE/Context.h" #include "libANGLE/ErrorStrings.h" +#include "libANGLE/Fence.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Renderbuffer.h" @@ -6348,4 +6349,150 @@ bool ValidateUseProgram(Context *context, GLuint program) return true; } +bool ValidateDeleteFencesNV(Context *context, GLsizei n, const GLuint *fences) +{ + if (!context->getExtensions().fence) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), NVFenceNotSupported); + return false; + } + + if (n < 0) + { + ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount); + return false; + } + + return true; +} + +bool ValidateFinishFenceNV(Context *context, GLuint fence) +{ + if (!context->getExtensions().fence) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), NVFenceNotSupported); + return false; + } + + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == nullptr) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFence); + return false; + } + + if (!fenceObject->isSet()) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFenceState); + return false; + } + + return true; +} + +bool ValidateGenFencesNV(Context *context, GLsizei n, GLuint *fences) +{ + if (!context->getExtensions().fence) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), NVFenceNotSupported); + return false; + } + + if (n < 0) + { + ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount); + return false; + } + + return true; +} + +bool ValidateGetFenceivNV(Context *context, GLuint fence, GLenum pname, GLint *params) +{ + if (!context->getExtensions().fence) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), NVFenceNotSupported); + return false; + } + + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == nullptr) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFence); + return false; + } + + if (!fenceObject->isSet()) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFenceState); + return false; + } + + switch (pname) + { + case GL_FENCE_STATUS_NV: + case GL_FENCE_CONDITION_NV: + break; + + default: + ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname); + return false; + } + + return true; +} + +bool ValidateGetGraphicsResetStatusEXT(Context *context) +{ + if (!context->getExtensions().robustness) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled); + return false; + } + + return true; +} + +bool ValidateGetTranslatedShaderSourceANGLE(Context *context, + GLuint shader, + GLsizei bufsize, + GLsizei *length, + GLchar *source) +{ + if (!context->getExtensions().translatedShaderSource) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled); + return false; + } + + if (bufsize < 0) + { + context->handleError(InvalidValue()); + return false; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->handleError(InvalidOperation()); + return false; + } + + return true; +} + +bool ValidateIsFenceNV(Context *context, GLuint fence) +{ + if (!context->getExtensions().fence) + { + ANGLE_VALIDATION_ERR(context, InvalidOperation(), NVFenceNotSupported); + return false; + } + + return true; +} + } // namespace gl diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h index af995aee1..6a02af32d 100644 --- a/src/libANGLE/validationES2.h +++ b/src/libANGLE/validationES2.h @@ -682,6 +682,19 @@ bool ValidateUniform1iv(ValidationContext *context, const GLint *value); bool ValidateUseProgram(Context *context, GLuint program); +// Extension validation +bool ValidateDeleteFencesNV(Context *context, GLsizei n, const GLuint *fences); +bool ValidateFinishFenceNV(Context *context, GLuint fence); +bool ValidateGenFencesNV(Context *context, GLsizei n, GLuint *fences); +bool ValidateGetFenceivNV(Context *context, GLuint fence, GLenum pname, GLint *params); +bool ValidateGetGraphicsResetStatusEXT(Context *context); +bool ValidateGetTranslatedShaderSourceANGLE(Context *context, + GLuint shader, + GLsizei bufsize, + GLsizei *length, + GLchar *source); +bool ValidateIsFenceNV(Context *context, GLuint fence); + } // namespace gl #endif // LIBANGLE_VALIDATION_ES2_H_ diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp index ed55e6495..122052f76 100644 --- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp +++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp @@ -152,7 +152,7 @@ void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params) Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetQueryivEXT(context, target, pname, params)) + if (!context->skipValidation() && !ValidateGetQueryivEXT(context, target, pname, params)) { return; } @@ -168,7 +168,7 @@ void GL_APIENTRY GetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params) Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetQueryObjectivEXT(context, id, pname, params)) + if (!context->skipValidation() && !ValidateGetQueryObjectivEXT(context, id, pname, params)) { return; } @@ -184,7 +184,7 @@ void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetQueryObjectuivEXT(context, id, pname, params)) + if (!context->skipValidation() && !ValidateGetQueryObjectuivEXT(context, id, pname, params)) { return; } @@ -200,7 +200,8 @@ void GL_APIENTRY GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 *params) Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetQueryObjecti64vEXT(context, id, pname, params)) + if (!context->skipValidation() && + !ValidateGetQueryObjecti64vEXT(context, id, pname, params)) { return; } @@ -216,7 +217,8 @@ void GL_APIENTRY GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *param Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetQueryObjectui64vEXT(context, id, pname, params)) + if (!context->skipValidation() && + !ValidateGetQueryObjectui64vEXT(context, id, pname, params)) { return; } @@ -232,16 +234,12 @@ void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint *fences) Context *context = GetValidGlobalContext(); if (context) { - if (n < 0) + if (!context->skipValidation() && !ValidateDeleteFencesNV(context, n, fences)) { - context->handleError(InvalidValue()); return; } - for (int i = 0; i < n; i++) - { - context->deleteFenceNV(fences[i]); - } + context->deleteFencesNV(n, fences); } } @@ -256,7 +254,8 @@ void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) + if (!context->skipValidation() && + !ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) { return; } @@ -299,21 +298,12 @@ void GL_APIENTRY FinishFenceNV(GLuint fence) Context *context = GetValidGlobalContext(); if (context) { - FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == nullptr) + if (!context->skipValidation() && !ValidateFinishFenceNV(context, fence)) { - context->handleError(InvalidOperation()); return; } - if (fenceObject->isSet() != GL_TRUE) - { - context->handleError(InvalidOperation()); - return; - } - - context->handleError(fenceObject->finish()); + context->finishFenceNV(fence); } } @@ -324,16 +314,12 @@ void GL_APIENTRY GenFencesNV(GLsizei n, GLuint *fences) Context *context = GetValidGlobalContext(); if (context) { - if (n < 0) + if (!context->skipValidation() && !ValidateGenFencesNV(context, n, fences)) { - context->handleError(InvalidValue()); return; } - for (int i = 0; i < n; i++) - { - fences[i] = context->createFenceNV(); - } + context->genFencesNV(n, fences); } } @@ -345,58 +331,16 @@ void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params) Context *context = GetValidGlobalContext(); if (context) { - FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == nullptr) + if (!context->skipValidation() && !ValidateGetFenceivNV(context, fence, pname, params)) { - context->handleError(InvalidOperation()); return; } - if (fenceObject->isSet() != GL_TRUE) - { - context->handleError(InvalidOperation()); - return; - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and - // the returned status is TRUE (via either TestFenceNV or GetFenceivNV querying the - // FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - GLboolean status = GL_TRUE; - if (fenceObject->getStatus() != GL_TRUE) - { - Error error = fenceObject->test(&status); - if (error.isError()) - { - context->handleError(error); - return; - } - } - *params = status; - break; - } - - case GL_FENCE_CONDITION_NV: - { - *params = static_cast(fenceObject->getCondition()); - break; - } - - default: - { - context->handleError(InvalidEnum()); - return; - } - } + context->getFenceivNV(fence, pname, params); } } -GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void) +GLenum GL_APIENTRY GetGraphicsResetStatusEXT() { EVENT("()"); @@ -404,6 +348,11 @@ GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void) if (context) { + if (!context->skipValidation() && !ValidateGetGraphicsResetStatusEXT(context)) + { + return GL_NO_ERROR; + } + return context->getResetStatus(); } @@ -423,21 +372,13 @@ void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, Context *context = GetValidGlobalContext(); if (context) { - if (bufsize < 0) + if (!context->skipValidation() && + !ValidateGetTranslatedShaderSourceANGLE(context, shader, bufsize, length, source)) { - context->handleError(InvalidValue()); return; } - Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->handleError(InvalidOperation()); - return; - } - - shaderObject->getTranslatedSourceWithDebugInfo(context, bufsize, length, source); + context->getTranslatedShaderSource(shader, bufsize, length, source); } } @@ -451,15 +392,13 @@ void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) + if (!context->skipValidation() && + !ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) { return; } - Program *programObject = context->getProgram(program); - ASSERT(programObject); - - programObject->getUniformfv(context, location, params); + context->getnUniformfv(program, location, bufSize, params); } } @@ -472,15 +411,13 @@ void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) + if (!context->skipValidation() && + !ValidateGetnUniformivEXT(context, program, location, bufSize, params)) { return; } - Program *programObject = context->getProgram(program); - ASSERT(programObject); - - programObject->getUniformiv(context, location, params); + context->getnUniformiv(program, location, bufSize, params); } } @@ -491,17 +428,12 @@ GLboolean GL_APIENTRY IsFenceNV(GLuint fence) Context *context = GetValidGlobalContext(); if (context) { - FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == nullptr) + if (!context->skipValidation() && !ValidateIsFenceNV(context, fence)) { return GL_FALSE; } - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an - // existing fence. - return fenceObject->isSet(); + return context->isFenceNV(fence); } return GL_FALSE; @@ -530,7 +462,7 @@ void GL_APIENTRY ReadnPixelsEXT(GLint x, return; } - context->readPixels(x, y, width, height, format, type, data); + context->readnPixels(x, y, width, height, format, type, bufSize, data); } }