9262bee5创建于 28 天前历史提交
//
// Copyright 2018 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.
//
// validationES2.h:
//  Inlined validation functions for OpenGL ES 2.0 entry points.

#ifndef LIBANGLE_VALIDATION_ES2_H_
#define LIBANGLE_VALIDATION_ES2_H_

#include "libANGLE/ErrorStrings.h"
#include "libANGLE/validationES.h"
#include "libANGLE/validationES2_autogen.h"

namespace gl
{

void RecordVersionErrorES20(const Context *context, angle::EntryPoint entryPoint);

ANGLE_INLINE bool ValidateDrawArrays(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     PrimitiveMode mode,
                                     GLint first,
                                     GLsizei count)
{
    if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, 1))
    {
        return false;
    }

    if (!ValidateDrawArraysTransformFeedbackBufferSize(context, entryPoint, &count, nullptr, 1))
    {
        return false;
    }

    return true;
}

ANGLE_INLINE bool ValidateUniform1f(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLfloat x)
{
    return ValidateUniform(context, entryPoint, GL_FLOAT, location, 1);
}

ANGLE_INLINE bool ValidateUniform1fv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLfloat *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_FLOAT, location, count);
}

ANGLE_INLINE bool ValidateUniform1i(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLint x)
{
    return ValidateUniform1iv(context, entryPoint, location, 1, &x);
}

ANGLE_INLINE bool ValidateUniform2f(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLfloat x,
                                    GLfloat y)
{
    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, 1);
}

ANGLE_INLINE bool ValidateUniform2fv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLfloat *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, count);
}

ANGLE_INLINE bool ValidateUniform2i(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLint x,
                                    GLint y)
{
    return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, 1);
}

ANGLE_INLINE bool ValidateUniform2iv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLint *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, count);
}

ANGLE_INLINE bool ValidateUniform3f(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLfloat x,
                                    GLfloat y,
                                    GLfloat z)
{
    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, 1);
}

ANGLE_INLINE bool ValidateUniform3fv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLfloat *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, count);
}

ANGLE_INLINE bool ValidateUniform3i(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLint x,
                                    GLint y,
                                    GLint z)
{
    return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, 1);
}

ANGLE_INLINE bool ValidateUniform3iv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLint *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, count);
}

ANGLE_INLINE bool ValidateUniform4f(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLfloat x,
                                    GLfloat y,
                                    GLfloat z,
                                    GLfloat w)
{
    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, 1);
}

ANGLE_INLINE bool ValidateUniform4fv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLfloat *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, count);
}

ANGLE_INLINE bool ValidateUniform4i(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    UniformLocation location,
                                    GLint x,
                                    GLint y,
                                    GLint z,
                                    GLint w)
{
    return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, 1);
}

ANGLE_INLINE bool ValidateUniform4iv(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     UniformLocation location,
                                     GLsizei count,
                                     const GLint *v)
{
    if (!ValidateUniformValuePointer(context, entryPoint, v))
    {
        // Error already generated.
        return false;
    }

    return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, count);
}

ANGLE_INLINE bool ValidateUniformMatrix2fv(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           UniformLocation location,
                                           GLsizei count,
                                           GLboolean transpose,
                                           const GLfloat *value)
{
    return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT2, location, count, transpose);
}

ANGLE_INLINE bool ValidateUniformMatrix3fv(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           UniformLocation location,
                                           GLsizei count,
                                           GLboolean transpose,
                                           const GLfloat *value)
{
    return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT3, location, count, transpose);
}

ANGLE_INLINE bool ValidateUniformMatrix4fv(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           UniformLocation location,
                                           GLsizei count,
                                           GLboolean transpose,
                                           const GLfloat *value)
{
    return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT4, location, count, transpose);
}

