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