diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h new file mode 100644 index 0000000000..92002db56f --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h @@ -0,0 +1,499 @@ +// +// 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/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, +}; + +bool IsRotatedAspectRatio(SurfaceRotation rotation); + +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 (*FastCopyFunction)(const uint8_t *source, + int srcXAxisPitch, + int srcYAxisPitch, + uint8_t *dest, + int destXAxisPitch, + int destYAxisPitch, + int width, + int height); + +class FastCopyFunctionMap +{ + public: + struct Entry + { + angle::FormatID formatID; + FastCopyFunction func; + }; + + constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {} + + constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {} + + bool has(angle::FormatID formatID) const; + FastCopyFunction 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 ¶ms, + 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); + +bool ShouldUseDebugLayers(const egl::AttributeMap &attribs); + +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 MultiDrawArraysIndirectGeneral(ContextImpl *contextImpl, + const gl::Context *context, + gl::PrimitiveMode mode, + const void *indirect, + GLsizei drawcount, + GLsizei stride); +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 MultiDrawElementsIndirectGeneral(ContextImpl *contextImpl, + const gl::Context *context, + gl::PrimitiveMode mode, + gl::DrawElementsType type, + const void *indirect, + GLsizei drawcount, + GLsizei stride); +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); + +enum class PipelineType +{ + Graphics = 0, + Compute = 1, + + InvalidEnum = 2, + EnumCount = 2, +}; +} // 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 + +// Helper macro that casts to a bitfield type then verifies no bits were dropped. +#define SetBitField(lhs, rhs) \ + do \ + { \ + auto ANGLE_LOCAL_VAR = rhs; \ + lhs = static_cast<typename std::decay<decltype(lhs)>::type>(ANGLE_LOCAL_VAR); \ + ASSERT(static_cast<decltype(ANGLE_LOCAL_VAR)>(lhs) == ANGLE_LOCAL_VAR); \ + } while (0) + +#endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_ |