• 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 #include "libANGLE/renderer/renderer_utils.h"
11 
12 #include "image_util/copyimage.h"
13 #include "image_util/imageformats.h"
14 
15 #include "libANGLE/AttributeMap.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Display.h"
18 #include "libANGLE/formatutils.h"
19 #include "libANGLE/renderer/ContextImpl.h"
20 #include "libANGLE/renderer/Format.h"
21 
22 #include "platform/Feature.h"
23 
24 #include <string.h>
25 #include "common/utilities.h"
26 
27 namespace rx
28 {
29 
30 namespace
31 {
CopyColor(gl::ColorF * color)32 void CopyColor(gl::ColorF *color)
33 {
34     // No-op
35 }
36 
PremultiplyAlpha(gl::ColorF * color)37 void PremultiplyAlpha(gl::ColorF *color)
38 {
39     color->red *= color->alpha;
40     color->green *= color->alpha;
41     color->blue *= color->alpha;
42 }
43 
UnmultiplyAlpha(gl::ColorF * color)44 void UnmultiplyAlpha(gl::ColorF *color)
45 {
46     if (color->alpha != 0.0f)
47     {
48         float invAlpha = 1.0f / color->alpha;
49         color->red *= invAlpha;
50         color->green *= invAlpha;
51         color->blue *= invAlpha;
52     }
53 }
54 
ClipChannelsR(gl::ColorF * color)55 void ClipChannelsR(gl::ColorF *color)
56 {
57     color->green = 0.0f;
58     color->blue  = 0.0f;
59     color->alpha = 1.0f;
60 }
61 
ClipChannelsRG(gl::ColorF * color)62 void ClipChannelsRG(gl::ColorF *color)
63 {
64     color->blue  = 0.0f;
65     color->alpha = 1.0f;
66 }
67 
ClipChannelsRGB(gl::ColorF * color)68 void ClipChannelsRGB(gl::ColorF *color)
69 {
70     color->alpha = 1.0f;
71 }
72 
ClipChannelsLuminance(gl::ColorF * color)73 void ClipChannelsLuminance(gl::ColorF *color)
74 {
75     color->alpha = 1.0f;
76 }
77 
ClipChannelsAlpha(gl::ColorF * color)78 void ClipChannelsAlpha(gl::ColorF *color)
79 {
80     color->red   = 0.0f;
81     color->green = 0.0f;
82     color->blue  = 0.0f;
83 }
84 
ClipChannelsNoOp(gl::ColorF * color)85 void ClipChannelsNoOp(gl::ColorF *color) {}
86 
WriteUintColor(const gl::ColorF & color,PixelWriteFunction colorWriteFunction,uint8_t * destPixelData)87 void WriteUintColor(const gl::ColorF &color,
88                     PixelWriteFunction colorWriteFunction,
89                     uint8_t *destPixelData)
90 {
91     gl::ColorUI destColor(
92         static_cast<unsigned int>(color.red * 255), static_cast<unsigned int>(color.green * 255),
93         static_cast<unsigned int>(color.blue * 255), static_cast<unsigned int>(color.alpha * 255));
94     colorWriteFunction(reinterpret_cast<const uint8_t *>(&destColor), destPixelData);
95 }
96 
WriteFloatColor(const gl::ColorF & color,PixelWriteFunction colorWriteFunction,uint8_t * destPixelData)97 void WriteFloatColor(const gl::ColorF &color,
98                      PixelWriteFunction colorWriteFunction,
99                      uint8_t *destPixelData)
100 {
101     colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
102 }
103 
104 template <int cols, int rows, bool IsColumnMajor>
GetFlattenedIndex(int col,int row)105 inline int GetFlattenedIndex(int col, int row)
106 {
107     if (IsColumnMajor)
108     {
109         return col * rows + row;
110     }
111     else
112     {
113         return row * cols + col;
114     }
115 }
116 
117 template <typename T,
118           bool IsSrcColumnMajor,
119           int colsSrc,
120           int rowsSrc,
121           bool IsDstColumnMajor,
122           int colsDst,
123           int rowsDst>
ExpandMatrix(T * target,const GLfloat * value)124 void ExpandMatrix(T *target, const GLfloat *value)
125 {
126     static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!");
127 
128     constexpr int kDstFlatSize = colsDst * rowsDst;
129     T staging[kDstFlatSize]    = {0};
130 
131     for (int r = 0; r < rowsSrc; r++)
132     {
133         for (int c = 0; c < colsSrc; c++)
134         {
135             int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc, IsSrcColumnMajor>(c, r);
136             int dstIndex = GetFlattenedIndex<colsDst, rowsDst, IsDstColumnMajor>(c, r);
137 
138             staging[dstIndex] = static_cast<T>(value[srcIndex]);
139         }
140     }
141 
142     memcpy(target, staging, kDstFlatSize * sizeof(T));
143 }
144 
145 template <bool IsSrcColumMajor,
146           int colsSrc,
147           int rowsSrc,
148           bool IsDstColumnMajor,
149           int colsDst,
150           int rowsDst>
SetFloatUniformMatrix(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,const GLfloat * value,uint8_t * targetData)151 void SetFloatUniformMatrix(unsigned int arrayElementOffset,
152                            unsigned int elementCount,
153                            GLsizei countIn,
154                            const GLfloat *value,
155                            uint8_t *targetData)
156 {
157     unsigned int count =
158         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
159 
160     const unsigned int targetMatrixStride = colsDst * rowsDst;
161     GLfloat *target                       = reinterpret_cast<GLfloat *>(
162         targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
163 
164     for (unsigned int i = 0; i < count; i++)
165     {
166         ExpandMatrix<GLfloat, IsSrcColumMajor, colsSrc, rowsSrc, IsDstColumnMajor, colsDst,
167                      rowsDst>(target, value);
168 
169         target += targetMatrixStride;
170         value += colsSrc * rowsSrc;
171     }
172 }
173 
SetFloatUniformMatrixFast(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,size_t matrixSize,const GLfloat * value,uint8_t * targetData)174 void SetFloatUniformMatrixFast(unsigned int arrayElementOffset,
175                                unsigned int elementCount,
176                                GLsizei countIn,
177                                size_t matrixSize,
178                                const GLfloat *value,
179                                uint8_t *targetData)
180 {
181     const unsigned int count =
182         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
183 
184     const uint8_t *valueData = reinterpret_cast<const uint8_t *>(value);
185     targetData               = targetData + arrayElementOffset * matrixSize;
186 
187     memcpy(targetData, valueData, matrixSize * count);
188 }
189 
190 }  // anonymous namespace
191 
PackPixelsParams()192 PackPixelsParams::PackPixelsParams()
193     : destFormat(nullptr), outputPitch(0), packBuffer(nullptr), offset(0)
194 {}
195 
PackPixelsParams(const gl::Rectangle & areaIn,const angle::Format & destFormat,GLuint outputPitchIn,bool reverseRowOrderIn,gl::Buffer * packBufferIn,ptrdiff_t offsetIn)196 PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
197                                    const angle::Format &destFormat,
198                                    GLuint outputPitchIn,
199                                    bool reverseRowOrderIn,
200                                    gl::Buffer *packBufferIn,
201                                    ptrdiff_t offsetIn)
202     : area(areaIn),
203       destFormat(&destFormat),
204       outputPitch(outputPitchIn),
205       packBuffer(packBufferIn),
206       reverseRowOrder(reverseRowOrderIn),
207       offset(offsetIn)
208 {}
209 
PackPixels(const PackPixelsParams & params,const angle::Format & sourceFormat,int inputPitchIn,const uint8_t * sourceIn,uint8_t * destWithoutOffset)210 void PackPixels(const PackPixelsParams &params,
211                 const angle::Format &sourceFormat,
212                 int inputPitchIn,
213                 const uint8_t *sourceIn,
214                 uint8_t *destWithoutOffset)
215 {
216     uint8_t *destWithOffset = destWithoutOffset + params.offset;
217 
218     const uint8_t *source = sourceIn;
219     int inputPitch        = inputPitchIn;
220 
221     if (params.reverseRowOrder)
222     {
223         source += inputPitch * (params.area.height - 1);
224         inputPitch = -inputPitch;
225     }
226 
227     if (sourceFormat == *params.destFormat)
228     {
229         // Direct copy possible
230         for (int y = 0; y < params.area.height; ++y)
231         {
232             memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
233                    params.area.width * sourceFormat.pixelBytes);
234         }
235         return;
236     }
237 
238     PixelCopyFunction fastCopyFunc = sourceFormat.fastCopyFunctions.get(params.destFormat->id);
239 
240     if (fastCopyFunc)
241     {
242         // Fast copy is possible through some special function
243         for (int y = 0; y < params.area.height; ++y)
244         {
245             for (int x = 0; x < params.area.width; ++x)
246             {
247                 uint8_t *dest =
248                     destWithOffset + y * params.outputPitch + x * params.destFormat->pixelBytes;
249                 const uint8_t *src = source + y * inputPitch + x * sourceFormat.pixelBytes;
250 
251                 fastCopyFunc(src, dest);
252             }
253         }
254         return;
255     }
256 
257     PixelWriteFunction pixelWriteFunction = params.destFormat->pixelWriteFunction;
258     ASSERT(pixelWriteFunction != nullptr);
259 
260     // Maximum size of any Color<T> type used.
261     uint8_t temp[16];
262     static_assert(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) &&
263                       sizeof(temp) >= sizeof(gl::ColorI) &&
264                       sizeof(temp) >= sizeof(angle::DepthStencil),
265                   "Unexpected size of pixel struct.");
266 
267     PixelReadFunction pixelReadFunction = sourceFormat.pixelReadFunction;
268     ASSERT(pixelReadFunction != nullptr);
269 
270     for (int y = 0; y < params.area.height; ++y)
271     {
272         for (int x = 0; x < params.area.width; ++x)
273         {
274             uint8_t *dest =
275                 destWithOffset + y * params.outputPitch + x * params.destFormat->pixelBytes;
276             const uint8_t *src = source + y * inputPitch + x * sourceFormat.pixelBytes;
277 
278             // readFunc and writeFunc will be using the same type of color, CopyTexImage
279             // will not allow the copy otherwise.
280             pixelReadFunction(src, temp);
281             pixelWriteFunction(temp, dest);
282         }
283     }
284 }
285 
has(angle::FormatID formatID) const286 bool FastCopyFunctionMap::has(angle::FormatID formatID) const
287 {
288     return (get(formatID) != nullptr);
289 }
290 
get(angle::FormatID formatID) const291 PixelCopyFunction FastCopyFunctionMap::get(angle::FormatID formatID) const
292 {
293     for (size_t index = 0; index < mSize; ++index)
294     {
295         if (mData[index].formatID == formatID)
296         {
297             return mData[index].func;
298         }
299     }
300 
301     return nullptr;
302 }
303 
ShouldUseDebugLayers(const egl::AttributeMap & attribs)304 bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
305 {
306     EGLAttrib debugSetting =
307         attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
308 
309 // Prefer to enable debug layers if compiling in Debug, and disabled in Release.
310 #if defined(ANGLE_ENABLE_ASSERTS)
311     return (debugSetting != EGL_FALSE);
312 #else
313     return (debugSetting == EGL_TRUE);
314 #endif  // defined(ANGLE_ENABLE_ASSERTS)
315 }
316 
ShouldUseVirtualizedContexts(const egl::AttributeMap & attribs,bool defaultValue)317 bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue)
318 {
319     EGLAttrib virtualizedContextRequest =
320         attribs.get(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE, EGL_DONT_CARE);
321     if (defaultValue)
322     {
323         return (virtualizedContextRequest != EGL_FALSE);
324     }
325     else
326     {
327         return (virtualizedContextRequest == EGL_TRUE);
328     }
329 }
330 
CopyImageCHROMIUM(const uint8_t * sourceData,size_t sourceRowPitch,size_t sourcePixelBytes,size_t sourceDepthPitch,PixelReadFunction pixelReadFunction,uint8_t * destData,size_t destRowPitch,size_t destPixelBytes,size_t destDepthPitch,PixelWriteFunction pixelWriteFunction,GLenum destUnsizedFormat,GLenum destComponentType,size_t width,size_t height,size_t depth,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)331 void CopyImageCHROMIUM(const uint8_t *sourceData,
332                        size_t sourceRowPitch,
333                        size_t sourcePixelBytes,
334                        size_t sourceDepthPitch,
335                        PixelReadFunction pixelReadFunction,
336                        uint8_t *destData,
337                        size_t destRowPitch,
338                        size_t destPixelBytes,
339                        size_t destDepthPitch,
340                        PixelWriteFunction pixelWriteFunction,
341                        GLenum destUnsizedFormat,
342                        GLenum destComponentType,
343                        size_t width,
344                        size_t height,
345                        size_t depth,
346                        bool unpackFlipY,
347                        bool unpackPremultiplyAlpha,
348                        bool unpackUnmultiplyAlpha)
349 {
350     using ConversionFunction              = void (*)(gl::ColorF *);
351     ConversionFunction conversionFunction = CopyColor;
352     if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
353     {
354         if (unpackPremultiplyAlpha)
355         {
356             conversionFunction = PremultiplyAlpha;
357         }
358         else
359         {
360             conversionFunction = UnmultiplyAlpha;
361         }
362     }
363 
364     auto clipChannelsFunction = ClipChannelsNoOp;
365     switch (destUnsizedFormat)
366     {
367         case GL_RED:
368             clipChannelsFunction = ClipChannelsR;
369             break;
370         case GL_RG:
371             clipChannelsFunction = ClipChannelsRG;
372             break;
373         case GL_RGB:
374             clipChannelsFunction = ClipChannelsRGB;
375             break;
376         case GL_LUMINANCE:
377             clipChannelsFunction = ClipChannelsLuminance;
378             break;
379         case GL_ALPHA:
380             clipChannelsFunction = ClipChannelsAlpha;
381             break;
382     }
383 
384     auto writeFunction = (destComponentType == GL_UNSIGNED_INT) ? WriteUintColor : WriteFloatColor;
385 
386     for (size_t z = 0; z < depth; z++)
387     {
388         for (size_t y = 0; y < height; y++)
389         {
390             for (size_t x = 0; x < width; x++)
391             {
392                 const uint8_t *sourcePixelData =
393                     sourceData + y * sourceRowPitch + x * sourcePixelBytes + z * sourceDepthPitch;
394 
395                 gl::ColorF sourceColor;
396                 pixelReadFunction(sourcePixelData, reinterpret_cast<uint8_t *>(&sourceColor));
397 
398                 conversionFunction(&sourceColor);
399                 clipChannelsFunction(&sourceColor);
400 
401                 size_t destY = 0;
402                 if (unpackFlipY)
403                 {
404                     destY += (height - 1);
405                     destY -= y;
406                 }
407                 else
408                 {
409                     destY += y;
410                 }
411 
412                 uint8_t *destPixelData =
413                     destData + destY * destRowPitch + x * destPixelBytes + z * destDepthPitch;
414                 writeFunction(sourceColor, pixelWriteFunction, destPixelData);
415             }
416         }
417     }
418 }
419 
420 // IncompleteTextureSet implementation.
IncompleteTextureSet()421 IncompleteTextureSet::IncompleteTextureSet() {}
422 
~IncompleteTextureSet()423 IncompleteTextureSet::~IncompleteTextureSet() {}
424 
onDestroy(const gl::Context * context)425 void IncompleteTextureSet::onDestroy(const gl::Context *context)
426 {
427     // Clear incomplete textures.
428     for (auto &incompleteTexture : mIncompleteTextures)
429     {
430         if (incompleteTexture.get() != nullptr)
431         {
432             incompleteTexture->onDestroy(context);
433             incompleteTexture.set(context, nullptr);
434         }
435     }
436 }
437 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,MultisampleTextureInitializer * multisampleInitializer,gl::Texture ** textureOut)438 angle::Result IncompleteTextureSet::getIncompleteTexture(
439     const gl::Context *context,
440     gl::TextureType type,
441     MultisampleTextureInitializer *multisampleInitializer,
442     gl::Texture **textureOut)
443 {
444     *textureOut = mIncompleteTextures[type].get();
445     if (*textureOut != nullptr)
446     {
447         return angle::Result::Continue;
448     }
449 
450     ContextImpl *implFactory = context->getImplementation();
451 
452     const GLubyte color[] = {0, 0, 0, 255};
453     const gl::Extents colorSize(1, 1, 1);
454     gl::PixelUnpackState unpack;
455     unpack.alignment = 1;
456     const gl::Box area(0, 0, 0, 1, 1, 1);
457 
458     // If a texture is external use a 2D texture for the incomplete texture
459     gl::TextureType createType = (type == gl::TextureType::External) ? gl::TextureType::_2D : type;
460 
461     gl::Texture *tex =
462         new gl::Texture(implFactory, {std::numeric_limits<GLuint>::max()}, createType);
463     angle::UniqueObjectPointer<gl::Texture, gl::Context> t(tex, context);
464 
465     // This is a bit of a kludge but is necessary to consume the error.
466     gl::Context *mutableContext = const_cast<gl::Context *>(context);
467 
468     if (createType == gl::TextureType::_2DMultisample)
469     {
470         ANGLE_TRY(
471             t->setStorageMultisample(mutableContext, createType, 1, GL_RGBA8, colorSize, true));
472     }
473     else
474     {
475         ANGLE_TRY(t->setStorage(mutableContext, createType, 1, GL_RGBA8, colorSize));
476     }
477 
478     if (type == gl::TextureType::CubeMap)
479     {
480         for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
481         {
482             ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr, face, 0, area, GL_RGBA,
483                                      GL_UNSIGNED_BYTE, color));
484         }
485     }
486     else if (type == gl::TextureType::_2DMultisample)
487     {
488         // Call a specialized clear function to init a multisample texture.
489         ANGLE_TRY(multisampleInitializer->initializeMultisampleTextureToBlack(context, t.get()));
490     }
491     else
492     {
493         ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
494                                  gl::NonCubeTextureTypeToTarget(createType), 0, area, GL_RGBA,
495                                  GL_UNSIGNED_BYTE, color));
496     }
497 
498     ANGLE_TRY(t->syncState(context));
499 
500     mIncompleteTextures[type].set(context, t.release());
501     *textureOut = mIncompleteTextures[type].get();
502     return angle::Result::Continue;
503 }
504 
505 #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
506     template void SetFloatUniformMatrix##api<cols, rows>::Run(     \
507         unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *)
508 
509 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
510 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
511 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
512 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
513 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
514 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3);
515 
516 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2);
517 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3);
518 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3);
519 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2);
520 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4);
521 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4);
522 
523 #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
524 
525 #define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
526     template void SetFloatUniformMatrix##api<cols, 4>::Run(unsigned int, unsigned int, GLsizei, \
527                                                            GLboolean, const GLfloat *, uint8_t *)
528 
529 template <int cols>
530 struct SetFloatUniformMatrixGLSL<cols, 4>
531 {
532     static void Run(unsigned int arrayElementOffset,
533                     unsigned int elementCount,
534                     GLsizei countIn,
535                     GLboolean transpose,
536                     const GLfloat *value,
537                     uint8_t *targetData);
538 };
539 
540 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
541 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
542 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
543 
544 #undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC
545 
546 #define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
547     template void SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \
548                                                            GLboolean, const GLfloat *, uint8_t *)
549 
550 template <int rows>
551 struct SetFloatUniformMatrixHLSL<4, rows>
552 {
553     static void Run(unsigned int arrayElementOffset,
554                     unsigned int elementCount,
555                     GLsizei countIn,
556                     GLboolean transpose,
557                     const GLfloat *value,
558                     uint8_t *targetData);
559 };
560 
561 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
562 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
563 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
564 
565 #undef ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC
566 
567 template <int cols>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)568 void SetFloatUniformMatrixGLSL<cols, 4>::Run(unsigned int arrayElementOffset,
569                                              unsigned int elementCount,
570                                              GLsizei countIn,
571                                              GLboolean transpose,
572                                              const GLfloat *value,
573                                              uint8_t *targetData)
574 {
575     const bool isSrcColumnMajor = !transpose;
576     if (isSrcColumnMajor)
577     {
578         // Both src and dst matrixs are has same layout,
579         // a single memcpy updates all the matrices
580         constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4;
581         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
582                                   targetData);
583     }
584     else
585     {
586         // fallback to general cases
587         SetFloatUniformMatrix<false, cols, 4, true, cols, 4>(arrayElementOffset, elementCount,
588                                                              countIn, value, targetData);
589     }
590 }
591 
592 template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)593 void SetFloatUniformMatrixGLSL<cols, rows>::Run(unsigned int arrayElementOffset,
594                                                 unsigned int elementCount,
595                                                 GLsizei countIn,
596                                                 GLboolean transpose,
597                                                 const GLfloat *value,
598                                                 uint8_t *targetData)
599 {
600     const bool isSrcColumnMajor = !transpose;
601     // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
602     if (isSrcColumnMajor)
603     {
604         SetFloatUniformMatrix<true, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
605                                                                countIn, value, targetData);
606     }
607     else
608     {
609         SetFloatUniformMatrix<false, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
610                                                                 countIn, value, targetData);
611     }
612 }
613 
614 template <int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)615 void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset,
616                                              unsigned int elementCount,
617                                              GLsizei countIn,
618                                              GLboolean transpose,
619                                              const GLfloat *value,
620                                              uint8_t *targetData)
621 {
622     const bool isSrcColumnMajor = !transpose;
623     if (!isSrcColumnMajor)
624     {
625         // Both src and dst matrixs are has same layout,
626         // a single memcpy updates all the matrices
627         constexpr size_t srcMatrixSize = sizeof(GLfloat) * 4 * rows;
628         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
629                                   targetData);
630     }
631     else
632     {
633         // fallback to general cases
634         SetFloatUniformMatrix<true, 4, rows, false, 4, rows>(arrayElementOffset, elementCount,
635                                                              countIn, value, targetData);
636     }
637 }
638 
639 template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)640 void SetFloatUniformMatrixHLSL<cols, rows>::Run(unsigned int arrayElementOffset,
641                                                 unsigned int elementCount,
642                                                 GLsizei countIn,
643                                                 GLboolean transpose,
644                                                 const GLfloat *value,
645                                                 uint8_t *targetData)
646 {
647     const bool isSrcColumnMajor = !transpose;
648     // Internally store matrices as row-major to accomodate HLSL matrix indexing.  Each row is
649     // padded to 4 columns.
650     if (!isSrcColumnMajor)
651     {
652         SetFloatUniformMatrix<false, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
653                                                                  countIn, value, targetData);
654     }
655     else
656     {
657         SetFloatUniformMatrix<true, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
658                                                                 countIn, value, targetData);
659     }
660 }
661 
662 template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
663 template void GetMatrixUniform<GLuint>(GLenum, GLuint *, const GLuint *, bool);
664 
GetMatrixUniform(GLenum type,GLfloat * dataOut,const GLfloat * source,bool transpose)665 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose)
666 {
667     int columns = gl::VariableColumnCount(type);
668     int rows    = gl::VariableRowCount(type);
669     for (GLint col = 0; col < columns; ++col)
670     {
671         for (GLint row = 0; row < rows; ++row)
672         {
673             GLfloat *outptr = dataOut + ((col * rows) + row);
674             const GLfloat *inptr =
675                 transpose ? source + ((row * 4) + col) : source + ((col * 4) + row);
676             *outptr = *inptr;
677         }
678     }
679 }
680 
681 template <typename NonFloatT>
GetMatrixUniform(GLenum type,NonFloatT * dataOut,const NonFloatT * source,bool transpose)682 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose)
683 {
684     UNREACHABLE();
685 }
686 
GetFormatFromFormatType(GLenum format,GLenum type)687 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type)
688 {
689     GLenum sizedInternalFormat    = gl::GetInternalFormatInfo(format, type).sizedInternalFormat;
690     angle::FormatID angleFormatID = angle::Format::InternalFormatToID(sizedInternalFormat);
691     return angle::Format::Get(angleFormatID);
692 }
693 
ComputeStartVertex(ContextImpl * contextImpl,const gl::IndexRange & indexRange,GLint baseVertex,GLint * firstVertexOut)694 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
695                                  const gl::IndexRange &indexRange,
696                                  GLint baseVertex,
697                                  GLint *firstVertexOut)
698 {
699     // The entire index range should be within the limits of a 32-bit uint because the largest
700     // GL index type is GL_UNSIGNED_INT.
701     ASSERT(indexRange.start <= std::numeric_limits<uint32_t>::max() &&
702            indexRange.end <= std::numeric_limits<uint32_t>::max());
703 
704     // The base vertex is only used in DrawElementsIndirect. Given the assertion above and the
705     // type of mBaseVertex (GLint), adding them both as 64-bit ints is safe.
706     int64_t startVertexInt64 =
707         static_cast<int64_t>(baseVertex) + static_cast<int64_t>(indexRange.start);
708 
709     // OpenGL ES 3.2 spec section 10.5: "Behavior of DrawElementsOneInstance is undefined if the
710     // vertex ID is negative for any element"
711     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 >= 0);
712 
713     // OpenGL ES 3.2 spec section 10.5: "If the vertex ID is larger than the maximum value
714     // representable by type, it should behave as if the calculation were upconverted to 32-bit
715     // unsigned integers(with wrapping on overflow conditions)." ANGLE does not fully handle
716     // these rules, an overflow error is returned if the start vertex cannot be stored in a
717     // 32-bit signed integer.
718     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max());
719 
720     *firstVertexOut = static_cast<GLint>(startVertexInt64);
721     return angle::Result::Continue;
722 }
723 
GetVertexRangeInfo(const gl::Context * context,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLint baseVertex,GLint * startVertexOut,size_t * vertexCountOut)724 angle::Result GetVertexRangeInfo(const gl::Context *context,
725                                  GLint firstVertex,
726                                  GLsizei vertexOrIndexCount,
727                                  gl::DrawElementsType indexTypeOrInvalid,
728                                  const void *indices,
729                                  GLint baseVertex,
730                                  GLint *startVertexOut,
731                                  size_t *vertexCountOut)
732 {
733     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
734     {
735         gl::IndexRange indexRange;
736         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
737             context, indexTypeOrInvalid, vertexOrIndexCount, indices, &indexRange));
738         ANGLE_TRY(ComputeStartVertex(context->getImplementation(), indexRange, baseVertex,
739                                      startVertexOut));
740         *vertexCountOut = indexRange.vertexCount();
741     }
742     else
743     {
744         *startVertexOut = firstVertex;
745         *vertexCountOut = vertexOrIndexCount;
746     }
747     return angle::Result::Continue;
748 }
749 
ClipRectToScissor(const gl::State & glState,const gl::Rectangle & rect,bool invertY)750 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY)
751 {
752     if (glState.isScissorTestEnabled())
753     {
754         gl::Rectangle clippedRect;
755         if (!gl::ClipRectangle(glState.getScissor(), rect, &clippedRect))
756         {
757             return gl::Rectangle();
758         }
759 
760         if (invertY)
761         {
762             clippedRect.y = rect.height - clippedRect.y - clippedRect.height;
763         }
764 
765         return clippedRect;
766     }
767 
768     // If the scissor test isn't enabled, assume it has infinite size.  Its intersection with the
769     // rect would be the rect itself.
770     //
771     // Note that on Vulkan, returning this (as opposed to a fixed max-int-sized rect) could lead to
772     // unnecessary pipeline creations if two otherwise identical pipelines are used on framebuffers
773     // with different sizes.  If such usage is observed in an application, we should investigate
774     // possible optimizations.
775     return rect;
776 }
777 
OverrideFeaturesWithDisplayState(angle::FeatureSetBase * features,const egl::DisplayState & state)778 void OverrideFeaturesWithDisplayState(angle::FeatureSetBase *features,
779                                       const egl::DisplayState &state)
780 {
781     features->overrideFeatures(state.featureOverridesEnabled, true);
782     features->overrideFeatures(state.featureOverridesDisabled, false);
783 }
784 }  // namespace rx
785