ANGLE_INLINE bool ValidateVertexAttrib1f(const PrivateState &state,
                                         ErrorSet *errors,
                                         angle::EntryPoint entryPoint,
                                         GLuint index,
                                         GLfloat x)
{
    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib1fv(const PrivateState &state,
                                          ErrorSet *errors,
                                          angle::EntryPoint entryPoint,
                                          GLuint index,
                                          const GLfloat *values)
{
    if (values == nullptr)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL);
        return false;
    }

    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib2f(const PrivateState &state,
                                         ErrorSet *errors,
                                         angle::EntryPoint entryPoint,
                                         GLuint index,
                                         GLfloat x,
                                         GLfloat y)
{
    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib2fv(const PrivateState &state,
                                          ErrorSet *errors,
                                          angle::EntryPoint entryPoint,
                                          GLuint index,
                                          const GLfloat *values)
{
    if (values == nullptr)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL);
        return false;
    }

    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib3f(const PrivateState &state,
                                         ErrorSet *errors,
                                         angle::EntryPoint entryPoint,
                                         GLuint index,
                                         GLfloat x,
                                         GLfloat y,
                                         GLfloat z)
{
    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib3fv(const PrivateState &state,
                                          ErrorSet *errors,
                                          angle::EntryPoint entryPoint,
                                          GLuint index,
                                          const GLfloat *values)
{
    if (values == nullptr)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL);
        return false;
    }

    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib4f(const PrivateState &state,
                                         ErrorSet *errors,
                                         angle::EntryPoint entryPoint,
                                         GLuint index,
                                         GLfloat x,
                                         GLfloat y,
                                         GLfloat z,
                                         GLfloat w)
{
    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateVertexAttrib4fv(const PrivateState &state,
                                          ErrorSet *errors,
                                          angle::EntryPoint entryPoint,
                                          GLuint index,
                                          const GLfloat *values)
{
    if (values == nullptr)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, err::kVertexAttributeValueNULL);
        return false;
    }

    return ValidateVertexAttribIndex(state, errors, entryPoint, index);
}

ANGLE_INLINE bool ValidateGenBuffers(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLint n,
                                     const BufferID *buffers)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, buffers);
}

ANGLE_INLINE bool ValidateGenFramebuffers(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          GLint n,
                                          const FramebufferID *framebuffers)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n,
                               framebuffers);
}

ANGLE_INLINE bool ValidateGenRenderbuffers(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           GLint n,
                                           const RenderbufferID *renderbuffers)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n,
                               renderbuffers);
}

ANGLE_INLINE bool ValidateGenTextures(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      GLint n,
                                      const TextureID *textures)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, textures);
}

ANGLE_INLINE bool ValidateGenerateMipmap(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target)
{
    return ValidateGenerateMipmapBase(context, entryPoint, target);
}

ANGLE_INLINE bool ValidateGetBufferParameteriv(const Context *context,
                                               angle::EntryPoint entryPoint,
                                               BufferBinding target,
                                               GLenum pname,
                                               const GLint *params)
{
    return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
}

ANGLE_INLINE bool ValidateGetRenderbufferParameteriv(const Context *context,
                                                     angle::EntryPoint entryPoint,
                                                     GLenum target,
                                                     GLenum pname,
                                                     const GLint *params)
{
    return ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, nullptr);
}

ANGLE_INLINE bool ValidateGetShaderiv(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      ShaderProgramID shader,
                                      GLenum pname,
                                      const GLint *params)
{
    if (params == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kPLSParamsNULL);
        return false;
    }

    return ValidateGetShaderivBase(context, entryPoint, shader, pname, nullptr);
}

ANGLE_INLINE bool ValidateGetTexParameterfv(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            TextureType target,
                                            GLenum pname,
                                            const GLfloat *params)
{
    return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
}

ANGLE_INLINE bool ValidateGetTexParameteriv(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            TextureType target,
                                            GLenum pname,
                                            const GLint *params)
{
    return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
}

