• 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 <atomic>
16 #include <limits>
17 #include <map>
18 
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 class ResourceSerial
48 {
49   public:
ResourceSerial()50     constexpr ResourceSerial() : mValue(kDirty) {}
ResourceSerial(uintptr_t value)51     explicit constexpr ResourceSerial(uintptr_t value) : mValue(value) {}
52     constexpr bool operator==(ResourceSerial other) const { return mValue == other.mValue; }
53     constexpr bool operator!=(ResourceSerial other) const { return mValue != other.mValue; }
54 
dirty()55     void dirty() { mValue = kDirty; }
clear()56     void clear() { mValue = kEmpty; }
57 
valid()58     constexpr bool valid() const { return mValue != kEmpty && mValue != kDirty; }
empty()59     constexpr bool empty() const { return mValue == kEmpty; }
60 
61   private:
62     constexpr static uintptr_t kDirty = std::numeric_limits<uintptr_t>::max();
63     constexpr static uintptr_t kEmpty = 0;
64 
65     uintptr_t mValue;
66 };
67 
68 class Serial final
69 {
70   public:
Serial()71     constexpr Serial() : mValue(kInvalid) {}
72     constexpr Serial(const Serial &other) = default;
73     Serial &operator=(const Serial &other) = default;
74 
75     constexpr bool operator==(const Serial &other) const
76     {
77         return mValue != kInvalid && mValue == other.mValue;
78     }
79     constexpr bool operator==(uint32_t value) const
80     {
81         return mValue != kInvalid && mValue == static_cast<uint64_t>(value);
82     }
83     constexpr bool operator!=(const Serial &other) const
84     {
85         return mValue == kInvalid || mValue != other.mValue;
86     }
87     constexpr bool operator>(const Serial &other) const { return mValue > other.mValue; }
88     constexpr bool operator>=(const Serial &other) const { return mValue >= other.mValue; }
89     constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; }
90     constexpr bool operator<=(const Serial &other) const { return mValue <= other.mValue; }
91 
92     constexpr bool operator<(uint32_t value) const { return mValue < static_cast<uint64_t>(value); }
93 
94     // Useful for serialization.
getValue()95     constexpr uint64_t getValue() const { return mValue; }
96 
97   private:
98     template <typename T>
99     friend class SerialFactoryBase;
Serial(uint64_t value)100     constexpr explicit Serial(uint64_t value) : mValue(value) {}
101     uint64_t mValue;
102     static constexpr uint64_t kInvalid = 0;
103 };
104 
105 template <typename SerialBaseType>
106 class SerialFactoryBase final : angle::NonCopyable
107 {
108   public:
SerialFactoryBase()109     SerialFactoryBase() : mSerial(1) {}
110 
generate()111     Serial generate()
112     {
113         ASSERT(mSerial + 1 > mSerial);
114         return Serial(mSerial++);
115     }
116 
117   private:
118     SerialBaseType mSerial;
119 };
120 
121 using SerialFactory       = SerialFactoryBase<uint64_t>;
122 using AtomicSerialFactory = SerialFactoryBase<std::atomic<uint64_t>>;
123 
124 using MipGenerationFunction = void (*)(size_t sourceWidth,
125                                        size_t sourceHeight,
126                                        size_t sourceDepth,
127                                        const uint8_t *sourceData,
128                                        size_t sourceRowPitch,
129                                        size_t sourceDepthPitch,
130                                        uint8_t *destData,
131                                        size_t destRowPitch,
132                                        size_t destDepthPitch);
133 
134 typedef void (*PixelReadFunction)(const uint8_t *source, uint8_t *dest);
135 typedef void (*PixelWriteFunction)(const uint8_t *source, uint8_t *dest);
136 typedef void (*PixelCopyFunction)(const uint8_t *source, uint8_t *dest);
137 
138 class FastCopyFunctionMap
139 {
140   public:
141     struct Entry
142     {
143         angle::FormatID formatID;
144         PixelCopyFunction func;
145     };
146 
FastCopyFunctionMap()147     constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
148 
FastCopyFunctionMap(const Entry * data,size_t size)149     constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
150 
151     bool has(angle::FormatID formatID) const;
152     PixelCopyFunction get(angle::FormatID formatID) const;
153 
154   private:
155     size_t mSize;
156     const Entry *mData;
157 };
158 
159 struct PackPixelsParams
160 {
161     PackPixelsParams();
162     PackPixelsParams(const gl::Rectangle &area,
163                      const angle::Format &destFormat,
164                      GLuint outputPitch,
165                      bool reverseRowOrderIn,
166                      gl::Buffer *packBufferIn,
167                      ptrdiff_t offset);
168 
169     gl::Rectangle area;
170     const angle::Format *destFormat;
171     GLuint outputPitch;
172     gl::Buffer *packBuffer;
173     bool reverseRowOrder;
174     ptrdiff_t offset;
175 };
176 
177 void PackPixels(const PackPixelsParams &params,
178                 const angle::Format &sourceFormat,
179                 int inputPitch,
180                 const uint8_t *source,
181                 uint8_t *destination);
182 
183 using InitializeTextureDataFunction = void (*)(size_t width,
184                                                size_t height,
185                                                size_t depth,
186                                                uint8_t *output,
187                                                size_t outputRowPitch,
188                                                size_t outputDepthPitch);
189 
190 using LoadImageFunction = void (*)(size_t width,
191                                    size_t height,
192                                    size_t depth,
193                                    const uint8_t *input,
194                                    size_t inputRowPitch,
195                                    size_t inputDepthPitch,
196                                    uint8_t *output,
197                                    size_t outputRowPitch,
198                                    size_t outputDepthPitch);
199 
200 struct LoadImageFunctionInfo
201 {
LoadImageFunctionInfoLoadImageFunctionInfo202     LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
LoadImageFunctionInfoLoadImageFunctionInfo203     LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
204         : loadFunction(loadFunction), requiresConversion(requiresConversion)
205     {}
206 
207     LoadImageFunction loadFunction;
208     bool requiresConversion;
209 };
210 
211 using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
212 
213 bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
214 bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
215 
216 void CopyImageCHROMIUM(const uint8_t *sourceData,
217                        size_t sourceRowPitch,
218                        size_t sourcePixelBytes,
219                        size_t sourceDepthPitch,
220                        PixelReadFunction pixelReadFunction,
221                        uint8_t *destData,
222                        size_t destRowPitch,
223                        size_t destPixelBytes,
224                        size_t destDepthPitch,
225                        PixelWriteFunction pixelWriteFunction,
226                        GLenum destUnsizedFormat,
227                        GLenum destComponentType,
228                        size_t width,
229                        size_t height,
230                        size_t depth,
231                        bool unpackFlipY,
232                        bool unpackPremultiplyAlpha,
233                        bool unpackUnmultiplyAlpha);
234 
235 // Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
236 // This helper class encapsulates handling incomplete textures. Because the GL back-end
237 // can take advantage of the driver's incomplete textures, and because clearing multisample
238 // textures is so difficult, we can keep an instance of this class in the back-end instead
239 // of moving the logic to the Context front-end.
240 
241 // This interface allows us to call-back to init a multisample texture.
242 class MultisampleTextureInitializer
243 {
244   public:
~MultisampleTextureInitializer()245     virtual ~MultisampleTextureInitializer() {}
246     virtual angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
247                                                               gl::Texture *glTexture) = 0;
248 };
249 
250 class IncompleteTextureSet final : angle::NonCopyable
251 {
252   public:
253     IncompleteTextureSet();
254     ~IncompleteTextureSet();
255 
256     void onDestroy(const gl::Context *context);
257 
258     angle::Result getIncompleteTexture(const gl::Context *context,
259                                        gl::TextureType type,
260                                        MultisampleTextureInitializer *multisampleInitializer,
261                                        gl::Texture **textureOut);
262 
263   private:
264     gl::TextureMap mIncompleteTextures;
265 };
266 
267 // Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
268 // The return value indicate if the data was updated or not.
269 template <int cols, int rows>
270 struct SetFloatUniformMatrixGLSL
271 {
272     static void Run(unsigned int arrayElementOffset,
273                     unsigned int elementCount,
274                     GLsizei countIn,
275                     GLboolean transpose,
276                     const GLfloat *value,
277                     uint8_t *targetData);
278 };
279 
280 template <int cols, int rows>
281 struct SetFloatUniformMatrixHLSL
282 {
283     static void Run(unsigned int arrayElementOffset,
284                     unsigned int elementCount,
285                     GLsizei countIn,
286                     GLboolean transpose,
287                     const GLfloat *value,
288                     uint8_t *targetData);
289 };
290 
291 // Helper method to de-tranpose a matrix uniform for an API query.
292 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
293 
294 template <typename NonFloatT>
295 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose);
296 
297 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type);
298 
299 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
300                                  const gl::IndexRange &indexRange,
301                                  GLint baseVertex,
302                                  GLint *firstVertexOut);
303 
304 angle::Result GetVertexRangeInfo(const gl::Context *context,
305                                  GLint firstVertex,
306                                  GLsizei vertexOrIndexCount,
307                                  gl::DrawElementsType indexTypeOrInvalid,
308                                  const void *indices,
309                                  GLint baseVertex,
310                                  GLint *startVertexOut,
311                                  size_t *vertexCountOut);
312 
313 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY);
314 
315 // Helper method to intialize a FeatureSet with overrides from the DisplayState
316 void OverrideFeaturesWithDisplayState(angle::FeatureSetBase *features,
317                                       const egl::DisplayState &state);
318 
319 template <typename In>
LineLoopRestartIndexCountHelper(GLsizei indexCount,const uint8_t * srcPtr)320 uint32_t LineLoopRestartIndexCountHelper(GLsizei indexCount, const uint8_t *srcPtr)
321 {
322     constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
323     const In *inIndices       = reinterpret_cast<const In *>(srcPtr);
324     uint32_t numIndices       = 0;
325     // See CopyLineLoopIndicesWithRestart() below for more info on how
326     // numIndices is calculated.
327     GLsizei loopStartIndex = 0;
328     for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
329     {
330         In vertex = inIndices[curIndex];
331         if (vertex != restartIndex)
332         {
333             numIndices++;
334         }
335         else
336         {
337             if (curIndex > loopStartIndex)
338             {
339                 numIndices += 2;
340             }
341             loopStartIndex = curIndex + 1;
342         }
343     }
344     if (indexCount > loopStartIndex)
345     {
346         numIndices++;
347     }
348     return numIndices;
349 }
350 
GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr)351 inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,
352                                                  GLsizei indexCount,
353                                                  const uint8_t *srcPtr)
354 {
355     switch (glIndexType)
356     {
357         case gl::DrawElementsType::UnsignedByte:
358             return LineLoopRestartIndexCountHelper<uint8_t>(indexCount, srcPtr);
359         case gl::DrawElementsType::UnsignedShort:
360             return LineLoopRestartIndexCountHelper<uint16_t>(indexCount, srcPtr);
361         case gl::DrawElementsType::UnsignedInt:
362             return LineLoopRestartIndexCountHelper<uint32_t>(indexCount, srcPtr);
363         default:
364             UNREACHABLE();
365             return 0;
366     }
367 }
368 
369 // Writes the line-strip vertices for a line loop to outPtr,
370 // where outLimit is calculated as in GetPrimitiveRestartIndexCount.
371 template <typename In, typename Out>
CopyLineLoopIndicesWithRestart(GLsizei indexCount,const uint8_t * srcPtr,uint8_t * outPtr)372 void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr)
373 {
374     constexpr In restartIndex     = gl::GetPrimitiveRestartIndexFromType<In>();
375     constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType<Out>();
376     const In *inIndices           = reinterpret_cast<const In *>(srcPtr);
377     Out *outIndices               = reinterpret_cast<Out *>(outPtr);
378     GLsizei loopStartIndex        = 0;
379     for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
380     {
381         In vertex = inIndices[curIndex];
382         if (vertex != restartIndex)
383         {
384             *(outIndices++) = static_cast<Out>(vertex);
385         }
386         else
387         {
388             if (curIndex > loopStartIndex)
389             {
390                 // Emit an extra vertex only if the loop is not empty.
391                 *(outIndices++) = inIndices[loopStartIndex];
392                 // Then restart the strip.
393                 *(outIndices++) = outRestartIndex;
394             }
395             loopStartIndex = curIndex + 1;
396         }
397     }
398     if (indexCount > loopStartIndex)
399     {
400         // Close the last loop if not empty.
401         *(outIndices++) = inIndices[loopStartIndex];
402     }
403 }
404 }  // namespace rx
405 
406 #endif  // LIBANGLE_RENDERER_RENDERER_UTILS_H_
407