Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2017-06-05 12:59:21
    Hash : bd044ed8
    Message : Defer shader compiles when possible. When using the program binary memory cache inside ANGLE, this will give a potential fast path. If the user doesn't query the shader compile status or info log before calling LinkProgram, then we can check the program cache before translating the program, and if it finds a hit, we don't even need to call the translator. To preserve the shader settings at compile time, a reference to the current shader translator is kept in a binding pointer on the call to compile. This mirrors a similar implementation in Chromium's command buffer. Also the compile options and source are cached at compile to preserve the correct shader state. BUG=angleproject:1897 Change-Id: I3c046d7ac8c3b5c8cc169c4802ffe47f95537212 Reviewed-on: https://chromium-review.googlesource.com/517379 Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/queryutils.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.
    //
    
    // queryutils.cpp: Utilities for querying values from GL objects
    
    #include "libANGLE/queryutils.h"
    
    #include "common/utilities.h"
    
    #include "libANGLE/Buffer.h"
    #include "libANGLE/Config.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Fence.h"
    #include "libANGLE/Framebuffer.h"
    #include "libANGLE/Program.h"
    #include "libANGLE/Renderbuffer.h"
    #include "libANGLE/Sampler.h"
    #include "libANGLE/Shader.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/Uniform.h"
    #include "libANGLE/VertexAttribute.h"
    
    namespace gl
    {
    
    namespace
    {
    template <typename ParamType>
    void QueryTexLevelParameterBase(const Texture *texture,
                                    GLenum target,
                                    GLint level,
                                    GLenum pname,
                                    ParamType *params)
    {
        ASSERT(texture != nullptr);
        const InternalFormat *info = texture->getTextureState().getImageDesc(target, level).format.info;
    
        switch (pname)
        {
            case GL_TEXTURE_RED_TYPE:
                *params = ConvertFromGLenum<ParamType>(info->redBits ? info->componentType : GL_NONE);
                break;
            case GL_TEXTURE_GREEN_TYPE:
                *params = ConvertFromGLenum<ParamType>(info->greenBits ? info->componentType : GL_NONE);
                break;
            case GL_TEXTURE_BLUE_TYPE:
                *params = ConvertFromGLenum<ParamType>(info->blueBits ? info->componentType : GL_NONE);
                break;
            case GL_TEXTURE_ALPHA_TYPE:
                *params = ConvertFromGLenum<ParamType>(info->alphaBits ? info->componentType : GL_NONE);
                break;
            case GL_TEXTURE_DEPTH_TYPE:
                *params = ConvertFromGLenum<ParamType>(info->depthBits ? info->componentType : GL_NONE);
                break;
            case GL_TEXTURE_RED_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->redBits);
                break;
            case GL_TEXTURE_GREEN_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->greenBits);
                break;
            case GL_TEXTURE_BLUE_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->blueBits);
                break;
            case GL_TEXTURE_ALPHA_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->alphaBits);
                break;
            case GL_TEXTURE_DEPTH_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->depthBits);
                break;
            case GL_TEXTURE_STENCIL_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->stencilBits);
                break;
            case GL_TEXTURE_SHARED_SIZE:
                *params = ConvertFromGLuint<ParamType>(info->sharedBits);
                break;
            case GL_TEXTURE_INTERNAL_FORMAT:
                *params =
                    ConvertFromGLenum<ParamType>(info->internalFormat ? info->internalFormat : GL_RGBA);
                break;
            case GL_TEXTURE_WIDTH:
                *params =
                    ConvertFromGLint<ParamType>(static_cast<GLint>(texture->getWidth(target, level)));
                break;
            case GL_TEXTURE_HEIGHT:
                *params =
                    ConvertFromGLint<ParamType>(static_cast<GLint>(texture->getHeight(target, level)));
                break;
            case GL_TEXTURE_DEPTH:
                *params =
                    ConvertFromGLint<ParamType>(static_cast<GLint>(texture->getDepth(target, level)));
                break;
            case GL_TEXTURE_SAMPLES:
                *params = ConvertFromGLint<ParamType>(texture->getSamples(target, level));
                break;
            case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
                *params =
                    ConvertFromGLboolean<ParamType>(texture->getFixedSampleLocations(target, level));
                break;
            case GL_TEXTURE_COMPRESSED:
                *params = ConvertFromGLboolean<ParamType>(info->compressed);
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    template <typename ParamType>
    void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *params)
    {
        ASSERT(texture != nullptr);
    
        switch (pname)
        {
            case GL_TEXTURE_MAG_FILTER:
                *params = ConvertFromGLenum<ParamType>(texture->getMagFilter());
                break;
            case GL_TEXTURE_MIN_FILTER:
                *params = ConvertFromGLenum<ParamType>(texture->getMinFilter());
                break;
            case GL_TEXTURE_WRAP_S:
                *params = ConvertFromGLenum<ParamType>(texture->getWrapS());
                break;
            case GL_TEXTURE_WRAP_T:
                *params = ConvertFromGLenum<ParamType>(texture->getWrapT());
                break;
            case GL_TEXTURE_WRAP_R:
                *params = ConvertFromGLenum<ParamType>(texture->getWrapR());
                break;
            case GL_TEXTURE_IMMUTABLE_FORMAT:
                *params = ConvertFromGLboolean<ParamType>(texture->getImmutableFormat());
                break;
            case GL_TEXTURE_IMMUTABLE_LEVELS:
                *params = ConvertFromGLuint<ParamType>(texture->getImmutableLevels());
                break;
            case GL_TEXTURE_USAGE_ANGLE:
                *params = ConvertFromGLenum<ParamType>(texture->getUsage());
                break;
            case GL_TEXTURE_MAX_ANISOTROPY_EXT:
                *params = ConvertFromGLfloat<ParamType>(texture->getMaxAnisotropy());
                break;
            case GL_TEXTURE_SWIZZLE_R:
                *params = ConvertFromGLenum<ParamType>(texture->getSwizzleRed());
                break;
            case GL_TEXTURE_SWIZZLE_G:
                *params = ConvertFromGLenum<ParamType>(texture->getSwizzleGreen());
                break;
            case GL_TEXTURE_SWIZZLE_B:
                *params = ConvertFromGLenum<ParamType>(texture->getSwizzleBlue());
                break;
            case GL_TEXTURE_SWIZZLE_A:
                *params = ConvertFromGLenum<ParamType>(texture->getSwizzleAlpha());
                break;
            case GL_TEXTURE_BASE_LEVEL:
                *params = ConvertFromGLuint<ParamType>(texture->getBaseLevel());
                break;
            case GL_TEXTURE_MAX_LEVEL:
                *params = ConvertFromGLuint<ParamType>(texture->getMaxLevel());
                break;
            case GL_TEXTURE_MIN_LOD:
                *params = ConvertFromGLfloat<ParamType>(texture->getSamplerState().minLod);
                break;
            case GL_TEXTURE_MAX_LOD:
                *params = ConvertFromGLfloat<ParamType>(texture->getSamplerState().maxLod);
                break;
            case GL_TEXTURE_COMPARE_MODE:
                *params = ConvertFromGLenum<ParamType>(texture->getCompareMode());
                break;
            case GL_TEXTURE_COMPARE_FUNC:
                *params = ConvertFromGLenum<ParamType>(texture->getCompareFunc());
                break;
            case GL_TEXTURE_SRGB_DECODE_EXT:
                *params = ConvertFromGLenum<ParamType>(texture->getSRGBDecode());
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    template <typename ParamType>
    void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params)
    {
        ASSERT(texture != nullptr);
    
        switch (pname)
        {
            case GL_TEXTURE_WRAP_S:
                texture->setWrapS(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_WRAP_T:
                texture->setWrapT(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_WRAP_R:
                texture->setWrapR(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MIN_FILTER:
                texture->setMinFilter(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MAG_FILTER:
                texture->setMagFilter(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_USAGE_ANGLE:
                texture->setUsage(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MAX_ANISOTROPY_EXT:
                texture->setMaxAnisotropy(ConvertToGLfloat(params[0]));
                break;
            case GL_TEXTURE_COMPARE_MODE:
                texture->setCompareMode(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_COMPARE_FUNC:
                texture->setCompareFunc(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_SWIZZLE_R:
                texture->setSwizzleRed(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_SWIZZLE_G:
                texture->setSwizzleGreen(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_SWIZZLE_B:
                texture->setSwizzleBlue(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_SWIZZLE_A:
                texture->setSwizzleAlpha(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_BASE_LEVEL:
                texture->setBaseLevel(ConvertToGLuint(params[0]));
                break;
            case GL_TEXTURE_MAX_LEVEL:
                texture->setMaxLevel(ConvertToGLuint(params[0]));
                break;
            case GL_TEXTURE_MIN_LOD:
                texture->setMinLod(ConvertToGLfloat(params[0]));
                break;
            case GL_TEXTURE_MAX_LOD:
                texture->setMaxLod(ConvertToGLfloat(params[0]));
                break;
            case GL_DEPTH_STENCIL_TEXTURE_MODE:
                texture->setDepthStencilTextureMode(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_SRGB_DECODE_EXT:
                texture->setSRGBDecode(ConvertToGLenum(params[0]));
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    template <typename ParamType>
    void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *params)
    {
        switch (pname)
        {
            case GL_TEXTURE_MIN_FILTER:
                *params = ConvertFromGLenum<ParamType>(sampler->getMinFilter());
                break;
            case GL_TEXTURE_MAG_FILTER:
                *params = ConvertFromGLenum<ParamType>(sampler->getMagFilter());
                break;
            case GL_TEXTURE_WRAP_S:
                *params = ConvertFromGLenum<ParamType>(sampler->getWrapS());
                break;
            case GL_TEXTURE_WRAP_T:
                *params = ConvertFromGLenum<ParamType>(sampler->getWrapT());
                break;
            case GL_TEXTURE_WRAP_R:
                *params = ConvertFromGLenum<ParamType>(sampler->getWrapR());
                break;
            case GL_TEXTURE_MAX_ANISOTROPY_EXT:
                *params = ConvertFromGLfloat<ParamType>(sampler->getMaxAnisotropy());
                break;
            case GL_TEXTURE_MIN_LOD:
                *params = ConvertFromGLfloat<ParamType>(sampler->getMinLod());
                break;
            case GL_TEXTURE_MAX_LOD:
                *params = ConvertFromGLfloat<ParamType>(sampler->getMaxLod());
                break;
            case GL_TEXTURE_COMPARE_MODE:
                *params = ConvertFromGLenum<ParamType>(sampler->getCompareMode());
                break;
            case GL_TEXTURE_COMPARE_FUNC:
                *params = ConvertFromGLenum<ParamType>(sampler->getCompareFunc());
                break;
            case GL_TEXTURE_SRGB_DECODE_EXT:
                *params = ConvertFromGLenum<ParamType>(sampler->getSRGBDecode());
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    template <typename ParamType>
    void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *params)
    {
        switch (pname)
        {
            case GL_TEXTURE_WRAP_S:
                sampler->setWrapS(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_WRAP_T:
                sampler->setWrapT(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_WRAP_R:
                sampler->setWrapR(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MIN_FILTER:
                sampler->setMinFilter(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MAG_FILTER:
                sampler->setMagFilter(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MAX_ANISOTROPY_EXT:
                sampler->setMaxAnisotropy(ConvertToGLfloat(params[0]));
                break;
            case GL_TEXTURE_COMPARE_MODE:
                sampler->setCompareMode(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_COMPARE_FUNC:
                sampler->setCompareFunc(ConvertToGLenum(params[0]));
                break;
            case GL_TEXTURE_MIN_LOD:
                sampler->setMinLod(ConvertToGLfloat(params[0]));
                break;
            case GL_TEXTURE_MAX_LOD:
                sampler->setMaxLod(ConvertToGLfloat(params[0]));
                break;
            case GL_TEXTURE_SRGB_DECODE_EXT:
                sampler->setSRGBDecode(ConvertToGLenum(params[0]));
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    template <typename ParamType, typename CurrentDataType>
    ParamType ConvertCurrentValue(CurrentDataType currentValue)
    {
        return static_cast<ParamType>(currentValue);
    }
    
    template <>
    GLint ConvertCurrentValue(GLfloat currentValue)
    {
        return iround<GLint>(currentValue);
    }
    
    // Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
    template <typename ParamType, typename CurrentDataType, size_t CurrentValueCount>
    void QueryVertexAttribBase(const VertexAttribute &attrib,
                               const VertexBinding &binding,
                               const CurrentDataType (&currentValueData)[CurrentValueCount],
                               GLenum pname,
                               ParamType *params)
    {
        switch (pname)
        {
            case GL_CURRENT_VERTEX_ATTRIB:
                for (size_t i = 0; i < CurrentValueCount; ++i)
                {
                    params[i] = ConvertCurrentValue<ParamType>(currentValueData[i]);
                }
                break;
            case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
                *params = ConvertFromGLboolean<ParamType>(attrib.enabled);
                break;
            case GL_VERTEX_ATTRIB_ARRAY_SIZE:
                *params = ConvertFromGLuint<ParamType>(attrib.size);
                break;
            case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
                *params = ConvertFromGLuint<ParamType>(attrib.vertexAttribArrayStride);
                break;
            case GL_VERTEX_ATTRIB_ARRAY_TYPE:
                *params = ConvertFromGLenum<ParamType>(attrib.type);
                break;
            case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
                *params = ConvertFromGLboolean<ParamType>(attrib.normalized);
                break;
            case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
                *params = ConvertFromGLuint<ParamType>(binding.buffer.id());
                break;
            case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
                *params = ConvertFromGLuint<ParamType>(binding.divisor);
                break;
            case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
                *params = ConvertFromGLboolean<ParamType>(attrib.pureInteger);
                break;
            case GL_VERTEX_ATTRIB_BINDING:
                *params = ConvertFromGLuint<ParamType>(attrib.bindingIndex);
                break;
            case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
                // attrib.relativeOffset should not be negative or greater than max GLint
                ASSERT(attrib.relativeOffset >= 0 &&
                       attrib.relativeOffset <= std::numeric_limits<GLint>::max());
                *params = ConvertFromGLint<ParamType>(static_cast<GLint>(attrib.relativeOffset));
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    template <typename ParamType>
    void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *params)
    {
        ASSERT(buffer != nullptr);
    
        switch (pname)
        {
            case GL_BUFFER_USAGE:
                *params = ConvertFromGLenum<ParamType>(buffer->getUsage());
                break;
            case GL_BUFFER_SIZE:
                *params = ConvertFromGLint64<ParamType>(buffer->getSize());
                break;
            case GL_BUFFER_ACCESS_FLAGS:
                *params = ConvertFromGLuint<ParamType>(buffer->getAccessFlags());
                break;
            case GL_BUFFER_ACCESS_OES:
                *params = ConvertFromGLenum<ParamType>(buffer->getAccess());
                break;
            case GL_BUFFER_MAPPED:
                *params = ConvertFromGLboolean<ParamType>(buffer->isMapped());
                break;
            case GL_BUFFER_MAP_OFFSET:
                *params = ConvertFromGLint64<ParamType>(buffer->getMapOffset());
                break;
            case GL_BUFFER_MAP_LENGTH:
                *params = ConvertFromGLint64<ParamType>(buffer->getMapLength());
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    }  // anonymous namespace
    
    void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
                                               GLenum attachment,
                                               GLenum pname,
                                               GLint *params)
    {
        ASSERT(framebuffer);
    
        const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
        if (attachmentObject == nullptr)
        {
            // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
            // is NONE, then querying any other pname will generate INVALID_ENUM.
    
            // ES 3.0.2 spec pg 235 states that if the attachment type is none,
            // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
            // INVALID_OPERATION for all other pnames
    
            switch (pname)
            {
                case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                    *params = GL_NONE;
                    break;
    
                case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
                    *params = 0;
                    break;
    
                default:
                    UNREACHABLE();
                    break;
            }
    
            return;
        }
    
        switch (pname)
        {
            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                *params = attachmentObject->type();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
                *params = attachmentObject->id();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
                *params = attachmentObject->mipLevel();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
                *params = attachmentObject->cubeMapFace();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
                *params = attachmentObject->getRedSize();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
                *params = attachmentObject->getGreenSize();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
                *params = attachmentObject->getBlueSize();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
                *params = attachmentObject->getAlphaSize();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
                *params = attachmentObject->getDepthSize();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
                *params = attachmentObject->getStencilSize();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
                *params = attachmentObject->getComponentType();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
                *params = attachmentObject->getColorEncoding();
                break;
    
            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
                *params = attachmentObject->layer();
                break;
    
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params)
    {
        QueryBufferParameterBase(buffer, pname, params);
    }
    
    void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params)
    {
        QueryBufferParameterBase(buffer, pname, params);
    }
    
    void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params)
    {
        switch (pname)
        {
            case GL_BUFFER_MAP_POINTER:
                *params = buffer->getMapPointer();
                break;
    
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryProgramiv(const Program *program, GLenum pname, GLint *params)
    {
        ASSERT(program != nullptr);
    
        switch (pname)
        {
            case GL_DELETE_STATUS:
                *params = program->isFlaggedForDeletion();
                return;
            case GL_LINK_STATUS:
                *params = program->isLinked();
                return;
            case GL_VALIDATE_STATUS:
                *params = program->isValidated();
                return;
            case GL_INFO_LOG_LENGTH:
                *params = program->getInfoLogLength();
                return;
            case GL_ATTACHED_SHADERS:
                *params = program->getAttachedShadersCount();
                return;
            case GL_ACTIVE_ATTRIBUTES:
                *params = program->getActiveAttributeCount();
                return;
            case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
                *params = program->getActiveAttributeMaxLength();
                return;
            case GL_ACTIVE_UNIFORMS:
                *params = program->getActiveUniformCount();
                return;
            case GL_ACTIVE_UNIFORM_MAX_LENGTH:
                *params = program->getActiveUniformMaxLength();
                return;
            case GL_PROGRAM_BINARY_LENGTH_OES:
                *params = program->getBinaryLength();
                return;
            case GL_ACTIVE_UNIFORM_BLOCKS:
                *params = program->getActiveUniformBlockCount();
                return;
            case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
                *params = program->getActiveUniformBlockMaxLength();
                break;
            case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
                *params = program->getTransformFeedbackBufferMode();
                break;
            case GL_TRANSFORM_FEEDBACK_VARYINGS:
                *params = program->getTransformFeedbackVaryingCount();
                break;
            case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
                *params = program->getTransformFeedbackVaryingMaxLength();
                break;
            case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
                *params = program->getBinaryRetrievableHint();
                break;
            case GL_PROGRAM_SEPARABLE:
                *params = program->isSeparable();
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryRenderbufferiv(const Context *context,
                             const Renderbuffer *renderbuffer,
                             GLenum pname,
                             GLint *params)
    {
        ASSERT(renderbuffer != nullptr);
    
        switch (pname)
        {
            case GL_RENDERBUFFER_WIDTH:
                *params = renderbuffer->getWidth();
                break;
            case GL_RENDERBUFFER_HEIGHT:
                *params = renderbuffer->getHeight();
                break;
            case GL_RENDERBUFFER_INTERNAL_FORMAT:
                // Special case the WebGL 1 DEPTH_STENCIL format.
                if (context->isWebGL1() &&
                    renderbuffer->getFormat().info->internalFormat == GL_DEPTH24_STENCIL8)
                {
                    *params = GL_DEPTH_STENCIL;
                }
                else
                {
                    *params = renderbuffer->getFormat().info->internalFormat;
                }
                break;
            case GL_RENDERBUFFER_RED_SIZE:
                *params = renderbuffer->getRedSize();
                break;
            case GL_RENDERBUFFER_GREEN_SIZE:
                *params = renderbuffer->getGreenSize();
                break;
            case GL_RENDERBUFFER_BLUE_SIZE:
                *params = renderbuffer->getBlueSize();
                break;
            case GL_RENDERBUFFER_ALPHA_SIZE:
                *params = renderbuffer->getAlphaSize();
                break;
            case GL_RENDERBUFFER_DEPTH_SIZE:
                *params = renderbuffer->getDepthSize();
                break;
            case GL_RENDERBUFFER_STENCIL_SIZE:
                *params = renderbuffer->getStencilSize();
                break;
            case GL_RENDERBUFFER_SAMPLES_ANGLE:
                *params = renderbuffer->getSamples();
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryShaderiv(const Context *context, Shader *shader, GLenum pname, GLint *params)
    {
        ASSERT(shader != nullptr);
    
        switch (pname)
        {
            case GL_SHADER_TYPE:
                *params = shader->getType();
                return;
            case GL_DELETE_STATUS:
                *params = shader->isFlaggedForDeletion();
                return;
            case GL_COMPILE_STATUS:
                *params = shader->isCompiled(context) ? GL_TRUE : GL_FALSE;
                return;
            case GL_INFO_LOG_LENGTH:
                *params = shader->getInfoLogLength(context);
                return;
            case GL_SHADER_SOURCE_LENGTH:
                *params = shader->getSourceLength();
                return;
            case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
                *params = shader->getTranslatedSourceWithDebugInfoLength(context);
                return;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryTexLevelParameterfv(const Texture *texture,
                                  GLenum target,
                                  GLint level,
                                  GLenum pname,
                                  GLfloat *params)
    {
        QueryTexLevelParameterBase(texture, target, level, pname, params);
    }
    
    void QueryTexLevelParameteriv(const Texture *texture,
                                  GLenum target,
                                  GLint level,
                                  GLenum pname,
                                  GLint *params)
    {
        QueryTexLevelParameterBase(texture, target, level, pname, params);
    }
    
    void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params)
    {
        QueryTexParameterBase(texture, pname, params);
    }
    
    void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params)
    {
        QueryTexParameterBase(texture, pname, params);
    }
    
    void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params)
    {
        QuerySamplerParameterBase(sampler, pname, params);
    }
    
    void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params)
    {
        QuerySamplerParameterBase(sampler, pname, params);
    }
    
    void QueryVertexAttribfv(const VertexAttribute &attrib,
                             const VertexBinding &binding,
                             const VertexAttribCurrentValueData &currentValueData,
                             GLenum pname,
                             GLfloat *params)
    {
        QueryVertexAttribBase(attrib, binding, currentValueData.FloatValues, pname, params);
    }
    
    void QueryVertexAttribiv(const VertexAttribute &attrib,
                             const VertexBinding &binding,
                             const VertexAttribCurrentValueData &currentValueData,
                             GLenum pname,
                             GLint *params)
    {
        QueryVertexAttribBase(attrib, binding, currentValueData.FloatValues, pname, params);
    }
    
    void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer)
    {
        switch (pname)
        {
            case GL_VERTEX_ATTRIB_ARRAY_POINTER:
                *pointer = const_cast<void *>(attrib.pointer);
                break;
    
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryVertexAttribIiv(const VertexAttribute &attrib,
                              const VertexBinding &binding,
                              const VertexAttribCurrentValueData &currentValueData,
                              GLenum pname,
                              GLint *params)
    {
        QueryVertexAttribBase(attrib, binding, currentValueData.IntValues, pname, params);
    }
    
    void QueryVertexAttribIuiv(const VertexAttribute &attrib,
                               const VertexBinding &binding,
                               const VertexAttribCurrentValueData &currentValueData,
                               GLenum pname,
                               GLuint *params)
    {
        QueryVertexAttribBase(attrib, binding, currentValueData.UnsignedIntValues, pname, params);
    }
    
    void QueryActiveUniformBlockiv(const Program *program,
                                   GLuint uniformBlockIndex,
                                   GLenum pname,
                                   GLint *params)
    {
        const UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
        switch (pname)
        {
            case GL_UNIFORM_BLOCK_BINDING:
                *params = ConvertToGLint(program->getUniformBlockBinding(uniformBlockIndex));
                break;
            case GL_UNIFORM_BLOCK_DATA_SIZE:
                *params = ConvertToGLint(uniformBlock.dataSize);
                break;
            case GL_UNIFORM_BLOCK_NAME_LENGTH:
                *params = ConvertToGLint(uniformBlock.nameWithArrayIndex().size() + 1);
                break;
            case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
                *params = ConvertToGLint(uniformBlock.memberUniformIndexes.size());
                break;
            case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
                for (size_t blockMemberIndex = 0;
                     blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
                {
                    params[blockMemberIndex] =
                        ConvertToGLint(uniformBlock.memberUniformIndexes[blockMemberIndex]);
                }
                break;
            case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
                *params = ConvertToGLint(uniformBlock.vertexStaticUse);
                break;
            case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
                *params = ConvertToGLint(uniformBlock.fragmentStaticUse);
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params)
    {
        switch (pname)
        {
            case GL_NUM_SAMPLE_COUNTS:
                if (bufSize != 0)
                {
                    *params = static_cast<GLint>(format.sampleCounts.size());
                }
                break;
    
            case GL_SAMPLES:
            {
                size_t returnCount   = std::min<size_t>(bufSize, format.sampleCounts.size());
                auto sampleReverseIt = format.sampleCounts.rbegin();
                for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
                {
                    params[sampleIndex] = *sampleReverseIt++;
                }
            }
            break;
    
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params)
    {
        ASSERT(framebuffer);
    
        switch (pname)
        {
            case GL_FRAMEBUFFER_DEFAULT_WIDTH:
                *params = framebuffer->getDefaultWidth();
                break;
            case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
                *params = framebuffer->getDefaultHeight();
                break;
            case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
                *params = framebuffer->getDefaultSamples();
                break;
            case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
                *params = framebuffer->getDefaultFixedSampleLocations();
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    Error QuerySynciv(const FenceSync *sync,
                      GLenum pname,
                      GLsizei bufSize,
                      GLsizei *length,
                      GLint *values)
    {
        ASSERT(sync);
    
        // All queries return one value, exit early if the buffer can't fit anything.
        if (bufSize < 1)
        {
            if (length != nullptr)
            {
                *length = 0;
            }
            return NoError();
        }
    
        switch (pname)
        {
            case GL_OBJECT_TYPE:
                *values = ConvertToGLint(GL_SYNC_FENCE);
                break;
            case GL_SYNC_CONDITION:
                *values = ConvertToGLint(sync->getCondition());
                break;
            case GL_SYNC_FLAGS:
                *values = ConvertToGLint(sync->getFlags());
                break;
            case GL_SYNC_STATUS:
                ANGLE_TRY(sync->getStatus(values));
                break;
    
            default:
                UNREACHABLE();
                break;
        }
    
        if (length != nullptr)
        {
            *length = 1;
        }
    
        return NoError();
    }
    
    void SetTexParameterf(Texture *texture, GLenum pname, GLfloat param)
    {
        SetTexParameterBase(texture, pname, &param);
    }
    
    void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params)
    {
        SetTexParameterBase(texture, pname, params);
    }
    
    void SetTexParameteri(Texture *texture, GLenum pname, GLint param)
    {
        SetTexParameterBase(texture, pname, &param);
    }
    
    void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params)
    {
        SetTexParameterBase(texture, pname, params);
    }
    
    void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param)
    {
        SetSamplerParameterBase(sampler, pname, &param);
    }
    
    void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params)
    {
        SetSamplerParameterBase(sampler, pname, params);
    }
    
    void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param)
    {
        SetSamplerParameterBase(sampler, pname, &param);
    }
    
    void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params)
    {
        SetSamplerParameterBase(sampler, pname, params);
    }
    
    void SetFramebufferParameteri(Framebuffer *framebuffer, GLenum pname, GLint param)
    {
        ASSERT(framebuffer);
    
        switch (pname)
        {
            case GL_FRAMEBUFFER_DEFAULT_WIDTH:
                framebuffer->setDefaultWidth(param);
                break;
            case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
                framebuffer->setDefaultHeight(param);
                break;
            case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
                framebuffer->setDefaultSamples(param);
                break;
            case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
                framebuffer->setDefaultFixedSampleLocations(static_cast<GLboolean>(param));
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    void SetProgramParameteri(Program *program, GLenum pname, GLint value)
    {
        ASSERT(program);
    
        switch (pname)
        {
            case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
                program->setBinaryRetrievableHint(value != GL_FALSE);
                break;
            case GL_PROGRAM_SEPARABLE:
                program->setSeparable(value != GL_FALSE);
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    GLuint QueryProgramResourceIndex(const Program *program,
                                     GLenum programInterface,
                                     const GLchar *name)
    {
        switch (programInterface)
        {
            case GL_PROGRAM_INPUT:
                return program->getInputResourceIndex(name);
    
            case GL_PROGRAM_OUTPUT:
                return program->getOutputResourceIndex(name);
    
            // TODO(Jie): more interfaces.
            case GL_UNIFORM:
            case GL_UNIFORM_BLOCK:
            case GL_TRANSFORM_FEEDBACK_VARYING:
            case GL_BUFFER_VARIABLE:
            case GL_SHADER_STORAGE_BLOCK:
                UNIMPLEMENTED();
                return GL_INVALID_INDEX;
    
            default:
                UNREACHABLE();
                return GL_INVALID_INDEX;
        }
    }
    
    void QueryProgramResourceName(const Program *program,
                                  GLenum programInterface,
                                  GLuint index,
                                  GLsizei bufSize,
                                  GLsizei *length,
                                  GLchar *name)
    {
        switch (programInterface)
        {
            case GL_PROGRAM_INPUT:
                program->getInputResourceName(index, bufSize, length, name);
                break;
    
            case GL_PROGRAM_OUTPUT:
                program->getOutputResourceName(index, bufSize, length, name);
                break;
    
            // TODO(Jie): more interfaces.
            case GL_UNIFORM:
            case GL_UNIFORM_BLOCK:
            case GL_TRANSFORM_FEEDBACK_VARYING:
            case GL_BUFFER_VARIABLE:
            case GL_SHADER_STORAGE_BLOCK:
                UNIMPLEMENTED();
                break;
    
            default:
                UNREACHABLE();
        }
    }
    
    }  // namespace gl
    
    namespace egl
    {
    
    void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value)
    {
        ASSERT(config != nullptr);
        switch (attribute)
        {
            case EGL_BUFFER_SIZE:
                *value = config->bufferSize;
                break;
            case EGL_ALPHA_SIZE:
                *value = config->alphaSize;
                break;
            case EGL_BLUE_SIZE:
                *value = config->blueSize;
                break;
            case EGL_GREEN_SIZE:
                *value = config->greenSize;
                break;
            case EGL_RED_SIZE:
                *value = config->redSize;
                break;
            case EGL_DEPTH_SIZE:
                *value = config->depthSize;
                break;
            case EGL_STENCIL_SIZE:
                *value = config->stencilSize;
                break;
            case EGL_CONFIG_CAVEAT:
                *value = config->configCaveat;
                break;
            case EGL_CONFIG_ID:
                *value = config->configID;
                break;
            case EGL_LEVEL:
                *value = config->level;
                break;
            case EGL_NATIVE_RENDERABLE:
                *value = config->nativeRenderable;
                break;
            case EGL_NATIVE_VISUAL_ID:
                *value = config->nativeVisualID;
                break;
            case EGL_NATIVE_VISUAL_TYPE:
                *value = config->nativeVisualType;
                break;
            case EGL_SAMPLES:
                *value = config->samples;
                break;
            case EGL_SAMPLE_BUFFERS:
                *value = config->sampleBuffers;
                break;
            case EGL_SURFACE_TYPE:
                *value = config->surfaceType;
                break;
            case EGL_TRANSPARENT_TYPE:
                *value = config->transparentType;
                break;
            case EGL_TRANSPARENT_BLUE_VALUE:
                *value = config->transparentBlueValue;
                break;
            case EGL_TRANSPARENT_GREEN_VALUE:
                *value = config->transparentGreenValue;
                break;
            case EGL_TRANSPARENT_RED_VALUE:
                *value = config->transparentRedValue;
                break;
            case EGL_BIND_TO_TEXTURE_RGB:
                *value = config->bindToTextureRGB;
                break;
            case EGL_BIND_TO_TEXTURE_RGBA:
                *value = config->bindToTextureRGBA;
                break;
            case EGL_MIN_SWAP_INTERVAL:
                *value = config->minSwapInterval;
                break;
            case EGL_MAX_SWAP_INTERVAL:
                *value = config->maxSwapInterval;
                break;
            case EGL_LUMINANCE_SIZE:
                *value = config->luminanceSize;
                break;
            case EGL_ALPHA_MASK_SIZE:
                *value = config->alphaMaskSize;
                break;
            case EGL_COLOR_BUFFER_TYPE:
                *value = config->colorBufferType;
                break;
            case EGL_RENDERABLE_TYPE:
                *value = config->renderableType;
                break;
            case EGL_MATCH_NATIVE_PIXMAP:
                *value = false;
                UNIMPLEMENTED();
                break;
            case EGL_CONFORMANT:
                *value = config->conformant;
                break;
            case EGL_MAX_PBUFFER_WIDTH:
                *value = config->maxPBufferWidth;
                break;
            case EGL_MAX_PBUFFER_HEIGHT:
                *value = config->maxPBufferHeight;
                break;
            case EGL_MAX_PBUFFER_PIXELS:
                *value = config->maxPBufferPixels;
                break;
            case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
                *value = config->optimalOrientation;
                break;
            case EGL_COLOR_COMPONENT_TYPE_EXT:
                *value = config->colorComponentType;
                break;
            default:
                UNREACHABLE();
                break;
        }
    }
    
    }  // namespace egl