ANGLE_INLINE bool ValidateGetUniformfv(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       ShaderProgramID program,
                                       UniformLocation location,
                                       const GLfloat *params)
{
    return ValidateGetUniformBase(context, entryPoint, program, location);
}

ANGLE_INLINE bool ValidateGetUniformiv(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       ShaderProgramID program,
                                       UniformLocation location,
                                       const GLint *params)
{
    return ValidateGetUniformBase(context, entryPoint, program, location);
}

ANGLE_INLINE bool ValidateGetVertexAttribfv(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            GLuint index,
                                            GLenum pname,
                                            const GLfloat *params)
{
    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false);
}

ANGLE_INLINE bool ValidateGetVertexAttribiv(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            GLuint index,
                                            GLenum pname,
                                            const GLint *params)
{
    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false);
}

ANGLE_INLINE bool ValidateGetVertexAttribPointerv(const Context *context,
                                                  angle::EntryPoint entryPoint,
                                                  GLuint index,
                                                  GLenum pname,
                                                  void *const *pointer)
{
    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, true);
}

ANGLE_INLINE bool ValidateReadPixels(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLint x,
                                     GLint y,
                                     GLsizei width,
                                     GLsizei height,
                                     GLenum format,
                                     GLenum type,
                                     const void *pixels)
{
    return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, -1,
                                  nullptr, nullptr, nullptr, pixels);
}

ANGLE_INLINE bool ValidateTexParameterf(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        TextureType target,
                                        GLenum pname,
                                        GLfloat param)
{
    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, &param);
}

ANGLE_INLINE bool ValidateTexParameterfv(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target,
                                         GLenum pname,
                                         const GLfloat *params)
{
    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
}

ANGLE_INLINE bool ValidateTexParameteri(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        TextureType target,
                                        GLenum pname,
                                        GLint param)
{
    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, &param);
}

ANGLE_INLINE bool ValidateTexParameteriv(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target,
                                         GLenum pname,
                                         const GLint *params)
{
    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
}

ANGLE_INLINE bool ValidateBindBuffer(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     BufferBinding target,
                                     BufferID buffer)
{
    if (!context->isValidBufferBinding(target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kInvalidBufferTypes);
        return false;
    }

    if (!context->getState().isBindGeneratesResourceEnabled() &&
        !context->isBufferGenerated(buffer))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kObjectNotGenerated);
        return false;
    }

    return true;
}

ANGLE_INLINE bool ValidateDrawElements(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       PrimitiveMode mode,
                                       GLsizei count,
                                       DrawElementsType type,
                                       const void *indices)
{
    return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1);
}

ANGLE_INLINE bool ValidateVertexAttribPointer(const Context *context,
                                              angle::EntryPoint entryPoint,
                                              GLuint index,
                                              GLint size,
                                              VertexAttribType type,
                                              GLboolean normalized,
                                              GLsizei stride,
                                              const void *ptr)
{
    if (!ValidateFloatVertexFormat(context->getPrivateState(), context->getPrivateStateCache(),
                                   context->getMutableErrorSetForValidation(), entryPoint, index,
                                   size, type))
    {
        return false;
    }

    if (stride < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeStride);
        return false;
    }

    if (context->getClientVersion() >= ES_3_1)
    {
        const Caps &caps = context->getCaps();
        if (stride > caps.maxVertexAttribStride)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kExceedsMaxVertexAttribStride);
            return false;
        }

        if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kExceedsMaxVertexAttribBindings);
            return false;
        }
    }

    // [OpenGL ES 3.0.2] Section 2.8 page 24:
    // An INVALID_OPERATION error is generated when a non-zero vertex array object
    // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
    // and the pointer argument is not NULL.
    bool nullBufferAllowed = context->getState().areClientArraysEnabled() &&
                             context->getState().getVertexArray()->id().value == 0;
    if (!nullBufferAllowed && context->getState().getTargetBuffer(BufferBinding::Array) == 0 &&
        ptr != nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kClientDataInVertexArray);
        return false;
    }

    if (context->isWebGL())
    {
        // WebGL 1.0 [Section 6.14] Fixed point support
        // The WebGL API does not support the GL_FIXED data type.
        if (type == VertexAttribType::Fixed)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kFixedNotInWebGL);
            return false;
        }

        if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, normalized, stride, ptr,
                                              false))
        {
            return false;
        }
    }

    return true;
}

