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