Edit

kc3-lang/angle/src/libANGLE/renderer/renderer_utils.h

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2021-09-13 10:56:58
    Hash : 1ca1589f
    Message : Give GLES extension bools a vendor suffix. This is in preparation for auto-generation which will give all of these bools suffixes. Bug: angleproject:6379 Change-Id: I7e3f6c9b644c41a2165e6bf7b62d661fd352a250 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3158503 Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/renderer/renderer_utils.h
  • //
    // Copyright 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.
    //
    // renderer_utils:
    //   Helper methods pertaining to most or all back-ends.
    //
    
    #ifndef LIBANGLE_RENDERER_RENDERER_UTILS_H_
    #define LIBANGLE_RENDERER_RENDERER_UTILS_H_
    
    #include <cstdint>
    
    #include <limits>
    #include <map>
    
    #include "GLSLANG/ShaderLang.h"
    #include "common/Color.h"
    #include "common/angleutils.h"
    #include "common/utilities.h"
    #include "libANGLE/angletypes.h"
    
    namespace angle
    {
    struct FeatureSetBase;
    struct Format;
    enum class FormatID;
    }  // namespace angle
    
    namespace gl
    {
    struct FormatType;
    struct InternalFormat;
    class State;
    }  // namespace gl
    
    namespace egl
    {
    class AttributeMap;
    struct DisplayState;
    }  // namespace egl
    
    namespace rx
    {
    class ContextImpl;
    
    // The possible rotations of the surface/draw framebuffer, particularly for the Vulkan back-end on
    // Android.
    enum class SurfaceRotation
    {
        Identity,
        Rotated90Degrees,
        Rotated180Degrees,
        Rotated270Degrees,
        FlippedIdentity,
        FlippedRotated90Degrees,
        FlippedRotated180Degrees,
        FlippedRotated270Degrees,
    
        InvalidEnum,
        EnumCount = InvalidEnum,
    };
    
    using SpecConstUsageBits = angle::PackedEnumBitSet<sh::vk::SpecConstUsage, uint32_t>;
    
    void RotateRectangle(const SurfaceRotation rotation,
                         const bool flipY,
                         const int framebufferWidth,
                         const int framebufferHeight,
                         const gl::Rectangle &incoming,
                         gl::Rectangle *outgoing);
    
    using MipGenerationFunction = void (*)(size_t sourceWidth,
                                           size_t sourceHeight,
                                           size_t sourceDepth,
                                           const uint8_t *sourceData,
                                           size_t sourceRowPitch,
                                           size_t sourceDepthPitch,
                                           uint8_t *destData,
                                           size_t destRowPitch,
                                           size_t destDepthPitch);
    
    typedef void (*PixelReadFunction)(const uint8_t *source, uint8_t *dest);
    typedef void (*PixelWriteFunction)(const uint8_t *source, uint8_t *dest);
    typedef void (*PixelCopyFunction)(const uint8_t *source, uint8_t *dest);
    
    class FastCopyFunctionMap
    {
      public:
        struct Entry
        {
            angle::FormatID formatID;
            PixelCopyFunction func;
        };
    
        constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
    
        constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
    
        bool has(angle::FormatID formatID) const;
        PixelCopyFunction get(angle::FormatID formatID) const;
    
      private:
        size_t mSize;
        const Entry *mData;
    };
    
    struct PackPixelsParams
    {
        PackPixelsParams();
        PackPixelsParams(const gl::Rectangle &area,
                         const angle::Format &destFormat,
                         GLuint outputPitch,
                         bool reverseRowOrderIn,
                         gl::Buffer *packBufferIn,
                         ptrdiff_t offset);
    
        gl::Rectangle area;
        const angle::Format *destFormat;
        GLuint outputPitch;
        gl::Buffer *packBuffer;
        bool reverseRowOrder;
        ptrdiff_t offset;
        SurfaceRotation rotation;
    };
    
    void PackPixels(const PackPixelsParams &params,
                    const angle::Format &sourceFormat,
                    int inputPitch,
                    const uint8_t *source,
                    uint8_t *destination);
    
    using InitializeTextureDataFunction = void (*)(size_t width,
                                                   size_t height,
                                                   size_t depth,
                                                   uint8_t *output,
                                                   size_t outputRowPitch,
                                                   size_t outputDepthPitch);
    
    using LoadImageFunction = void (*)(size_t width,
                                       size_t height,
                                       size_t depth,
                                       const uint8_t *input,
                                       size_t inputRowPitch,
                                       size_t inputDepthPitch,
                                       uint8_t *output,
                                       size_t outputRowPitch,
                                       size_t outputDepthPitch);
    
    struct LoadImageFunctionInfo
    {
        LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
        LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
            : loadFunction(loadFunction), requiresConversion(requiresConversion)
        {}
    
        LoadImageFunction loadFunction;
        bool requiresConversion;
    };
    
    using LoadFunctionMap           = LoadImageFunctionInfo (*)(GLenum);
    using LoadTextureBorderFunction = void (*)(angle::ColorF &mBorderColor);
    struct LoadTextureBorderFunctionInfo
    {
        LoadTextureBorderFunctionInfo() : loadFunction(nullptr) {}
        LoadTextureBorderFunctionInfo(LoadTextureBorderFunction loadFunction)
            : loadFunction(loadFunction)
        {}
    
        LoadTextureBorderFunction loadFunction;
    };
    
    using LoadTextureBorderFunctionMap = LoadTextureBorderFunctionInfo (*)();
    
    bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
    bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
    
    void CopyImageCHROMIUM(const uint8_t *sourceData,
                           size_t sourceRowPitch,
                           size_t sourcePixelBytes,
                           size_t sourceDepthPitch,
                           PixelReadFunction pixelReadFunction,
                           uint8_t *destData,
                           size_t destRowPitch,
                           size_t destPixelBytes,
                           size_t destDepthPitch,
                           PixelWriteFunction pixelWriteFunction,
                           GLenum destUnsizedFormat,
                           GLenum destComponentType,
                           size_t width,
                           size_t height,
                           size_t depth,
                           bool unpackFlipY,
                           bool unpackPremultiplyAlpha,
                           bool unpackUnmultiplyAlpha);
    
    // Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
    // This helper class encapsulates handling incomplete textures. Because the GL back-end
    // can take advantage of the driver's incomplete textures, and because clearing multisample
    // textures is so difficult, we can keep an instance of this class in the back-end instead
    // of moving the logic to the Context front-end.
    
    // This interface allows us to call-back to init a multisample texture.
    class MultisampleTextureInitializer
    {
      public:
        virtual ~MultisampleTextureInitializer() {}
        virtual angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
                                                                  gl::Texture *glTexture) = 0;
    };
    
    class IncompleteTextureSet final : angle::NonCopyable
    {
      public:
        IncompleteTextureSet();
        ~IncompleteTextureSet();
    
        void onDestroy(const gl::Context *context);
    
        angle::Result getIncompleteTexture(const gl::Context *context,
                                           gl::TextureType type,
                                           gl::SamplerFormat format,
                                           MultisampleTextureInitializer *multisampleInitializer,
                                           gl::Texture **textureOut);
    
      private:
        using TextureMapWithSamplerFormat = angle::PackedEnumMap<gl::SamplerFormat, gl::TextureMap>;
    
        TextureMapWithSamplerFormat mIncompleteTextures;
        gl::Buffer *mIncompleteTextureBufferAttachment;
    };
    
    // Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
    // The return value indicate if the data was updated or not.
    template <int cols, int rows>
    struct SetFloatUniformMatrixGLSL
    {
        static void Run(unsigned int arrayElementOffset,
                        unsigned int elementCount,
                        GLsizei countIn,
                        GLboolean transpose,
                        const GLfloat *value,
                        uint8_t *targetData);
    };
    
    template <int cols, int rows>
    struct SetFloatUniformMatrixHLSL
    {
        static void Run(unsigned int arrayElementOffset,
                        unsigned int elementCount,
                        GLsizei countIn,
                        GLboolean transpose,
                        const GLfloat *value,
                        uint8_t *targetData);
    };
    
    // Helper method to de-tranpose a matrix uniform for an API query.
    void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
    
    template <typename NonFloatT>
    void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose);
    
    const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type);
    
    angle::Result ComputeStartVertex(ContextImpl *contextImpl,
                                     const gl::IndexRange &indexRange,
                                     GLint baseVertex,
                                     GLint *firstVertexOut);
    
    angle::Result GetVertexRangeInfo(const gl::Context *context,
                                     GLint firstVertex,
                                     GLsizei vertexOrIndexCount,
                                     gl::DrawElementsType indexTypeOrInvalid,
                                     const void *indices,
                                     GLint baseVertex,
                                     GLint *startVertexOut,
                                     size_t *vertexCountOut);
    
    gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY);
    
    // Helper method to intialize a FeatureSet with overrides from the DisplayState
    void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state);
    
    template <typename In>
    uint32_t LineLoopRestartIndexCountHelper(GLsizei indexCount, const uint8_t *srcPtr)
    {
        constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
        const In *inIndices       = reinterpret_cast<const In *>(srcPtr);
        uint32_t numIndices       = 0;
        // See CopyLineLoopIndicesWithRestart() below for more info on how
        // numIndices is calculated.
        GLsizei loopStartIndex = 0;
        for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
        {
            In vertex = inIndices[curIndex];
            if (vertex != restartIndex)
            {
                numIndices++;
            }
            else
            {
                if (curIndex > loopStartIndex)
                {
                    numIndices += 2;
                }
                loopStartIndex = curIndex + 1;
            }
        }
        if (indexCount > loopStartIndex)
        {
            numIndices++;
        }
        return numIndices;
    }
    
    inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,
                                                     GLsizei indexCount,
                                                     const uint8_t *srcPtr)
    {
        switch (glIndexType)
        {
            case gl::DrawElementsType::UnsignedByte:
                return LineLoopRestartIndexCountHelper<uint8_t>(indexCount, srcPtr);
            case gl::DrawElementsType::UnsignedShort:
                return LineLoopRestartIndexCountHelper<uint16_t>(indexCount, srcPtr);
            case gl::DrawElementsType::UnsignedInt:
                return LineLoopRestartIndexCountHelper<uint32_t>(indexCount, srcPtr);
            default:
                UNREACHABLE();
                return 0;
        }
    }
    
    // Writes the line-strip vertices for a line loop to outPtr,
    // where outLimit is calculated as in GetPrimitiveRestartIndexCount.
    template <typename In, typename Out>
    void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr)
    {
        constexpr In restartIndex     = gl::GetPrimitiveRestartIndexFromType<In>();
        constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType<Out>();
        const In *inIndices           = reinterpret_cast<const In *>(srcPtr);
        Out *outIndices               = reinterpret_cast<Out *>(outPtr);
        GLsizei loopStartIndex        = 0;
        for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
        {
            In vertex = inIndices[curIndex];
            if (vertex != restartIndex)
            {
                *(outIndices++) = static_cast<Out>(vertex);
            }
            else
            {
                if (curIndex > loopStartIndex)
                {
                    // Emit an extra vertex only if the loop is not empty.
                    *(outIndices++) = inIndices[loopStartIndex];
                    // Then restart the strip.
                    *(outIndices++) = outRestartIndex;
                }
                loopStartIndex = curIndex + 1;
            }
        }
        if (indexCount > loopStartIndex)
        {
            // Close the last loop if not empty.
            *(outIndices++) = inIndices[loopStartIndex];
        }
    }
    
    void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
    
    angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
                                         const gl::Context *context,
                                         gl::PrimitiveMode mode,
                                         const GLint *firsts,
                                         const GLsizei *counts,
                                         GLsizei drawcount);
    angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
                                                  const gl::Context *context,
                                                  gl::PrimitiveMode mode,
                                                  const GLint *firsts,
                                                  const GLsizei *counts,
                                                  const GLsizei *instanceCounts,
                                                  GLsizei drawcount);
    angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
                                           const gl::Context *context,
                                           gl::PrimitiveMode mode,
                                           const GLsizei *counts,
                                           gl::DrawElementsType type,
                                           const GLvoid *const *indices,
                                           GLsizei drawcount);
    angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
                                                    const gl::Context *context,
                                                    gl::PrimitiveMode mode,
                                                    const GLsizei *counts,
                                                    gl::DrawElementsType type,
                                                    const GLvoid *const *indices,
                                                    const GLsizei *instanceCounts,
                                                    GLsizei drawcount);
    angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
                                                              const gl::Context *context,
                                                              gl::PrimitiveMode mode,
                                                              const GLint *firsts,
                                                              const GLsizei *counts,
                                                              const GLsizei *instanceCounts,
                                                              const GLuint *baseInstances,
                                                              GLsizei drawcount);
    angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
                                                                          const gl::Context *context,
                                                                          gl::PrimitiveMode mode,
                                                                          const GLsizei *counts,
                                                                          gl::DrawElementsType type,
                                                                          const GLvoid *const *indices,
                                                                          const GLsizei *instanceCounts,
                                                                          const GLint *baseVertices,
                                                                          const GLuint *baseInstances,
                                                                          GLsizei drawcount);
    
    // RAII object making sure reset uniforms is called no matter whether there's an error in draw calls
    class ResetBaseVertexBaseInstance : angle::NonCopyable
    {
      public:
        ResetBaseVertexBaseInstance(gl::Program *programObject,
                                    bool resetBaseVertex,
                                    bool resetBaseInstance);
    
        ~ResetBaseVertexBaseInstance();
    
      private:
        gl::Program *mProgramObject;
        bool mResetBaseVertex;
        bool mResetBaseInstance;
    };
    
    angle::FormatID ConvertToSRGB(angle::FormatID formatID);
    angle::FormatID ConvertToLinear(angle::FormatID formatID);
    bool IsOverridableLinearFormat(angle::FormatID formatID);
    }  // namespace rx
    
    // MultiDraw macro patterns
    // These macros are to avoid too much code duplication as we don't want to have if detect for
    // hasDrawID/BaseVertex/BaseInstance inside for loop in a multiDrawANGLE call Part of these are put
    // in the header as we want to share with specialized context impl on some platforms for multidraw
    #define ANGLE_SET_DRAW_ID_UNIFORM_0(drawID) \
        {}
    #define ANGLE_SET_DRAW_ID_UNIFORM_1(drawID) programObject->setDrawIDUniform(drawID)
    #define ANGLE_SET_DRAW_ID_UNIFORM(cond) ANGLE_SET_DRAW_ID_UNIFORM_##cond
    
    #define ANGLE_SET_BASE_VERTEX_UNIFORM_0(baseVertex) \
        {}
    #define ANGLE_SET_BASE_VERTEX_UNIFORM_1(baseVertex) programObject->setBaseVertexUniform(baseVertex);
    #define ANGLE_SET_BASE_VERTEX_UNIFORM(cond) ANGLE_SET_BASE_VERTEX_UNIFORM_##cond
    
    #define ANGLE_SET_BASE_INSTANCE_UNIFORM_0(baseInstance) \
        {}
    #define ANGLE_SET_BASE_INSTANCE_UNIFORM_1(baseInstance) \
        programObject->setBaseInstanceUniform(baseInstance)
    #define ANGLE_SET_BASE_INSTANCE_UNIFORM(cond) ANGLE_SET_BASE_INSTANCE_UNIFORM_##cond
    
    #define ANGLE_NOOP_DRAW_ context->noopDraw(mode, counts[drawID])
    #define ANGLE_NOOP_DRAW_INSTANCED \
        context->noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID])
    #define ANGLE_NOOP_DRAW(_instanced) ANGLE_NOOP_DRAW##_instanced
    
    #define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE_ \
        gl::MarkTransformFeedbackBufferUsage(context, counts[drawID], 1)
    #define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE_INSTANCED \
        gl::MarkTransformFeedbackBufferUsage(context, counts[drawID], instanceCounts[drawID])
    #define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced) \
        ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE##instanced
    
    #endif  // LIBANGLE_RENDERER_RENDERER_UTILS_H_