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