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