Edit

kc3-lang/angle/src/libANGLE/validationES31.cpp

Branch :

  • Show log

    Commit

  • Author : Jiajia Qin
    Date : 2016-11-29 16:30:31
    Hash : d9671226
    Message : Implement ES3.1 glDraw*Indirect entry points for OpenGL BUG=angleproject:1595 TEST=dEQP-GLES31.functional.draw_indirect.* Change-Id: I82f5d0864e70d6e7abdccf5f10330ddfa099ec62 Reviewed-on: https://chromium-review.googlesource.com/417250 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>

  • src/libANGLE/validationES31.cpp
  • //
    // 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/validationES31.h"
    
    #include "libANGLE/Context.h"
    #include "libANGLE/validationES.h"
    #include "libANGLE/validationES3.h"
    #include "libANGLE/VertexArray.h"
    
    using namespace angle;
    
    namespace gl
    {
    
    bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
    {
        if (context->getClientVersion() < ES_3_1)
        {
            context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
            return false;
        }
    
        if (!ValidateIndexedStateQuery(context, target, index, nullptr))
        {
            return false;
        }
    
        return true;
    }
    
    bool ValidateGetBooleani_vRobustANGLE(Context *context,
                                          GLenum target,
                                          GLuint index,
                                          GLsizei bufSize,
                                          GLsizei *length,
                                          GLboolean *data)
    {
        if (context->getClientVersion() < ES_3_1)
        {
            context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
            return false;
        }
    
        if (!ValidateRobustEntryPoint(context, bufSize))
        {
            return false;
        }
    
        if (!ValidateIndexedStateQuery(context, target, index, length))
        {
            return false;
        }
    
        if (!ValidateRobustBufferSize(context, bufSize, *length))
        {
            return false;
        }
    
        return true;
    }
    
    bool ValidateDrawIndirectBase(Context *context, GLenum mode, const GLvoid *indirect)
    {
        if (context->getClientVersion() < ES_3_1)
        {
            context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
            return false;
        }
    
        // Here the third parameter 1 is only to pass the count validation.
        if (!ValidateDrawBase(context, mode, 1))
        {
            return false;
        }
    
        const State &state = context->getGLState();
    
        // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
        // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
        if (!state.getVertexArrayId())
        {
            context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to VERTEX_ARRAY_BINDING"));
            return false;
        }
    
        gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
        if (!drawIndirectBuffer)
        {
            context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to DRAW_INDIRECT_BUFFER"));
            return false;
        }
    
        // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
        // machine units, of uint.
        GLint64 offset = reinterpret_cast<GLint64>(indirect);
        if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
        {
            context->handleError(
                Error(GL_INVALID_VALUE,
                      "indirect is not a multiple of the size, in basic machine units, of uint"));
            return false;
        }
    
        return true;
    }
    
    bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const GLvoid *indirect)
    {
        const State &state                          = context->getGLState();
        gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
        if (curTransformFeedback && curTransformFeedback->isActive() &&
            !curTransformFeedback->isPaused())
        {
            // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
            context->handleError(
                Error(GL_INVALID_OPERATION, "transform feedback is active and not paused."));
            return false;
        }
    
        if (!ValidateDrawIndirectBase(context, mode, indirect))
            return false;
    
        gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
        // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
        // which's size is 4 * sizeof(uint).
        auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
        if (!checkedSum.IsValid() ||
            checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
        {
            context->handleError(
                Error(GL_INVALID_OPERATION,
                      "the  command  would source data beyond the end of the buffer object."));
            return false;
        }
    
        return true;
    }
    
    bool ValidateDrawElementsIndirect(Context *context,
                                      GLenum mode,
                                      GLenum type,
                                      const GLvoid *indirect)
    {
        if (!ValidateDrawElementsBase(context, type))
            return false;
    
        const State &state             = context->getGLState();
        const VertexArray *vao         = state.getVertexArray();
        gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
        if (!elementArrayBuffer)
        {
            context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to ELEMENT_ARRAY_BUFFER"));
            return false;
        }
    
        if (!ValidateDrawIndirectBase(context, mode, indirect))
            return false;
    
        gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
        // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
        // which's size is 5 * sizeof(uint).
        auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
        if (!checkedSum.IsValid() ||
            checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
        {
            context->handleError(
                Error(GL_INVALID_OPERATION,
                      "the  command  would source data beyond the end of the buffer object."));
            return false;
        }
    
        return true;
    }
    
    }  // namespace gl