• 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 "GLSLANG/ShaderLang.h"
19 #include "common/angleutils.h"
20 #include "common/utilities.h"
21 #include "libANGLE/angletypes.h"
22 
23 namespace angle
24 {
25 struct FeatureSetBase;
26 struct Format;
27 enum class FormatID;
28 }  // namespace angle
29 
30 namespace gl
31 {
32 struct FormatType;
33 struct InternalFormat;
34 class State;
35 }  // namespace gl
36 
37 namespace egl
38 {
39 class AttributeMap;
40 struct DisplayState;
41 }  // namespace egl
42 
43 namespace rx
44 {
45 class ContextImpl;
46 
47 // The possible rotations of the surface/draw framebuffer, particularly for the Vulkan back-end on
48 // Android.
49 enum class SurfaceRotation
50 {
51     Identity,
52     Rotated90Degrees,
53     Rotated180Degrees,
54     Rotated270Degrees,
55     FlippedIdentity,
56     FlippedRotated90Degrees,
57     FlippedRotated180Degrees,
58     FlippedRotated270Degrees,
59 
60     InvalidEnum,
61     EnumCount = InvalidEnum,
62 };
63 
64 using SpecConstUsageBits = angle::PackedEnumBitSet<sh::vk::SpecConstUsage, uint32_t>;
65 
66 void RotateRectangle(const SurfaceRotation rotation,
67                      const bool flipY,
68                      const int framebufferWidth,
69                      const int framebufferHeight,
70                      const gl::Rectangle &incoming,
71                      gl::Rectangle *outgoing);
72 
73 using MipGenerationFunction = void (*)(size_t sourceWidth,
74                                        size_t sourceHeight,
75                                        size_t sourceDepth,
76                                        const uint8_t *sourceData,
77                                        size_t sourceRowPitch,
78                                        size_t sourceDepthPitch,
79                                        uint8_t *destData,
80                                        size_t destRowPitch,
81                                        size_t destDepthPitch);
82 
83 typedef void (*PixelReadFunction)(const uint8_t *source, uint8_t *dest);
84 typedef void (*PixelWriteFunction)(const uint8_t *source, uint8_t *dest);
85 typedef void (*FastCopyFunction)(const uint8_t *source,
86                                  int srcXAxisPitch,
87                                  int srcYAxisPitch,
88                                  uint8_t *dest,
89                                  int destXAxisPitch,
90                                  int destYAxisPitch,
91                                  int width,
92                                  int height);
93 
94 class FastCopyFunctionMap
95 {
96   public:
97     struct Entry
98     {
99         angle::FormatID formatID;
100         FastCopyFunction func;
101     };
102 
FastCopyFunctionMap()103     constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
104 
FastCopyFunctionMap(const Entry * data,size_t size)105     constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
106 
107     bool has(angle::FormatID formatID) const;
108     FastCopyFunction get(angle::FormatID formatID) const;
109 
110   private:
111     size_t mSize;
112     const Entry *mData;
113 };
114 
115 struct PackPixelsParams
116 {
117     PackPixelsParams();
118     PackPixelsParams(const gl::Rectangle &area,
119                      const angle::Format &destFormat,
120                      GLuint outputPitch,
121                      bool reverseRowOrderIn,
122                      gl::Buffer *packBufferIn,
123                      ptrdiff_t offset);
124 
125     gl::Rectangle area;
126     const angle::Format *destFormat;
127     GLuint outputPitch;
128     gl::Buffer *packBuffer;
129     bool reverseRowOrder;
130     ptrdiff_t offset;
131     SurfaceRotation rotation;
132 };
133 
134 void PackPixels(const PackPixelsParams &params,
135                 const angle::Format &sourceFormat,
136                 int inputPitch,
137                 const uint8_t *source,
138                 uint8_t *destination);
139 
140 using InitializeTextureDataFunction = void (*)(size_t width,
141                                                size_t height,
142                                                size_t depth,
143                                                uint8_t *output,
144                                                size_t outputRowPitch,
145                                                size_t outputDepthPitch);
146 
147 using LoadImageFunction = void (*)(size_t width,
148                                    size_t height,
149                                    size_t depth,
150                                    const uint8_t *input,
151                                    size_t inputRowPitch,
152                                    size_t inputDepthPitch,
153                                    uint8_t *output,
154                                    size_t outputRowPitch,
155                                    size_t outputDepthPitch);
156 
157 struct LoadImageFunctionInfo
158 {
LoadImageFunctionInfoLoadImageFunctionInfo159     LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
LoadImageFunctionInfoLoadImageFunctionInfo160     LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
161         : loadFunction(loadFunction), requiresConversion(requiresConversion)
162     {}
163 
164     LoadImageFunction loadFunction;
165     bool requiresConversion;
166 };
167 
168 using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
169 
170 bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
171 
172 void CopyImageCHROMIUM(const uint8_t *sourceData,
173                        size_t sourceRowPitch,
174                        size_t sourcePixelBytes,
175                        size_t sourceDepthPitch,
176                        PixelReadFunction pixelReadFunction,
177                        uint8_t *destData,
178                        size_t destRowPitch,
179                        size_t destPixelBytes,
180                        size_t destDepthPitch,
181                        PixelWriteFunction pixelWriteFunction,
182                        GLenum destUnsizedFormat,
183                        GLenum destComponentType,
184                        size_t width,
185                        size_t height,
186                        size_t depth,
187                        bool unpackFlipY,
188                        bool unpackPremultiplyAlpha,
189                        bool unpackUnmultiplyAlpha);
190 
191 // Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
192 // This helper class encapsulates handling incomplete textures. Because the GL back-end
193 // can take advantage of the driver's incomplete textures, and because clearing multisample
194 // textures is so difficult, we can keep an instance of this class in the back-end instead
195 // of moving the logic to the Context front-end.
196 
197 // This interface allows us to call-back to init a multisample texture.
198 class MultisampleTextureInitializer
199 {
200   public:
~MultisampleTextureInitializer()201     virtual ~MultisampleTextureInitializer() {}
202     virtual angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
203                                                               gl::Texture *glTexture) = 0;
204 };
205 
206 class IncompleteTextureSet final : angle::NonCopyable
207 {
208   public:
209     IncompleteTextureSet();
210     ~IncompleteTextureSet();
211 
212     void onDestroy(const gl::Context *context);
213 
214     angle::Result getIncompleteTexture(const gl::Context *context,
215                                        gl::TextureType type,
216                                        gl::SamplerFormat format,
217                                        MultisampleTextureInitializer *multisampleInitializer,
218                                        gl::Texture **textureOut);
219 
220   private:
221     using TextureMapWithSamplerFormat = angle::PackedEnumMap<gl::SamplerFormat, gl::TextureMap>;
222 
223     TextureMapWithSamplerFormat mIncompleteTextures;
224     gl::Buffer *mIncompleteTextureBufferAttachment;
225 };
226 
227 // Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
228 // The return value indicate if the data was updated or not.
229 template <int cols, int rows>
230 struct SetFloatUniformMatrixGLSL
231 {
232     static void Run(unsigned int arrayElementOffset,
233                     unsigned int elementCount,
234                     GLsizei countIn,
235                     GLboolean transpose,
236                     const GLfloat *value,
237                     uint8_t *targetData);
238 };
239 
240 template <int cols, int rows>
241 struct SetFloatUniformMatrixHLSL
242 {
243     static void Run(unsigned int arrayElementOffset,
244                     unsigned int elementCount,
245                     GLsizei countIn,
246                     GLboolean transpose,
247                     const GLfloat *value,
248                     uint8_t *targetData);
249 };
250 
251 // Helper method to de-tranpose a matrix uniform for an API query.
252 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
253 
254 template <typename NonFloatT>
255 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose);
256 
257 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type);
258 
259 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
260                                  const gl::IndexRange &indexRange,
261                                  GLint baseVertex,
262                                  GLint *firstVertexOut);
263 
264 angle::Result GetVertexRangeInfo(const gl::Context *context,
265                                  GLint firstVertex,
266                                  GLsizei vertexOrIndexCount,
267                                  gl::DrawElementsType indexTypeOrInvalid,
268                                  const void *indices,
269                                  GLint baseVertex,
270                                  GLint *startVertexOut,
271                                  size_t *vertexCountOut);
272 
273 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY);
274 
275 // Helper method to intialize a FeatureSet with overrides from the DisplayState
276 void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state);
277 
278 template <typename In>
LineLoopRestartIndexCountHelper(GLsizei indexCount,const uint8_t * srcPtr)279 uint32_t LineLoopRestartIndexCountHelper(GLsizei indexCount, const uint8_t *srcPtr)
280 {
281     constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
282     const In *inIndices       = reinterpret_cast<const In *>(srcPtr);
283     uint32_t numIndices       = 0;
284     // See CopyLineLoopIndicesWithRestart() below for more info on how
285     // numIndices is calculated.
286     GLsizei loopStartIndex = 0;
287     for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
288     {
289         In vertex = inIndices[curIndex];
290         if (vertex != restartIndex)
291         {
292             numIndices++;
293         }
294         else
295         {
296             if (curIndex > loopStartIndex)
297             {
298                 numIndices += 2;
299             }
300             loopStartIndex = curIndex + 1;
301         }
302     }
303     if (indexCount > loopStartIndex)
304     {
305         numIndices++;
306     }
307     return numIndices;
308 }
309 
GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr)310 inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,
311                                                  GLsizei indexCount,
312                                                  const uint8_t *srcPtr)
313 {
314     switch (glIndexType)
315     {
316         case gl::DrawElementsType::UnsignedByte:
317             return LineLoopRestartIndexCountHelper<uint8_t>(indexCount, srcPtr);
318         case gl::DrawElementsType::UnsignedShort:
319             return LineLoopRestartIndexCountHelper<uint16_t>(indexCount, srcPtr);
320         case gl::DrawElementsType::UnsignedInt:
321             return LineLoopRestartIndexCountHelper<uint32_t>(indexCount, srcPtr);
322         default:
323             UNREACHABLE();
324             return 0;
325     }
326 }
327 
328 // Writes the line-strip vertices for a line loop to outPtr,
329 // where outLimit is calculated as in GetPrimitiveRestartIndexCount.
330 template <typename In, typename Out>
CopyLineLoopIndicesWithRestart(GLsizei indexCount,const uint8_t * srcPtr,uint8_t * outPtr)331 void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr)
332 {
333     constexpr In restartIndex     = gl::GetPrimitiveRestartIndexFromType<In>();
334     constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType<Out>();
335     const In *inIndices           = reinterpret_cast<const In *>(srcPtr);
336     Out *outIndices               = reinterpret_cast<Out *>(outPtr);
337     GLsizei loopStartIndex        = 0;
338     for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
339     {
340         In vertex = inIndices[curIndex];
341         if (vertex != restartIndex)
342         {
343             *(outIndices++) = static_cast<Out>(vertex);
344         }
345         else
346         {
347             if (curIndex > loopStartIndex)
348             {
349                 // Emit an extra vertex only if the loop is not empty.
350                 *(outIndices++) = inIndices[loopStartIndex];
351                 // Then restart the strip.
352                 *(outIndices++) = outRestartIndex;
353             }
354             loopStartIndex = curIndex + 1;
355         }
356     }
357     if (indexCount > loopStartIndex)
358     {
359         // Close the last loop if not empty.
360         *(outIndices++) = inIndices[loopStartIndex];
361     }
362 }
363 
364 void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
365 
366 angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
367                                      const gl::Context *context,
368                                      gl::PrimitiveMode mode,
369                                      const GLint *firsts,
370                                      const GLsizei *counts,
371                                      GLsizei drawcount);
372 angle::Result MultiDrawArraysIndirectGeneral(ContextImpl *contextImpl,
373                                              const gl::Context *context,
374                                              gl::PrimitiveMode mode,
375                                              const void *indirect,
376                                              GLsizei drawcount,
377                                              GLsizei stride);
378 angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
379                                               const gl::Context *context,
380                                               gl::PrimitiveMode mode,
381                                               const GLint *firsts,
382                                               const GLsizei *counts,
383                                               const GLsizei *instanceCounts,
384                                               GLsizei drawcount);
385 angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
386                                        const gl::Context *context,
387                                        gl::PrimitiveMode mode,
388                                        const GLsizei *counts,
389                                        gl::DrawElementsType type,
390                                        const GLvoid *const *indices,
391                                        GLsizei drawcount);
392 angle::Result MultiDrawElementsIndirectGeneral(ContextImpl *contextImpl,
393                                                const gl::Context *context,
394                                                gl::PrimitiveMode mode,
395                                                gl::DrawElementsType type,
396                                                const void *indirect,
397                                                GLsizei drawcount,
398                                                GLsizei stride);
399 angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
400                                                 const gl::Context *context,
401                                                 gl::PrimitiveMode mode,
402                                                 const GLsizei *counts,
403                                                 gl::DrawElementsType type,
404                                                 const GLvoid *const *indices,
405                                                 const GLsizei *instanceCounts,
406                                                 GLsizei drawcount);
407 angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
408                                                           const gl::Context *context,
409                                                           gl::PrimitiveMode mode,
410                                                           const GLint *firsts,
411                                                           const GLsizei *counts,
412                                                           const GLsizei *instanceCounts,
413                                                           const GLuint *baseInstances,
414                                                           GLsizei drawcount);
415 angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
416                                                                       const gl::Context *context,
417                                                                       gl::PrimitiveMode mode,
418                                                                       const GLsizei *counts,
419                                                                       gl::DrawElementsType type,
420                                                                       const GLvoid *const *indices,
421                                                                       const GLsizei *instanceCounts,
422                                                                       const GLint *baseVertices,
423                                                                       const GLuint *baseInstances,
424                                                                       GLsizei drawcount);
425 
426 // RAII object making sure reset uniforms is called no matter whether there's an error in draw calls
427 class ResetBaseVertexBaseInstance : angle::NonCopyable
428 {
429   public:
430     ResetBaseVertexBaseInstance(gl::Program *programObject,
431                                 bool resetBaseVertex,
432                                 bool resetBaseInstance);
433 
434     ~ResetBaseVertexBaseInstance();
435 
436   private:
437     gl::Program *mProgramObject;
438     bool mResetBaseVertex;
439     bool mResetBaseInstance;
440 };
441 
442 angle::FormatID ConvertToSRGB(angle::FormatID formatID);
443 angle::FormatID ConvertToLinear(angle::FormatID formatID);
444 bool IsOverridableLinearFormat(angle::FormatID formatID);
445 
446 enum class PipelineType
447 {
448     Graphics = 0,
449     Compute  = 1,
450 
451     InvalidEnum = 2,
452     EnumCount   = 2,
453 };
454 }  // namespace rx
455 
456 // MultiDraw macro patterns
457 // These macros are to avoid too much code duplication as we don't want to have if detect for
458 // hasDrawID/BaseVertex/BaseInstance inside for loop in a multiDrawANGLE call Part of these are put
459 // in the header as we want to share with specialized context impl on some platforms for multidraw
460 #define ANGLE_SET_DRAW_ID_UNIFORM_0(drawID) \
461     {}
462 #define ANGLE_SET_DRAW_ID_UNIFORM_1(drawID) programObject->setDrawIDUniform(drawID)
463 #define ANGLE_SET_DRAW_ID_UNIFORM(cond) ANGLE_SET_DRAW_ID_UNIFORM_##cond
464 
465 #define ANGLE_SET_BASE_VERTEX_UNIFORM_0(baseVertex) \
466     {}
467 #define ANGLE_SET_BASE_VERTEX_UNIFORM_1(baseVertex) programObject->setBaseVertexUniform(baseVertex);
468 #define ANGLE_SET_BASE_VERTEX_UNIFORM(cond) ANGLE_SET_BASE_VERTEX_UNIFORM_##cond
469 
470 #define ANGLE_SET_BASE_INSTANCE_UNIFORM_0(baseInstance) \
471     {}
472 #define ANGLE_SET_BASE_INSTANCE_UNIFORM_1(baseInstance) \
473     programObject->setBaseInstanceUniform(baseInstance)
474 #define ANGLE_SET_BASE_INSTANCE_UNIFORM(cond) ANGLE_SET_BASE_INSTANCE_UNIFORM_##cond
475 
476 #define ANGLE_NOOP_DRAW_ context->noopDraw(mode, counts[drawID])
477 #define ANGLE_NOOP_DRAW_INSTANCED \
478     context->noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID])
479 #define ANGLE_NOOP_DRAW(_instanced) ANGLE_NOOP_DRAW##_instanced
480 
481 #define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE_ \
482     gl::MarkTransformFeedbackBufferUsage(context, counts[drawID], 1)
483 #define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE_INSTANCED \
484     gl::MarkTransformFeedbackBufferUsage(context, counts[drawID], instanceCounts[drawID])
485 #define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced) \
486     ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE##instanced
487 
488 #endif  // LIBANGLE_RENDERER_RENDERER_UTILS_H_
489