• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // renderer_utils:
7 //   Helper methods pertaining to most or all back-ends.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_RENDERER_UTILS_H_
11 #define LIBANGLE_RENDERER_RENDERER_UTILS_H_
12 
13 #include <cstdint>
14 
15 #include <limits>
16 #include <map>
17 
18 #include "common/angleutils.h"
19 #include "common/utilities.h"
20 #include "libANGLE/angletypes.h"
21 
22 namespace angle
23 {
24 struct FeatureSetBase;
25 struct Format;
26 enum class FormatID;
27 }  // namespace angle
28 
29 namespace gl
30 {
31 struct FormatType;
32 struct InternalFormat;
33 class State;
34 }  // namespace gl
35 
36 namespace egl
37 {
38 class AttributeMap;
39 struct DisplayState;
40 }  // namespace egl
41 
42 namespace rx
43 {
44 class ContextImpl;
45 
46 using MipGenerationFunction = void (*)(size_t sourceWidth,
47                                        size_t sourceHeight,
48                                        size_t sourceDepth,
49                                        const uint8_t *sourceData,
50                                        size_t sourceRowPitch,
51                                        size_t sourceDepthPitch,
52                                        uint8_t *destData,
53                                        size_t destRowPitch,
54                                        size_t destDepthPitch);
55 
56 typedef void (*PixelReadFunction)(const uint8_t *source, uint8_t *dest);
57 typedef void (*PixelWriteFunction)(const uint8_t *source, uint8_t *dest);
58 typedef void (*PixelCopyFunction)(const uint8_t *source, uint8_t *dest);
59 
60 class FastCopyFunctionMap
61 {
62   public:
63     struct Entry
64     {
65         angle::FormatID formatID;
66         PixelCopyFunction func;
67     };
68 
FastCopyFunctionMap()69     constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
70 
FastCopyFunctionMap(const Entry * data,size_t size)71     constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
72 
73     bool has(angle::FormatID formatID) const;
74     PixelCopyFunction get(angle::FormatID formatID) const;
75 
76   private:
77     size_t mSize;
78     const Entry *mData;
79 };
80 
81 struct PackPixelsParams
82 {
83     PackPixelsParams();
84     PackPixelsParams(const gl::Rectangle &area,
85                      const angle::Format &destFormat,
86                      GLuint outputPitch,
87                      bool reverseRowOrderIn,
88                      gl::Buffer *packBufferIn,
89                      ptrdiff_t offset);
90 
91     gl::Rectangle area;
92     const angle::Format *destFormat;
93     GLuint outputPitch;
94     gl::Buffer *packBuffer;
95     bool reverseRowOrder;
96     ptrdiff_t offset;
97 };
98 
99 void PackPixels(const PackPixelsParams &params,
100                 const angle::Format &sourceFormat,
101                 int inputPitch,
102                 const uint8_t *source,
103                 uint8_t *destination);
104 
105 using InitializeTextureDataFunction = void (*)(size_t width,
106                                                size_t height,
107                                                size_t depth,
108                                                uint8_t *output,
109                                                size_t outputRowPitch,
110                                                size_t outputDepthPitch);
111 
112 using LoadImageFunction = void (*)(size_t width,
113                                    size_t height,
114                                    size_t depth,
115                                    const uint8_t *input,
116                                    size_t inputRowPitch,
117                                    size_t inputDepthPitch,
118                                    uint8_t *output,
119                                    size_t outputRowPitch,
120                                    size_t outputDepthPitch);
121 
122 struct LoadImageFunctionInfo
123 {
LoadImageFunctionInfoLoadImageFunctionInfo124     LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
LoadImageFunctionInfoLoadImageFunctionInfo125     LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
126         : loadFunction(loadFunction), requiresConversion(requiresConversion)
127     {}
128 
129     LoadImageFunction loadFunction;
130     bool requiresConversion;
131 };
132 
133 using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
134 
135 bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
136 bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
137 
138 void CopyImageCHROMIUM(const uint8_t *sourceData,
139                        size_t sourceRowPitch,
140                        size_t sourcePixelBytes,
141                        size_t sourceDepthPitch,
142                        PixelReadFunction pixelReadFunction,
143                        uint8_t *destData,
144                        size_t destRowPitch,
145                        size_t destPixelBytes,
146                        size_t destDepthPitch,
147                        PixelWriteFunction pixelWriteFunction,
148                        GLenum destUnsizedFormat,
149                        GLenum destComponentType,
150                        size_t width,
151                        size_t height,
152                        size_t depth,
153                        bool unpackFlipY,
154                        bool unpackPremultiplyAlpha,
155                        bool unpackUnmultiplyAlpha);
156 
157 // Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
158 // This helper class encapsulates handling incomplete textures. Because the GL back-end
159 // can take advantage of the driver's incomplete textures, and because clearing multisample
160 // textures is so difficult, we can keep an instance of this class in the back-end instead
161 // of moving the logic to the Context front-end.
162 
163 // This interface allows us to call-back to init a multisample texture.
164 class MultisampleTextureInitializer
165 {
166   public:
~MultisampleTextureInitializer()167     virtual ~MultisampleTextureInitializer() {}
168     virtual angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
169                                                               gl::Texture *glTexture) = 0;
170 };
171 
172 class IncompleteTextureSet final : angle::NonCopyable
173 {
174   public:
175     IncompleteTextureSet();
176     ~IncompleteTextureSet();
177 
178     void onDestroy(const gl::Context *context);
179 
180     angle::Result getIncompleteTexture(const gl::Context *context,
181                                        gl::TextureType type,
182                                        MultisampleTextureInitializer *multisampleInitializer,
183                                        gl::Texture **textureOut);
184 
185   private:
186     gl::TextureMap mIncompleteTextures;
187 };
188 
189 // Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
190 // The return value indicate if the data was updated or not.
191 template <int cols, int rows>
192 struct SetFloatUniformMatrixGLSL
193 {
194     static void Run(unsigned int arrayElementOffset,
195                     unsigned int elementCount,
196                     GLsizei countIn,
197                     GLboolean transpose,
198                     const GLfloat *value,
199                     uint8_t *targetData);
200 };
201 
202 template <int cols, int rows>
203 struct SetFloatUniformMatrixHLSL
204 {
205     static void Run(unsigned int arrayElementOffset,
206                     unsigned int elementCount,
207                     GLsizei countIn,
208                     GLboolean transpose,
209                     const GLfloat *value,
210                     uint8_t *targetData);
211 };
212 
213 // Helper method to de-tranpose a matrix uniform for an API query.
214 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
215 
216 template <typename NonFloatT>
217 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose);
218 
219 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type);
220 
221 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
222                                  const gl::IndexRange &indexRange,
223                                  GLint baseVertex,
224                                  GLint *firstVertexOut);
225 
226 angle::Result GetVertexRangeInfo(const gl::Context *context,
227                                  GLint firstVertex,
228                                  GLsizei vertexOrIndexCount,
229                                  gl::DrawElementsType indexTypeOrInvalid,
230                                  const void *indices,
231                                  GLint baseVertex,
232                                  GLint *startVertexOut,
233                                  size_t *vertexCountOut);
234 
235 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY);
236 
237 // Helper method to intialize a FeatureSet with overrides from the DisplayState
238 void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state);
239 
240 template <typename In>
LineLoopRestartIndexCountHelper(GLsizei indexCount,const uint8_t * srcPtr)241 uint32_t LineLoopRestartIndexCountHelper(GLsizei indexCount, const uint8_t *srcPtr)
242 {
243     constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
244     const In *inIndices       = reinterpret_cast<const In *>(srcPtr);
245     uint32_t numIndices       = 0;
246     // See CopyLineLoopIndicesWithRestart() below for more info on how
247     // numIndices is calculated.
248     GLsizei loopStartIndex = 0;
249     for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
250     {
251         In vertex = inIndices[curIndex];
252         if (vertex != restartIndex)
253         {
254             numIndices++;
255         }
256         else
257         {
258             if (curIndex > loopStartIndex)
259             {
260                 numIndices += 2;
261             }
262             loopStartIndex = curIndex + 1;
263         }
264     }
265     if (indexCount > loopStartIndex)
266     {
267         numIndices++;
268     }
269     return numIndices;
270 }
271 
GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr)272 inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,
273                                                  GLsizei indexCount,
274                                                  const uint8_t *srcPtr)
275 {
276     switch (glIndexType)
277     {
278         case gl::DrawElementsType::UnsignedByte:
279             return LineLoopRestartIndexCountHelper<uint8_t>(indexCount, srcPtr);
280         case gl::DrawElementsType::UnsignedShort:
281             return LineLoopRestartIndexCountHelper<uint16_t>(indexCount, srcPtr);
282         case gl::DrawElementsType::UnsignedInt:
283             return LineLoopRestartIndexCountHelper<uint32_t>(indexCount, srcPtr);
284         default:
285             UNREACHABLE();
286             return 0;
287     }
288 }
289 
290 // Writes the line-strip vertices for a line loop to outPtr,
291 // where outLimit is calculated as in GetPrimitiveRestartIndexCount.
292 template <typename In, typename Out>
CopyLineLoopIndicesWithRestart(GLsizei indexCount,const uint8_t * srcPtr,uint8_t * outPtr)293 void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr)
294 {
295     constexpr In restartIndex     = gl::GetPrimitiveRestartIndexFromType<In>();
296     constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType<Out>();
297     const In *inIndices           = reinterpret_cast<const In *>(srcPtr);
298     Out *outIndices               = reinterpret_cast<Out *>(outPtr);
299     GLsizei loopStartIndex        = 0;
300     for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
301     {
302         In vertex = inIndices[curIndex];
303         if (vertex != restartIndex)
304         {
305             *(outIndices++) = static_cast<Out>(vertex);
306         }
307         else
308         {
309             if (curIndex > loopStartIndex)
310             {
311                 // Emit an extra vertex only if the loop is not empty.
312                 *(outIndices++) = inIndices[loopStartIndex];
313                 // Then restart the strip.
314                 *(outIndices++) = outRestartIndex;
315             }
316             loopStartIndex = curIndex + 1;
317         }
318     }
319     if (indexCount > loopStartIndex)
320     {
321         // Close the last loop if not empty.
322         *(outIndices++) = inIndices[loopStartIndex];
323     }
324 }
325 
326 void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
327 }  // namespace rx
328 
329 #endif  // LIBANGLE_RENDERER_RENDERER_UTILS_H_
330