void RecordBindTextureTypeError(const Context *context,
                                angle::EntryPoint entryPoint,
                                TextureType target);

ANGLE_INLINE bool ValidateBindTexture(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      TextureType target,
                                      TextureID texture)
{
    if (!context->getStateCache().isValidBindTextureType(target))
    {
        RecordBindTextureTypeError(context, entryPoint, target);
        return false;
    }

    if (texture.value == 0)
    {
        return true;
    }

    Texture *textureObject = context->getTexture(texture);
    if (textureObject && textureObject->getType() != target)
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, err::kTextureTargetMismatchWithLabel,
                                static_cast<uint8_t>(target),
                                static_cast<uint8_t>(textureObject->getType()),
                                textureObject->getLabel().c_str());
        return false;
    }

    if (!context->getState().isBindGeneratesResourceEnabled() &&
        !context->isTextureGenerated(texture))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kObjectNotGenerated);
        return false;
    }

    return true;
}

// Validation of all Tex[Sub]Image2D parameters except TextureTarget.
bool ValidateES2TexImageParametersBase(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       TextureTarget target,
                                       GLint level,
                                       GLenum internalformat,
                                       bool isCompressed,
                                       bool isSubImage,
                                       GLint xoffset,
                                       GLint yoffset,
                                       GLsizei width,
                                       GLsizei height,
                                       GLint border,
                                       GLenum format,
                                       GLenum type,
                                       GLsizei imageSize,
                                       const void *pixels);

// Validation of TexStorage*2DEXT
bool ValidateES2TexStorageParametersBase(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target,
                                         GLsizei levels,
                                         GLenum internalformat,
                                         GLsizei width,
                                         GLsizei height);

// Validation of [Push,Pop]DebugGroup
bool ValidatePushDebugGroupBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLenum source,
                                GLuint id,
                                GLsizei length,
                                const GLchar *message);
bool ValidatePopDebugGroupBase(const Context *context, angle::EntryPoint entryPoint);

bool ValidateDebugMessageControlBase(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLenum source,
                                     GLenum type,
                                     GLenum severity,
                                     GLsizei count,
                                     const GLuint *ids);

bool ValidateDebugMessageInsertBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum source,
                                    GLenum type,
                                    GLuint id,
                                    GLenum severity,
                                    GLsizei length,
                                    const GLchar *buf);

bool ValidateGetDebugMessageLogBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLuint count,
                                    GLsizei bufSize,
                                    const GLenum *sources,
                                    const GLenum *types,
                                    const GLuint *ids,
                                    const GLenum *severities,
                                    const GLsizei *lengths,
                                    const GLchar *messageLog);

// Validation of ObjectLabel
bool ValidateObjectLabelBase(const Context *context,
                             angle::EntryPoint entryPoint,
                             GLenum identifier,
                             GLuint name,
                             GLsizei length,
                             const GLchar *label);

// Validation of GetObjectLabel
bool ValidateGetObjectLabelBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLenum identifier,
                                GLuint name,
                                GLsizei bufSize,
                                const GLsizei *length,
                                const GLchar *label);

// Validation of ObjectPtrLabel
bool ValidateObjectPtrLabelBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                const void *ptr,
                                GLsizei length,
                                const GLchar *label);

// Validation of GetObjectPtrLabel
bool ValidateGetObjectPtrLabelBase(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   const void *ptr,
                                   GLsizei bufSize,
                                   const GLsizei *length,
                                   const GLchar *label);

}  // namespace gl

#endif  // LIBANGLE_VALIDATION_ES2_H_