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 "common/angleutils.h"
19 #include "common/utilities.h"
20 #include "libANGLE/angletypes.h"
21
22 namespace angle
23 {
24 struct FeatureSetBase;
25 struct Format;
26 enum class FormatID;
27 } // namespace angle
28
29 namespace gl
30 {
31 struct FormatType;
32 struct InternalFormat;
33 class State;
34 } // namespace gl
35
36 namespace egl
37 {
38 class AttributeMap;
39 struct DisplayState;
40 } // namespace egl
41
42 namespace rx
43 {
44 class ContextImpl;
45
46 // The possible rotations of the surface/draw framebuffer, particularly for the Vulkan back-end on
47 // Android.
48 enum class SurfaceRotation
49 {
50 Identity,
51 Rotated90Degrees,
52 Rotated180Degrees,
53 Rotated270Degrees,
54 FlippedIdentity,
55 FlippedRotated90Degrees,
56 FlippedRotated180Degrees,
57 FlippedRotated270Degrees,
58
59 InvalidEnum,
60 EnumCount = InvalidEnum,
61 };
62
63 void RotateRectangle(const SurfaceRotation rotation,
64 const bool flipY,
65 const int framebufferWidth,
66 const int framebufferHeight,
67 const gl::Rectangle &incoming,
68 gl::Rectangle *outgoing);
69
70 using MipGenerationFunction = void (*)(size_t sourceWidth,
71 size_t sourceHeight,
72 size_t sourceDepth,
73 const uint8_t *sourceData,
74 size_t sourceRowPitch,
75 size_t sourceDepthPitch,
76 uint8_t *destData,
77 size_t destRowPitch,
78 size_t destDepthPitch);
79
80 typedef void (*PixelReadFunction)(const uint8_t *source, uint8_t *dest);
81 typedef void (*PixelWriteFunction)(const uint8_t *source, uint8_t *dest);
82 typedef void (*PixelCopyFunction)(const uint8_t *source, uint8_t *dest);
83
84 class FastCopyFunctionMap
85 {
86 public:
87 struct Entry
88 {
89 angle::FormatID formatID;
90 PixelCopyFunction func;
91 };
92
FastCopyFunctionMap()93 constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
94
FastCopyFunctionMap(const Entry * data,size_t size)95 constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
96
97 bool has(angle::FormatID formatID) const;
98 PixelCopyFunction get(angle::FormatID formatID) const;
99
100 private:
101 size_t mSize;
102 const Entry *mData;
103 };
104
105 struct PackPixelsParams
106 {
107 PackPixelsParams();
108 PackPixelsParams(const gl::Rectangle &area,
109 const angle::Format &destFormat,
110 GLuint outputPitch,
111 bool reverseRowOrderIn,
112 gl::Buffer *packBufferIn,
113 ptrdiff_t offset);
114
115 gl::Rectangle area;
116 const angle::Format *destFormat;
117 GLuint outputPitch;
118 gl::Buffer *packBuffer;
119 bool reverseRowOrder;
120 ptrdiff_t offset;
121 SurfaceRotation rotation;
122 };
123
124 void PackPixels(const PackPixelsParams ¶ms,
125 const angle::Format &sourceFormat,
126 int inputPitch,
127 const uint8_t *source,
128 uint8_t *destination);
129
130 using InitializeTextureDataFunction = void (*)(size_t width,
131 size_t height,
132 size_t depth,
133 uint8_t *output,
134 size_t outputRowPitch,
135 size_t outputDepthPitch);
136
137 using LoadImageFunction = void (*)(size_t width,
138 size_t height,
139 size_t depth,
140 const uint8_t *input,
141 size_t inputRowPitch,
142 size_t inputDepthPitch,
143 uint8_t *output,
144 size_t outputRowPitch,
145 size_t outputDepthPitch);
146
147 struct LoadImageFunctionInfo
148 {
LoadImageFunctionInfoLoadImageFunctionInfo149 LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
LoadImageFunctionInfoLoadImageFunctionInfo150 LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
151 : loadFunction(loadFunction), requiresConversion(requiresConversion)
152 {}
153
154 LoadImageFunction loadFunction;
155 bool requiresConversion;
156 };
157
158 using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
159
160 bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
161 bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
162
163 void CopyImageCHROMIUM(const uint8_t *sourceData,
164 size_t sourceRowPitch,
165 size_t sourcePixelBytes,
166 size_t sourceDepthPitch,
167 PixelReadFunction pixelReadFunction,
168 uint8_t *destData,
169 size_t destRowPitch,
170 size_t destPixelBytes,
171 size_t destDepthPitch,
172 PixelWriteFunction pixelWriteFunction,
173 GLenum destUnsizedFormat,
174 GLenum destComponentType,
175 size_t width,
176 size_t height,
177 size_t depth,
178 bool unpackFlipY,
179 bool unpackPremultiplyAlpha,
180 bool unpackUnmultiplyAlpha);
181
182 // Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
183 // This helper class encapsulates handling incomplete textures. Because the GL back-end
184 // can take advantage of the driver's incomplete textures, and because clearing multisample
185 // textures is so difficult, we can keep an instance of this class in the back-end instead
186 // of moving the logic to the Context front-end.
187
188 // This interface allows us to call-back to init a multisample texture.
189 class MultisampleTextureInitializer
190 {
191 public:
~MultisampleTextureInitializer()192 virtual ~MultisampleTextureInitializer() {}
193 virtual angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
194 gl::Texture *glTexture) = 0;
195 };
196
197 class IncompleteTextureSet final : angle::NonCopyable
198 {
199 public:
200 IncompleteTextureSet();
201 ~IncompleteTextureSet();
202
203 void onDestroy(const gl::Context *context);
204
205 angle::Result getIncompleteTexture(const gl::Context *context,
206 gl::TextureType type,
207 MultisampleTextureInitializer *multisampleInitializer,
208 gl::Texture **textureOut);
209
210 private:
211 gl::TextureMap mIncompleteTextures;
212 };
213
214 // Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
215 // The return value indicate if the data was updated or not.
216 template <int cols, int rows>
217 struct SetFloatUniformMatrixGLSL
218 {
219 static void Run(unsigned int arrayElementOffset,
220 unsigned int elementCount,
221 GLsizei countIn,
222 GLboolean transpose,
223 const GLfloat *value,
224 uint8_t *targetData);
225 };
226
227 template <int cols, int rows>
228 struct SetFloatUniformMatrixHLSL
229 {
230 static void Run(unsigned int arrayElementOffset,
231 unsigned int elementCount,
232 GLsizei countIn,
233 GLboolean transpose,
234 const GLfloat *value,
235 uint8_t *targetData);
236 };
237
238 // Helper method to de-tranpose a matrix uniform for an API query.
239 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
240
241 template <typename NonFloatT>
242 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose);
243
244 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type);
245
246 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
247 const gl::IndexRange &indexRange,
248 GLint baseVertex,
249 GLint *firstVertexOut);
250
251 angle::Result GetVertexRangeInfo(const gl::Context *context,
252 GLint firstVertex,
253 GLsizei vertexOrIndexCount,
254 gl::DrawElementsType indexTypeOrInvalid,
255 const void *indices,
256 GLint baseVertex,
257 GLint *startVertexOut,
258 size_t *vertexCountOut);
259
260 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY);
261
262 // Helper method to intialize a FeatureSet with overrides from the DisplayState
263 void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state);
264
265 template <typename In>
LineLoopRestartIndexCountHelper(GLsizei indexCount,const uint8_t * srcPtr)266 uint32_t LineLoopRestartIndexCountHelper(GLsizei indexCount, const uint8_t *srcPtr)
267 {
268 constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
269 const In *inIndices = reinterpret_cast<const In *>(srcPtr);
270 uint32_t numIndices = 0;
271 // See CopyLineLoopIndicesWithRestart() below for more info on how
272 // numIndices is calculated.
273 GLsizei loopStartIndex = 0;
274 for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
275 {
276 In vertex = inIndices[curIndex];
277 if (vertex != restartIndex)
278 {
279 numIndices++;
280 }
281 else
282 {
283 if (curIndex > loopStartIndex)
284 {
285 numIndices += 2;
286 }
287 loopStartIndex = curIndex + 1;
288 }
289 }
290 if (indexCount > loopStartIndex)
291 {
292 numIndices++;
293 }
294 return numIndices;
295 }
296
GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr)297 inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,
298 GLsizei indexCount,
299 const uint8_t *srcPtr)
300 {
301 switch (glIndexType)
302 {
303 case gl::DrawElementsType::UnsignedByte:
304 return LineLoopRestartIndexCountHelper<uint8_t>(indexCount, srcPtr);
305 case gl::DrawElementsType::UnsignedShort:
306 return LineLoopRestartIndexCountHelper<uint16_t>(indexCount, srcPtr);
307 case gl::DrawElementsType::UnsignedInt:
308 return LineLoopRestartIndexCountHelper<uint32_t>(indexCount, srcPtr);
309 default:
310 UNREACHABLE();
311 return 0;
312 }
313 }
314
315 // Writes the line-strip vertices for a line loop to outPtr,
316 // where outLimit is calculated as in GetPrimitiveRestartIndexCount.
317 template <typename In, typename Out>
CopyLineLoopIndicesWithRestart(GLsizei indexCount,const uint8_t * srcPtr,uint8_t * outPtr)318 void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr)
319 {
320 constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
321 constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType<Out>();
322 const In *inIndices = reinterpret_cast<const In *>(srcPtr);
323 Out *outIndices = reinterpret_cast<Out *>(outPtr);
324 GLsizei loopStartIndex = 0;
325 for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
326 {
327 In vertex = inIndices[curIndex];
328 if (vertex != restartIndex)
329 {
330 *(outIndices++) = static_cast<Out>(vertex);
331 }
332 else
333 {
334 if (curIndex > loopStartIndex)
335 {
336 // Emit an extra vertex only if the loop is not empty.
337 *(outIndices++) = inIndices[loopStartIndex];
338 // Then restart the strip.
339 *(outIndices++) = outRestartIndex;
340 }
341 loopStartIndex = curIndex + 1;
342 }
343 }
344 if (indexCount > loopStartIndex)
345 {
346 // Close the last loop if not empty.
347 *(outIndices++) = inIndices[loopStartIndex];
348 }
349 }
350
351 void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
352 } // namespace rx
353
354 #endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_
355