• 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 "common/string_utils.h"
13 #include "common/system_utils.h"
14 #include "common/utilities.h"
15 #include "image_util/copyimage.h"
16 #include "image_util/imageformats.h"
17 #include "libANGLE/AttributeMap.h"
18 #include "libANGLE/Context.h"
19 #include "libANGLE/Context.inl.h"
20 #include "libANGLE/Display.h"
21 #include "libANGLE/formatutils.h"
22 #include "libANGLE/renderer/ContextImpl.h"
23 #include "libANGLE/renderer/Format.h"
24 #include "platform/Feature.h"
25 
26 #include <string.h>
27 
28 namespace rx
29 {
30 
31 namespace
32 {
33 // Both D3D and Vulkan support the same set of standard sample positions for 1, 2, 4, 8, and 16
34 // samples.  See:
35 //
36 // - https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx
37 //
38 // -
39 // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#primsrast-multisampling
40 using SamplePositionsArray                                     = std::array<float, 32>;
41 constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
42     {{{0.5f, 0.5f}},
43      {{0.75f, 0.75f, 0.25f, 0.25f}},
44      {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
45      {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
46        0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
47      {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f,  0.75f,   0.4375f,
48        0.1875f, 0.375f,  0.625f,  0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
49        0.375f,  0.875f,  0.5f,    0.0625f, 0.25f,   0.125f,  0.125f,  0.75f,
50        0.0f,    0.5f,    0.9375f, 0.25f,   0.875f,  0.9375f, 0.0625f, 0.0f}}}};
51 
52 struct IncompleteTextureParameters
53 {
54     GLenum sizedInternalFormat;
55     GLenum format;
56     GLenum type;
57     GLubyte clearColor[4];
58 };
59 
60 // Note that for gl::SamplerFormat::Shadow, the clearColor datatype needs to be GLushort and as such
61 // we will reinterpret GLubyte[4] as GLushort[2].
62 constexpr angle::PackedEnumMap<gl::SamplerFormat, IncompleteTextureParameters>
63     kIncompleteTextureParameters = {
64         {gl::SamplerFormat::Float, {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, {0, 0, 0, 255}}},
65         {gl::SamplerFormat::Unsigned,
66          {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, {0, 0, 0, 255}}},
67         {gl::SamplerFormat::Signed, {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, {0, 0, 0, 127}}},
68         {gl::SamplerFormat::Shadow,
69          {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, {0, 0, 0, 0}}}};
70 
CopyColor(gl::ColorF * color)71 void CopyColor(gl::ColorF *color)
72 {
73     // No-op
74 }
75 
PremultiplyAlpha(gl::ColorF * color)76 void PremultiplyAlpha(gl::ColorF *color)
77 {
78     color->red *= color->alpha;
79     color->green *= color->alpha;
80     color->blue *= color->alpha;
81 }
82 
UnmultiplyAlpha(gl::ColorF * color)83 void UnmultiplyAlpha(gl::ColorF *color)
84 {
85     if (color->alpha != 0.0f)
86     {
87         float invAlpha = 1.0f / color->alpha;
88         color->red *= invAlpha;
89         color->green *= invAlpha;
90         color->blue *= invAlpha;
91     }
92 }
93 
ClipChannelsR(gl::ColorF * color)94 void ClipChannelsR(gl::ColorF *color)
95 {
96     color->green = 0.0f;
97     color->blue  = 0.0f;
98     color->alpha = 1.0f;
99 }
100 
ClipChannelsRG(gl::ColorF * color)101 void ClipChannelsRG(gl::ColorF *color)
102 {
103     color->blue  = 0.0f;
104     color->alpha = 1.0f;
105 }
106 
ClipChannelsRGB(gl::ColorF * color)107 void ClipChannelsRGB(gl::ColorF *color)
108 {
109     color->alpha = 1.0f;
110 }
111 
ClipChannelsLuminance(gl::ColorF * color)112 void ClipChannelsLuminance(gl::ColorF *color)
113 {
114     color->alpha = 1.0f;
115 }
116 
ClipChannelsAlpha(gl::ColorF * color)117 void ClipChannelsAlpha(gl::ColorF *color)
118 {
119     color->red   = 0.0f;
120     color->green = 0.0f;
121     color->blue  = 0.0f;
122 }
123 
ClipChannelsNoOp(gl::ColorF * color)124 void ClipChannelsNoOp(gl::ColorF *color) {}
125 
WriteUintColor(const gl::ColorF & color,PixelWriteFunction colorWriteFunction,uint8_t * destPixelData)126 void WriteUintColor(const gl::ColorF &color,
127                     PixelWriteFunction colorWriteFunction,
128                     uint8_t *destPixelData)
129 {
130     gl::ColorUI destColor(
131         static_cast<unsigned int>(color.red * 255), static_cast<unsigned int>(color.green * 255),
132         static_cast<unsigned int>(color.blue * 255), static_cast<unsigned int>(color.alpha * 255));
133     colorWriteFunction(reinterpret_cast<const uint8_t *>(&destColor), destPixelData);
134 }
135 
WriteFloatColor(const gl::ColorF & color,PixelWriteFunction colorWriteFunction,uint8_t * destPixelData)136 void WriteFloatColor(const gl::ColorF &color,
137                      PixelWriteFunction colorWriteFunction,
138                      uint8_t *destPixelData)
139 {
140     colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
141 }
142 
143 template <int cols, int rows, bool IsColumnMajor>
GetFlattenedIndex(int col,int row)144 inline int GetFlattenedIndex(int col, int row)
145 {
146     if (IsColumnMajor)
147     {
148         return col * rows + row;
149     }
150     else
151     {
152         return row * cols + col;
153     }
154 }
155 
156 template <typename T,
157           bool IsSrcColumnMajor,
158           int colsSrc,
159           int rowsSrc,
160           bool IsDstColumnMajor,
161           int colsDst,
162           int rowsDst>
ExpandMatrix(T * target,const GLfloat * value)163 void ExpandMatrix(T *target, const GLfloat *value)
164 {
165     static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!");
166 
167     constexpr int kDstFlatSize = colsDst * rowsDst;
168     T staging[kDstFlatSize]    = {0};
169 
170     for (int r = 0; r < rowsSrc; r++)
171     {
172         for (int c = 0; c < colsSrc; c++)
173         {
174             int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc, IsSrcColumnMajor>(c, r);
175             int dstIndex = GetFlattenedIndex<colsDst, rowsDst, IsDstColumnMajor>(c, r);
176 
177             staging[dstIndex] = static_cast<T>(value[srcIndex]);
178         }
179     }
180 
181     memcpy(target, staging, kDstFlatSize * sizeof(T));
182 }
183 
184 template <bool IsSrcColumMajor,
185           int colsSrc,
186           int rowsSrc,
187           bool IsDstColumnMajor,
188           int colsDst,
189           int rowsDst>
SetFloatUniformMatrix(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,const GLfloat * value,uint8_t * targetData)190 void SetFloatUniformMatrix(unsigned int arrayElementOffset,
191                            unsigned int elementCount,
192                            GLsizei countIn,
193                            const GLfloat *value,
194                            uint8_t *targetData)
195 {
196     unsigned int count =
197         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
198 
199     const unsigned int targetMatrixStride = colsDst * rowsDst;
200     GLfloat *target                       = reinterpret_cast<GLfloat *>(
201         targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
202 
203     for (unsigned int i = 0; i < count; i++)
204     {
205         ExpandMatrix<GLfloat, IsSrcColumMajor, colsSrc, rowsSrc, IsDstColumnMajor, colsDst,
206                      rowsDst>(target, value);
207 
208         target += targetMatrixStride;
209         value += colsSrc * rowsSrc;
210     }
211 }
212 
SetFloatUniformMatrixFast(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,size_t matrixSize,const GLfloat * value,uint8_t * targetData)213 void SetFloatUniformMatrixFast(unsigned int arrayElementOffset,
214                                unsigned int elementCount,
215                                GLsizei countIn,
216                                size_t matrixSize,
217                                const GLfloat *value,
218                                uint8_t *targetData)
219 {
220     const unsigned int count =
221         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
222 
223     const uint8_t *valueData = reinterpret_cast<const uint8_t *>(value);
224     targetData               = targetData + arrayElementOffset * matrixSize;
225 
226     memcpy(targetData, valueData, matrixSize * count);
227 }
228 
229 }  // anonymous namespace
230 
RotateRectangle(const SurfaceRotation rotation,const bool flipY,const int framebufferWidth,const int framebufferHeight,const gl::Rectangle & incoming,gl::Rectangle * outgoing)231 void RotateRectangle(const SurfaceRotation rotation,
232                      const bool flipY,
233                      const int framebufferWidth,
234                      const int framebufferHeight,
235                      const gl::Rectangle &incoming,
236                      gl::Rectangle *outgoing)
237 {
238     // GLES's y-axis points up; Vulkan's points down.
239     switch (rotation)
240     {
241         case SurfaceRotation::Identity:
242             // Do not rotate gl_Position (surface matches the device's orientation):
243             outgoing->x     = incoming.x;
244             outgoing->y     = flipY ? framebufferHeight - incoming.y - incoming.height : incoming.y;
245             outgoing->width = incoming.width;
246             outgoing->height = incoming.height;
247             break;
248         case SurfaceRotation::Rotated90Degrees:
249             // Rotate gl_Position 90 degrees:
250             outgoing->x      = incoming.y;
251             outgoing->y      = flipY ? incoming.x : framebufferWidth - incoming.x - incoming.width;
252             outgoing->width  = incoming.height;
253             outgoing->height = incoming.width;
254             break;
255         case SurfaceRotation::Rotated180Degrees:
256             // Rotate gl_Position 180 degrees:
257             outgoing->x     = framebufferWidth - incoming.x - incoming.width;
258             outgoing->y     = flipY ? incoming.y : framebufferHeight - incoming.y - incoming.height;
259             outgoing->width = incoming.width;
260             outgoing->height = incoming.height;
261             break;
262         case SurfaceRotation::Rotated270Degrees:
263             // Rotate gl_Position 270 degrees:
264             outgoing->x      = framebufferHeight - incoming.y - incoming.height;
265             outgoing->y      = flipY ? framebufferWidth - incoming.x - incoming.width : incoming.x;
266             outgoing->width  = incoming.height;
267             outgoing->height = incoming.width;
268             break;
269         default:
270             UNREACHABLE();
271             break;
272     }
273 }
274 
PackPixelsParams()275 PackPixelsParams::PackPixelsParams()
276     : destFormat(nullptr),
277       outputPitch(0),
278       packBuffer(nullptr),
279       offset(0),
280       rotation(SurfaceRotation::Identity)
281 {}
282 
PackPixelsParams(const gl::Rectangle & areaIn,const angle::Format & destFormat,GLuint outputPitchIn,bool reverseRowOrderIn,gl::Buffer * packBufferIn,ptrdiff_t offsetIn)283 PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
284                                    const angle::Format &destFormat,
285                                    GLuint outputPitchIn,
286                                    bool reverseRowOrderIn,
287                                    gl::Buffer *packBufferIn,
288                                    ptrdiff_t offsetIn)
289     : area(areaIn),
290       destFormat(&destFormat),
291       outputPitch(outputPitchIn),
292       packBuffer(packBufferIn),
293       reverseRowOrder(reverseRowOrderIn),
294       offset(offsetIn),
295       rotation(SurfaceRotation::Identity)
296 {}
297 
PackPixels(const PackPixelsParams & params,const angle::Format & sourceFormat,int inputPitchIn,const uint8_t * sourceIn,uint8_t * destWithoutOffset)298 void PackPixels(const PackPixelsParams &params,
299                 const angle::Format &sourceFormat,
300                 int inputPitchIn,
301                 const uint8_t *sourceIn,
302                 uint8_t *destWithoutOffset)
303 {
304     uint8_t *destWithOffset = destWithoutOffset + params.offset;
305 
306     const uint8_t *source = sourceIn;
307     int inputPitch        = inputPitchIn;
308     int destWidth         = params.area.width;
309     int destHeight        = params.area.height;
310     int xAxisPitch        = 0;
311     int yAxisPitch        = 0;
312     switch (params.rotation)
313     {
314         case SurfaceRotation::Identity:
315             // The source image is not rotated (i.e. matches the device's orientation), and may or
316             // may not be y-flipped.  The image is row-major.  Each source row (one step along the
317             // y-axis for each step in the dest y-axis) is inputPitch past the previous row.  Along
318             // a row, each source pixel (one step along the x-axis for each step in the dest
319             // x-axis) is sourceFormat.pixelBytes past the previous pixel.
320             xAxisPitch = sourceFormat.pixelBytes;
321             if (params.reverseRowOrder)
322             {
323                 // The source image is y-flipped, which means we start at the last row, and each
324                 // source row is BEFORE the previous row.
325                 source += inputPitchIn * (params.area.height - 1);
326                 inputPitch = -inputPitch;
327                 yAxisPitch = -inputPitchIn;
328             }
329             else
330             {
331                 yAxisPitch = inputPitchIn;
332             }
333             break;
334         case SurfaceRotation::Rotated90Degrees:
335             // The source image is rotated 90 degrees counter-clockwise.  Y-flip is always applied
336             // to rotated images.  The image is column-major.  Each source column (one step along
337             // the source x-axis for each step in the dest y-axis) is inputPitch past the previous
338             // column.  Along a column, each source pixel (one step along the y-axis for each step
339             // in the dest x-axis) is sourceFormat.pixelBytes past the previous pixel.
340             xAxisPitch = inputPitchIn;
341             yAxisPitch = sourceFormat.pixelBytes;
342             destWidth  = params.area.height;
343             destHeight = params.area.width;
344             break;
345         case SurfaceRotation::Rotated180Degrees:
346             // The source image is rotated 180 degrees.  Y-flip is always applied to rotated
347             // images.  The image is row-major, but upside down.  Each source row (one step along
348             // the y-axis for each step in the dest y-axis) is inputPitch after the previous row.
349             // Along a row, each source pixel (one step along the x-axis for each step in the dest
350             // x-axis) is sourceFormat.pixelBytes BEFORE the previous pixel.
351             xAxisPitch = -static_cast<int>(sourceFormat.pixelBytes);
352             yAxisPitch = inputPitchIn;
353             source += sourceFormat.pixelBytes * (params.area.width - 1);
354             break;
355         case SurfaceRotation::Rotated270Degrees:
356             // The source image is rotated 270 degrees counter-clockwise (or 90 degrees clockwise).
357             // Y-flip is always applied to rotated images.  The image is column-major, where each
358             // column (one step in the source x-axis for one step in the dest y-axis) is inputPitch
359             // BEFORE the previous column.  Along a column, each source pixel (one step along the
360             // y-axis for each step in the dest x-axis) is sourceFormat.pixelBytes BEFORE the
361             // previous pixel.  The first pixel is at the end of the source.
362             xAxisPitch = -inputPitchIn;
363             yAxisPitch = -static_cast<int>(sourceFormat.pixelBytes);
364             destWidth  = params.area.height;
365             destHeight = params.area.width;
366             source += inputPitch * (params.area.height - 1) +
367                       sourceFormat.pixelBytes * (params.area.width - 1);
368             break;
369         default:
370             UNREACHABLE();
371             break;
372     }
373 
374     if (params.rotation == SurfaceRotation::Identity && sourceFormat == *params.destFormat)
375     {
376         // Direct copy possible
377         for (int y = 0; y < params.area.height; ++y)
378         {
379             memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
380                    params.area.width * sourceFormat.pixelBytes);
381         }
382         return;
383     }
384 
385     PixelCopyFunction fastCopyFunc = sourceFormat.fastCopyFunctions.get(params.destFormat->id);
386 
387     if (fastCopyFunc)
388     {
389         // Fast copy is possible through some special function
390         for (int y = 0; y < destHeight; ++y)
391         {
392             for (int x = 0; x < destWidth; ++x)
393             {
394                 uint8_t *dest =
395                     destWithOffset + y * params.outputPitch + x * params.destFormat->pixelBytes;
396                 const uint8_t *src = source + y * yAxisPitch + x * xAxisPitch;
397 
398                 fastCopyFunc(src, dest);
399             }
400         }
401         return;
402     }
403 
404     PixelWriteFunction pixelWriteFunction = params.destFormat->pixelWriteFunction;
405     ASSERT(pixelWriteFunction != nullptr);
406 
407     // Maximum size of any Color<T> type used.
408     uint8_t temp[16];
409     static_assert(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) &&
410                       sizeof(temp) >= sizeof(gl::ColorI) &&
411                       sizeof(temp) >= sizeof(angle::DepthStencil),
412                   "Unexpected size of pixel struct.");
413 
414     PixelReadFunction pixelReadFunction = sourceFormat.pixelReadFunction;
415     ASSERT(pixelReadFunction != nullptr);
416 
417     for (int y = 0; y < destHeight; ++y)
418     {
419         for (int x = 0; x < destWidth; ++x)
420         {
421             uint8_t *dest =
422                 destWithOffset + y * params.outputPitch + x * params.destFormat->pixelBytes;
423             const uint8_t *src = source + y * yAxisPitch + x * xAxisPitch;
424 
425             // readFunc and writeFunc will be using the same type of color, CopyTexImage
426             // will not allow the copy otherwise.
427             pixelReadFunction(src, temp);
428             pixelWriteFunction(temp, dest);
429         }
430     }
431 }
432 
has(angle::FormatID formatID) const433 bool FastCopyFunctionMap::has(angle::FormatID formatID) const
434 {
435     return (get(formatID) != nullptr);
436 }
437 
get(angle::FormatID formatID) const438 PixelCopyFunction FastCopyFunctionMap::get(angle::FormatID formatID) const
439 {
440     for (size_t index = 0; index < mSize; ++index)
441     {
442         if (mData[index].formatID == formatID)
443         {
444             return mData[index].func;
445         }
446     }
447 
448     return nullptr;
449 }
450 
ShouldUseDebugLayers(const egl::AttributeMap & attribs)451 bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
452 {
453     EGLAttrib debugSetting =
454         attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
455 
456     // Prefer to enable debug layers when available.
457 #if defined(ANGLE_ENABLE_ASSERTS)
458     return (debugSetting != EGL_FALSE);
459 #else
460     return (debugSetting == EGL_TRUE);
461 #endif  // defined(ANGLE_ENABLE_ASSERTS)
462 }
463 
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)464 void CopyImageCHROMIUM(const uint8_t *sourceData,
465                        size_t sourceRowPitch,
466                        size_t sourcePixelBytes,
467                        size_t sourceDepthPitch,
468                        PixelReadFunction pixelReadFunction,
469                        uint8_t *destData,
470                        size_t destRowPitch,
471                        size_t destPixelBytes,
472                        size_t destDepthPitch,
473                        PixelWriteFunction pixelWriteFunction,
474                        GLenum destUnsizedFormat,
475                        GLenum destComponentType,
476                        size_t width,
477                        size_t height,
478                        size_t depth,
479                        bool unpackFlipY,
480                        bool unpackPremultiplyAlpha,
481                        bool unpackUnmultiplyAlpha)
482 {
483     using ConversionFunction              = void (*)(gl::ColorF *);
484     ConversionFunction conversionFunction = CopyColor;
485     if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
486     {
487         if (unpackPremultiplyAlpha)
488         {
489             conversionFunction = PremultiplyAlpha;
490         }
491         else
492         {
493             conversionFunction = UnmultiplyAlpha;
494         }
495     }
496 
497     auto clipChannelsFunction = ClipChannelsNoOp;
498     switch (destUnsizedFormat)
499     {
500         case GL_RED:
501             clipChannelsFunction = ClipChannelsR;
502             break;
503         case GL_RG:
504             clipChannelsFunction = ClipChannelsRG;
505             break;
506         case GL_RGB:
507             clipChannelsFunction = ClipChannelsRGB;
508             break;
509         case GL_LUMINANCE:
510             clipChannelsFunction = ClipChannelsLuminance;
511             break;
512         case GL_ALPHA:
513             clipChannelsFunction = ClipChannelsAlpha;
514             break;
515     }
516 
517     auto writeFunction = (destComponentType == GL_UNSIGNED_INT) ? WriteUintColor : WriteFloatColor;
518 
519     for (size_t z = 0; z < depth; z++)
520     {
521         for (size_t y = 0; y < height; y++)
522         {
523             for (size_t x = 0; x < width; x++)
524             {
525                 const uint8_t *sourcePixelData =
526                     sourceData + y * sourceRowPitch + x * sourcePixelBytes + z * sourceDepthPitch;
527 
528                 gl::ColorF sourceColor;
529                 pixelReadFunction(sourcePixelData, reinterpret_cast<uint8_t *>(&sourceColor));
530 
531                 conversionFunction(&sourceColor);
532                 clipChannelsFunction(&sourceColor);
533 
534                 size_t destY = 0;
535                 if (unpackFlipY)
536                 {
537                     destY += (height - 1);
538                     destY -= y;
539                 }
540                 else
541                 {
542                     destY += y;
543                 }
544 
545                 uint8_t *destPixelData =
546                     destData + destY * destRowPitch + x * destPixelBytes + z * destDepthPitch;
547                 writeFunction(sourceColor, pixelWriteFunction, destPixelData);
548             }
549         }
550     }
551 }
552 
553 // IncompleteTextureSet implementation.
IncompleteTextureSet()554 IncompleteTextureSet::IncompleteTextureSet() : mIncompleteTextureBufferAttachment(nullptr) {}
555 
~IncompleteTextureSet()556 IncompleteTextureSet::~IncompleteTextureSet() {}
557 
onDestroy(const gl::Context * context)558 void IncompleteTextureSet::onDestroy(const gl::Context *context)
559 {
560     // Clear incomplete textures.
561     for (auto &incompleteTextures : mIncompleteTextures)
562     {
563         for (auto &incompleteTexture : incompleteTextures)
564         {
565             if (incompleteTexture.get() != nullptr)
566             {
567                 incompleteTexture->onDestroy(context);
568                 incompleteTexture.set(context, nullptr);
569             }
570         }
571     }
572     if (mIncompleteTextureBufferAttachment != nullptr)
573     {
574         mIncompleteTextureBufferAttachment->onDestroy(context);
575         mIncompleteTextureBufferAttachment = nullptr;
576     }
577 }
578 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::SamplerFormat format,MultisampleTextureInitializer * multisampleInitializer,gl::Texture ** textureOut)579 angle::Result IncompleteTextureSet::getIncompleteTexture(
580     const gl::Context *context,
581     gl::TextureType type,
582     gl::SamplerFormat format,
583     MultisampleTextureInitializer *multisampleInitializer,
584     gl::Texture **textureOut)
585 {
586     *textureOut = mIncompleteTextures[format][type].get();
587     if (*textureOut != nullptr)
588     {
589         return angle::Result::Continue;
590     }
591 
592     ContextImpl *implFactory = context->getImplementation();
593 
594     const gl::Extents colorSize(1, 1, 1);
595     gl::PixelUnpackState unpack;
596     unpack.alignment = 1;
597     const gl::Box area(0, 0, 0, 1, 1, 1);
598     const IncompleteTextureParameters &incompleteTextureParam =
599         kIncompleteTextureParameters[format];
600 
601     // If a texture is external use a 2D texture for the incomplete texture
602     gl::TextureType createType = (type == gl::TextureType::External) ? gl::TextureType::_2D : type;
603 
604     gl::Texture *tex =
605         new gl::Texture(implFactory, {std::numeric_limits<GLuint>::max()}, createType);
606     angle::UniqueObjectPointer<gl::Texture, gl::Context> t(tex, context);
607 
608     // This is a bit of a kludge but is necessary to consume the error.
609     gl::Context *mutableContext = const_cast<gl::Context *>(context);
610 
611     if (createType == gl::TextureType::Buffer)
612     {
613         constexpr uint32_t kBufferInitData = 0;
614         mIncompleteTextureBufferAttachment =
615             new gl::Buffer(implFactory, {std::numeric_limits<GLuint>::max()});
616         ANGLE_TRY(mIncompleteTextureBufferAttachment->bufferData(
617             mutableContext, gl::BufferBinding::Texture, &kBufferInitData, sizeof(kBufferInitData),
618             gl::BufferUsage::StaticDraw));
619     }
620     else if (createType == gl::TextureType::_2DMultisample)
621     {
622         ANGLE_TRY(t->setStorageMultisample(mutableContext, createType, 1,
623                                            incompleteTextureParam.sizedInternalFormat, colorSize,
624                                            true));
625     }
626     else
627     {
628         ANGLE_TRY(t->setStorage(mutableContext, createType, 1,
629                                 incompleteTextureParam.sizedInternalFormat, colorSize));
630     }
631 
632     if (type == gl::TextureType::CubeMap)
633     {
634         for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
635         {
636             ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr, face, 0, area,
637                                      incompleteTextureParam.format, incompleteTextureParam.type,
638                                      incompleteTextureParam.clearColor));
639         }
640     }
641     else if (type == gl::TextureType::_2DMultisample)
642     {
643         // Call a specialized clear function to init a multisample texture.
644         ANGLE_TRY(multisampleInitializer->initializeMultisampleTextureToBlack(context, t.get()));
645     }
646     else if (type == gl::TextureType::Buffer)
647     {
648         ANGLE_TRY(t->setBuffer(context, mIncompleteTextureBufferAttachment,
649                                incompleteTextureParam.sizedInternalFormat));
650     }
651     else
652     {
653         ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
654                                  gl::NonCubeTextureTypeToTarget(createType), 0, area,
655                                  incompleteTextureParam.format, incompleteTextureParam.type,
656                                  incompleteTextureParam.clearColor));
657     }
658 
659     if (format == gl::SamplerFormat::Shadow)
660     {
661         // To avoid the undefined spec behavior for shadow samplers with a depth texture, we set the
662         // compare mode to GL_COMPARE_REF_TO_TEXTURE
663         ASSERT(!t->hasObservers());
664         t->setCompareMode(context, GL_COMPARE_REF_TO_TEXTURE);
665     }
666 
667     ANGLE_TRY(t->syncState(context, gl::Command::Other));
668 
669     mIncompleteTextures[format][type].set(context, t.release());
670     *textureOut = mIncompleteTextures[format][type].get();
671     return angle::Result::Continue;
672 }
673 
674 #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
675     template void SetFloatUniformMatrix##api<cols, rows>::Run(     \
676         unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *)
677 
678 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
679 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
680 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
681 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
682 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
683 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3);
684 
685 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2);
686 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3);
687 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3);
688 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2);
689 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4);
690 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4);
691 
692 #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
693 
694 #define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
695     template void SetFloatUniformMatrix##api<cols, 4>::Run(unsigned int, unsigned int, GLsizei, \
696                                                            GLboolean, const GLfloat *, uint8_t *)
697 
698 template <int cols>
699 struct SetFloatUniformMatrixGLSL<cols, 4>
700 {
701     static void Run(unsigned int arrayElementOffset,
702                     unsigned int elementCount,
703                     GLsizei countIn,
704                     GLboolean transpose,
705                     const GLfloat *value,
706                     uint8_t *targetData);
707 };
708 
709 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
710 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
711 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
712 
713 #undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC
714 
715 #define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
716     template void SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \
717                                                            GLboolean, const GLfloat *, uint8_t *)
718 
719 template <int rows>
720 struct SetFloatUniformMatrixHLSL<4, rows>
721 {
722     static void Run(unsigned int arrayElementOffset,
723                     unsigned int elementCount,
724                     GLsizei countIn,
725                     GLboolean transpose,
726                     const GLfloat *value,
727                     uint8_t *targetData);
728 };
729 
730 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
731 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
732 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
733 
734 #undef ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC
735 
736 template <int cols>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)737 void SetFloatUniformMatrixGLSL<cols, 4>::Run(unsigned int arrayElementOffset,
738                                              unsigned int elementCount,
739                                              GLsizei countIn,
740                                              GLboolean transpose,
741                                              const GLfloat *value,
742                                              uint8_t *targetData)
743 {
744     const bool isSrcColumnMajor = !transpose;
745     if (isSrcColumnMajor)
746     {
747         // Both src and dst matrixs are has same layout,
748         // a single memcpy updates all the matrices
749         constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4;
750         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
751                                   targetData);
752     }
753     else
754     {
755         // fallback to general cases
756         SetFloatUniformMatrix<false, cols, 4, true, cols, 4>(arrayElementOffset, elementCount,
757                                                              countIn, value, targetData);
758     }
759 }
760 
761 template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)762 void SetFloatUniformMatrixGLSL<cols, rows>::Run(unsigned int arrayElementOffset,
763                                                 unsigned int elementCount,
764                                                 GLsizei countIn,
765                                                 GLboolean transpose,
766                                                 const GLfloat *value,
767                                                 uint8_t *targetData)
768 {
769     const bool isSrcColumnMajor = !transpose;
770     // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
771     if (isSrcColumnMajor)
772     {
773         SetFloatUniformMatrix<true, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
774                                                                countIn, value, targetData);
775     }
776     else
777     {
778         SetFloatUniformMatrix<false, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
779                                                                 countIn, value, targetData);
780     }
781 }
782 
783 template <int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)784 void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset,
785                                              unsigned int elementCount,
786                                              GLsizei countIn,
787                                              GLboolean transpose,
788                                              const GLfloat *value,
789                                              uint8_t *targetData)
790 {
791     const bool isSrcColumnMajor = !transpose;
792     if (!isSrcColumnMajor)
793     {
794         // Both src and dst matrixs are has same layout,
795         // a single memcpy updates all the matrices
796         constexpr size_t srcMatrixSize = sizeof(GLfloat) * 4 * rows;
797         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
798                                   targetData);
799     }
800     else
801     {
802         // fallback to general cases
803         SetFloatUniformMatrix<true, 4, rows, false, 4, rows>(arrayElementOffset, elementCount,
804                                                              countIn, value, targetData);
805     }
806 }
807 
808 template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)809 void SetFloatUniformMatrixHLSL<cols, rows>::Run(unsigned int arrayElementOffset,
810                                                 unsigned int elementCount,
811                                                 GLsizei countIn,
812                                                 GLboolean transpose,
813                                                 const GLfloat *value,
814                                                 uint8_t *targetData)
815 {
816     const bool isSrcColumnMajor = !transpose;
817     // Internally store matrices as row-major to accomodate HLSL matrix indexing.  Each row is
818     // padded to 4 columns.
819     if (!isSrcColumnMajor)
820     {
821         SetFloatUniformMatrix<false, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
822                                                                  countIn, value, targetData);
823     }
824     else
825     {
826         SetFloatUniformMatrix<true, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
827                                                                 countIn, value, targetData);
828     }
829 }
830 
831 template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
832 template void GetMatrixUniform<GLuint>(GLenum, GLuint *, const GLuint *, bool);
833 
GetMatrixUniform(GLenum type,GLfloat * dataOut,const GLfloat * source,bool transpose)834 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose)
835 {
836     int columns = gl::VariableColumnCount(type);
837     int rows    = gl::VariableRowCount(type);
838     for (GLint col = 0; col < columns; ++col)
839     {
840         for (GLint row = 0; row < rows; ++row)
841         {
842             GLfloat *outptr = dataOut + ((col * rows) + row);
843             const GLfloat *inptr =
844                 transpose ? source + ((row * 4) + col) : source + ((col * 4) + row);
845             *outptr = *inptr;
846         }
847     }
848 }
849 
850 template <typename NonFloatT>
GetMatrixUniform(GLenum type,NonFloatT * dataOut,const NonFloatT * source,bool transpose)851 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose)
852 {
853     UNREACHABLE();
854 }
855 
GetFormatFromFormatType(GLenum format,GLenum type)856 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type)
857 {
858     GLenum sizedInternalFormat    = gl::GetInternalFormatInfo(format, type).sizedInternalFormat;
859     angle::FormatID angleFormatID = angle::Format::InternalFormatToID(sizedInternalFormat);
860     return angle::Format::Get(angleFormatID);
861 }
862 
ComputeStartVertex(ContextImpl * contextImpl,const gl::IndexRange & indexRange,GLint baseVertex,GLint * firstVertexOut)863 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
864                                  const gl::IndexRange &indexRange,
865                                  GLint baseVertex,
866                                  GLint *firstVertexOut)
867 {
868     // The entire index range should be within the limits of a 32-bit uint because the largest
869     // GL index type is GL_UNSIGNED_INT.
870     ASSERT(indexRange.start <= std::numeric_limits<uint32_t>::max() &&
871            indexRange.end <= std::numeric_limits<uint32_t>::max());
872 
873     // The base vertex is only used in DrawElementsIndirect. Given the assertion above and the
874     // type of mBaseVertex (GLint), adding them both as 64-bit ints is safe.
875     int64_t startVertexInt64 =
876         static_cast<int64_t>(baseVertex) + static_cast<int64_t>(indexRange.start);
877 
878     // OpenGL ES 3.2 spec section 10.5: "Behavior of DrawElementsOneInstance is undefined if the
879     // vertex ID is negative for any element"
880     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 >= 0);
881 
882     // OpenGL ES 3.2 spec section 10.5: "If the vertex ID is larger than the maximum value
883     // representable by type, it should behave as if the calculation were upconverted to 32-bit
884     // unsigned integers(with wrapping on overflow conditions)." ANGLE does not fully handle
885     // these rules, an overflow error is returned if the start vertex cannot be stored in a
886     // 32-bit signed integer.
887     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max());
888 
889     *firstVertexOut = static_cast<GLint>(startVertexInt64);
890     return angle::Result::Continue;
891 }
892 
GetVertexRangeInfo(const gl::Context * context,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLint baseVertex,GLint * startVertexOut,size_t * vertexCountOut)893 angle::Result GetVertexRangeInfo(const gl::Context *context,
894                                  GLint firstVertex,
895                                  GLsizei vertexOrIndexCount,
896                                  gl::DrawElementsType indexTypeOrInvalid,
897                                  const void *indices,
898                                  GLint baseVertex,
899                                  GLint *startVertexOut,
900                                  size_t *vertexCountOut)
901 {
902     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
903     {
904         gl::IndexRange indexRange;
905         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
906             context, indexTypeOrInvalid, vertexOrIndexCount, indices, &indexRange));
907         ANGLE_TRY(ComputeStartVertex(context->getImplementation(), indexRange, baseVertex,
908                                      startVertexOut));
909         *vertexCountOut = indexRange.vertexCount();
910     }
911     else
912     {
913         *startVertexOut = firstVertex;
914         *vertexCountOut = vertexOrIndexCount;
915     }
916     return angle::Result::Continue;
917 }
918 
ClipRectToScissor(const gl::State & glState,const gl::Rectangle & rect,bool invertY)919 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY)
920 {
921     // If the scissor test isn't enabled, assume it has infinite size.  Its intersection with the
922     // rect would be the rect itself.
923     //
924     // Note that on Vulkan, returning this (as opposed to a fixed max-int-sized rect) could lead to
925     // unnecessary pipeline creations if two otherwise identical pipelines are used on framebuffers
926     // with different sizes.  If such usage is observed in an application, we should investigate
927     // possible optimizations.
928     if (!glState.isScissorTestEnabled())
929     {
930         return rect;
931     }
932 
933     gl::Rectangle clippedRect;
934     if (!gl::ClipRectangle(glState.getScissor(), rect, &clippedRect))
935     {
936         return gl::Rectangle();
937     }
938 
939     if (invertY)
940     {
941         clippedRect.y = rect.height - clippedRect.y - clippedRect.height;
942     }
943 
944     return clippedRect;
945 }
946 
LogFeatureStatus(const angle::FeatureSetBase & features,const std::vector<std::string> & featureNames,bool enabled)947 void LogFeatureStatus(const angle::FeatureSetBase &features,
948                       const std::vector<std::string> &featureNames,
949                       bool enabled)
950 {
951     for (const std::string &name : featureNames)
952     {
953         if (features.getFeatures().find(name) != features.getFeatures().end())
954         {
955             INFO() << "Feature: " << name << (enabled ? " enabled" : " disabled");
956         }
957     }
958 }
959 
ApplyFeatureOverrides(angle::FeatureSetBase * features,const egl::DisplayState & state)960 void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state)
961 {
962     features->overrideFeatures(state.featureOverridesEnabled, true);
963     features->overrideFeatures(state.featureOverridesDisabled, false);
964 
965     // Override with environment as well.
966     constexpr char kAngleFeatureOverridesEnabledEnvName[]  = "ANGLE_FEATURE_OVERRIDES_ENABLED";
967     constexpr char kAngleFeatureOverridesDisabledEnvName[] = "ANGLE_FEATURE_OVERRIDES_DISABLED";
968     constexpr char kAngleFeatureOverridesEnabledPropertyName[] =
969         "debug.angle.feature_overrides_enabled";
970     constexpr char kAngleFeatureOverridesDisabledPropertyName[] =
971         "debug.angle.feature_overrides_disabled";
972     std::vector<std::string> overridesEnabled =
973         angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
974             kAngleFeatureOverridesEnabledEnvName, kAngleFeatureOverridesEnabledPropertyName, ":");
975     std::vector<std::string> overridesDisabled =
976         angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
977             kAngleFeatureOverridesDisabledEnvName, kAngleFeatureOverridesDisabledPropertyName, ":");
978     features->overrideFeatures(overridesEnabled, true);
979     LogFeatureStatus(*features, overridesEnabled, true);
980 
981     features->overrideFeatures(overridesDisabled, false);
982     LogFeatureStatus(*features, overridesDisabled, false);
983 }
984 
GetSamplePosition(GLsizei sampleCount,size_t index,GLfloat * xy)985 void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
986 {
987     ASSERT(gl::isPow2(sampleCount));
988     if (sampleCount > 16)
989     {
990         // Vulkan (and D3D11) doesn't have standard sample positions for 32 and 64 samples (and no
991         // drivers are known to support that many samples)
992         xy[0] = 0.5f;
993         xy[1] = 0.5f;
994     }
995     else
996     {
997         size_t indexKey = static_cast<size_t>(gl::log2(sampleCount));
998         ASSERT(indexKey < kSamplePositions.size() &&
999                (2 * index + 1) < kSamplePositions[indexKey].size());
1000 
1001         xy[0] = kSamplePositions[indexKey][2 * index];
1002         xy[1] = kSamplePositions[indexKey][2 * index + 1];
1003     }
1004 }
1005 
1006 // These macros are to avoid code too much duplication for variations of multi draw types
1007 #define DRAW_ARRAYS__ contextImpl->drawArrays(context, mode, firsts[drawID], counts[drawID])
1008 #define DRAW_ARRAYS_INSTANCED_                                                      \
1009     contextImpl->drawArraysInstanced(context, mode, firsts[drawID], counts[drawID], \
1010                                      instanceCounts[drawID])
1011 #define DRAW_ELEMENTS__ \
1012     contextImpl->drawElements(context, mode, counts[drawID], type, indices[drawID])
1013 #define DRAW_ELEMENTS_INSTANCED_                                                             \
1014     contextImpl->drawElementsInstanced(context, mode, counts[drawID], type, indices[drawID], \
1015                                        instanceCounts[drawID])
1016 #define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE                                                     \
1017     contextImpl->drawArraysInstancedBaseInstance(context, mode, firsts[drawID], counts[drawID], \
1018                                                  instanceCounts[drawID], baseInstances[drawID])
1019 #define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE                             \
1020     contextImpl->drawElementsInstancedBaseVertexBaseInstance(                         \
1021         context, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID], \
1022         baseVertices[drawID], baseInstances[drawID])
1023 #define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
1024 
1025 #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
1026     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)                                     \
1027     {                                                                                          \
1028         if (ANGLE_NOOP_DRAW(instanced))                                                        \
1029         {                                                                                      \
1030             ANGLE_TRY(contextImpl->handleNoopDrawEvent());                                     \
1031             continue;                                                                          \
1032         }                                                                                      \
1033         ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID);                                          \
1034         ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]);                    \
1035         ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]);               \
1036         ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi));                                       \
1037         ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced);                                        \
1038         gl::MarkShaderStorageUsage(context);                                                   \
1039     }
1040 
MultiDrawArraysGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)1041 angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
1042                                      const gl::Context *context,
1043                                      gl::PrimitiveMode mode,
1044                                      const GLint *firsts,
1045                                      const GLsizei *counts,
1046                                      GLsizei drawcount)
1047 {
1048     gl::Program *programObject = context->getState().getLinkedProgram(context);
1049     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1050     if (hasDrawID)
1051     {
1052         MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0)
1053     }
1054     else
1055     {
1056         MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0)
1057     }
1058 
1059     return angle::Result::Continue;
1060 }
1061 
MultiDrawArraysIndirectGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)1062 angle::Result MultiDrawArraysIndirectGeneral(ContextImpl *contextImpl,
1063                                              const gl::Context *context,
1064                                              gl::PrimitiveMode mode,
1065                                              const void *indirect,
1066                                              GLsizei drawcount,
1067                                              GLsizei stride)
1068 {
1069     const GLubyte *indirectPtr = static_cast<const GLubyte *>(indirect);
1070 
1071     for (auto count = 0; count < drawcount; count++)
1072     {
1073         ANGLE_TRY(contextImpl->drawArraysIndirect(
1074             context, mode, reinterpret_cast<const gl::DrawArraysIndirectCommand *>(indirectPtr)));
1075         if (stride == 0)
1076         {
1077             indirectPtr += sizeof(gl::DrawArraysIndirectCommand);
1078         }
1079         else
1080         {
1081             indirectPtr += stride;
1082         }
1083     }
1084 
1085     return angle::Result::Continue;
1086 }
1087 
MultiDrawArraysInstancedGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)1088 angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
1089                                               const gl::Context *context,
1090                                               gl::PrimitiveMode mode,
1091                                               const GLint *firsts,
1092                                               const GLsizei *counts,
1093                                               const GLsizei *instanceCounts,
1094                                               GLsizei drawcount)
1095 {
1096     gl::Program *programObject = context->getState().getLinkedProgram(context);
1097     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1098     if (hasDrawID)
1099     {
1100         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0)
1101     }
1102     else
1103     {
1104         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0)
1105     }
1106 
1107     return angle::Result::Continue;
1108 }
1109 
MultiDrawElementsGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)1110 angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
1111                                        const gl::Context *context,
1112                                        gl::PrimitiveMode mode,
1113                                        const GLsizei *counts,
1114                                        gl::DrawElementsType type,
1115                                        const GLvoid *const *indices,
1116                                        GLsizei drawcount)
1117 {
1118     gl::Program *programObject = context->getState().getLinkedProgram(context);
1119     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1120     if (hasDrawID)
1121     {
1122         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0)
1123     }
1124     else
1125     {
1126         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0)
1127     }
1128 
1129     return angle::Result::Continue;
1130 }
1131 
MultiDrawElementsIndirectGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)1132 angle::Result MultiDrawElementsIndirectGeneral(ContextImpl *contextImpl,
1133                                                const gl::Context *context,
1134                                                gl::PrimitiveMode mode,
1135                                                gl::DrawElementsType type,
1136                                                const void *indirect,
1137                                                GLsizei drawcount,
1138                                                GLsizei stride)
1139 {
1140     const GLubyte *indirectPtr = static_cast<const GLubyte *>(indirect);
1141 
1142     for (auto count = 0; count < drawcount; count++)
1143     {
1144         ANGLE_TRY(contextImpl->drawElementsIndirect(
1145             context, mode, type,
1146             reinterpret_cast<const gl::DrawElementsIndirectCommand *>(indirectPtr)));
1147         if (stride == 0)
1148         {
1149             indirectPtr += sizeof(gl::DrawElementsIndirectCommand);
1150         }
1151         else
1152         {
1153             indirectPtr += stride;
1154         }
1155     }
1156 
1157     return angle::Result::Continue;
1158 }
1159 
MultiDrawElementsInstancedGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)1160 angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
1161                                                 const gl::Context *context,
1162                                                 gl::PrimitiveMode mode,
1163                                                 const GLsizei *counts,
1164                                                 gl::DrawElementsType type,
1165                                                 const GLvoid *const *indices,
1166                                                 const GLsizei *instanceCounts,
1167                                                 GLsizei drawcount)
1168 {
1169     gl::Program *programObject = context->getState().getLinkedProgram(context);
1170     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1171     if (hasDrawID)
1172     {
1173         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0)
1174     }
1175     else
1176     {
1177         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0)
1178     }
1179 
1180     return angle::Result::Continue;
1181 }
1182 
MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)1183 angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
1184                                                           const gl::Context *context,
1185                                                           gl::PrimitiveMode mode,
1186                                                           const GLint *firsts,
1187                                                           const GLsizei *counts,
1188                                                           const GLsizei *instanceCounts,
1189                                                           const GLuint *baseInstances,
1190                                                           GLsizei drawcount)
1191 {
1192     gl::Program *programObject = context->getState().getLinkedProgram(context);
1193     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1194     const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
1195     ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance);
1196 
1197     if (hasDrawID && hasBaseInstance)
1198     {
1199         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1)
1200     }
1201     else if (hasDrawID)
1202     {
1203         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0)
1204     }
1205     else if (hasBaseInstance)
1206     {
1207         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1)
1208     }
1209     else
1210     {
1211         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0)
1212     }
1213 
1214     return angle::Result::Continue;
1215 }
1216 
MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)1217 angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
1218                                                                       const gl::Context *context,
1219                                                                       gl::PrimitiveMode mode,
1220                                                                       const GLsizei *counts,
1221                                                                       gl::DrawElementsType type,
1222                                                                       const GLvoid *const *indices,
1223                                                                       const GLsizei *instanceCounts,
1224                                                                       const GLint *baseVertices,
1225                                                                       const GLuint *baseInstances,
1226                                                                       GLsizei drawcount)
1227 {
1228     gl::Program *programObject = context->getState().getLinkedProgram(context);
1229     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1230     const bool hasBaseVertex   = programObject && programObject->hasBaseVertexUniform();
1231     const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
1232     ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance);
1233 
1234     if (hasDrawID)
1235     {
1236         if (hasBaseVertex)
1237         {
1238             if (hasBaseInstance)
1239             {
1240                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1)
1241             }
1242             else
1243             {
1244                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0)
1245             }
1246         }
1247         else
1248         {
1249             if (hasBaseInstance)
1250             {
1251                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1)
1252             }
1253             else
1254             {
1255                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0)
1256             }
1257         }
1258     }
1259     else
1260     {
1261         if (hasBaseVertex)
1262         {
1263             if (hasBaseInstance)
1264             {
1265                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1)
1266             }
1267             else
1268             {
1269                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0)
1270             }
1271         }
1272         else
1273         {
1274             if (hasBaseInstance)
1275             {
1276                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1)
1277             }
1278             else
1279             {
1280                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0)
1281             }
1282         }
1283     }
1284 
1285     return angle::Result::Continue;
1286 }
1287 
ResetBaseVertexBaseInstance(gl::Program * programObject,bool resetBaseVertex,bool resetBaseInstance)1288 ResetBaseVertexBaseInstance::ResetBaseVertexBaseInstance(gl::Program *programObject,
1289                                                          bool resetBaseVertex,
1290                                                          bool resetBaseInstance)
1291     : mProgramObject(programObject),
1292       mResetBaseVertex(resetBaseVertex),
1293       mResetBaseInstance(resetBaseInstance)
1294 {}
1295 
~ResetBaseVertexBaseInstance()1296 ResetBaseVertexBaseInstance::~ResetBaseVertexBaseInstance()
1297 {
1298     if (mProgramObject)
1299     {
1300         // Reset emulated uniforms to zero to avoid affecting other draw calls
1301         if (mResetBaseVertex)
1302         {
1303             mProgramObject->setBaseVertexUniform(0);
1304         }
1305 
1306         if (mResetBaseInstance)
1307         {
1308             mProgramObject->setBaseInstanceUniform(0);
1309         }
1310     }
1311 }
1312 
ConvertToSRGB(angle::FormatID formatID)1313 angle::FormatID ConvertToSRGB(angle::FormatID formatID)
1314 {
1315     switch (formatID)
1316     {
1317         case angle::FormatID::R8_UNORM:
1318             return angle::FormatID::R8_UNORM_SRGB;
1319         case angle::FormatID::R8G8_UNORM:
1320             return angle::FormatID::R8G8_UNORM_SRGB;
1321         case angle::FormatID::R8G8B8_UNORM:
1322             return angle::FormatID::R8G8B8_UNORM_SRGB;
1323         case angle::FormatID::R8G8B8A8_UNORM:
1324             return angle::FormatID::R8G8B8A8_UNORM_SRGB;
1325         case angle::FormatID::B8G8R8A8_UNORM:
1326             return angle::FormatID::B8G8R8A8_UNORM_SRGB;
1327         case angle::FormatID::BC1_RGB_UNORM_BLOCK:
1328             return angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
1329         case angle::FormatID::BC1_RGBA_UNORM_BLOCK:
1330             return angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
1331         case angle::FormatID::BC2_RGBA_UNORM_BLOCK:
1332             return angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
1333         case angle::FormatID::BC3_RGBA_UNORM_BLOCK:
1334             return angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
1335         case angle::FormatID::BC7_RGBA_UNORM_BLOCK:
1336             return angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK;
1337         case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
1338             return angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK;
1339         case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
1340             return angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK;
1341         case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
1342             return angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK;
1343         case angle::FormatID::ASTC_4x4_UNORM_BLOCK:
1344             return angle::FormatID::ASTC_4x4_SRGB_BLOCK;
1345         case angle::FormatID::ASTC_5x4_UNORM_BLOCK:
1346             return angle::FormatID::ASTC_5x4_SRGB_BLOCK;
1347         case angle::FormatID::ASTC_5x5_UNORM_BLOCK:
1348             return angle::FormatID::ASTC_5x5_SRGB_BLOCK;
1349         case angle::FormatID::ASTC_6x5_UNORM_BLOCK:
1350             return angle::FormatID::ASTC_6x5_SRGB_BLOCK;
1351         case angle::FormatID::ASTC_6x6_UNORM_BLOCK:
1352             return angle::FormatID::ASTC_6x6_SRGB_BLOCK;
1353         case angle::FormatID::ASTC_8x5_UNORM_BLOCK:
1354             return angle::FormatID::ASTC_8x5_SRGB_BLOCK;
1355         case angle::FormatID::ASTC_8x6_UNORM_BLOCK:
1356             return angle::FormatID::ASTC_8x6_SRGB_BLOCK;
1357         case angle::FormatID::ASTC_8x8_UNORM_BLOCK:
1358             return angle::FormatID::ASTC_8x8_SRGB_BLOCK;
1359         case angle::FormatID::ASTC_10x5_UNORM_BLOCK:
1360             return angle::FormatID::ASTC_10x5_SRGB_BLOCK;
1361         case angle::FormatID::ASTC_10x6_UNORM_BLOCK:
1362             return angle::FormatID::ASTC_10x6_SRGB_BLOCK;
1363         case angle::FormatID::ASTC_10x8_UNORM_BLOCK:
1364             return angle::FormatID::ASTC_10x8_SRGB_BLOCK;
1365         case angle::FormatID::ASTC_10x10_UNORM_BLOCK:
1366             return angle::FormatID::ASTC_10x10_SRGB_BLOCK;
1367         case angle::FormatID::ASTC_12x10_UNORM_BLOCK:
1368             return angle::FormatID::ASTC_12x10_SRGB_BLOCK;
1369         case angle::FormatID::ASTC_12x12_UNORM_BLOCK:
1370             return angle::FormatID::ASTC_12x12_SRGB_BLOCK;
1371         default:
1372             return angle::FormatID::NONE;
1373     }
1374 }
1375 
ConvertToLinear(angle::FormatID formatID)1376 angle::FormatID ConvertToLinear(angle::FormatID formatID)
1377 {
1378     switch (formatID)
1379     {
1380         case angle::FormatID::R8_UNORM_SRGB:
1381             return angle::FormatID::R8_UNORM;
1382         case angle::FormatID::R8G8_UNORM_SRGB:
1383             return angle::FormatID::R8G8_UNORM;
1384         case angle::FormatID::R8G8B8_UNORM_SRGB:
1385             return angle::FormatID::R8G8B8_UNORM;
1386         case angle::FormatID::R8G8B8A8_UNORM_SRGB:
1387             return angle::FormatID::R8G8B8A8_UNORM;
1388         case angle::FormatID::B8G8R8A8_UNORM_SRGB:
1389             return angle::FormatID::B8G8R8A8_UNORM;
1390         case angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK:
1391             return angle::FormatID::BC1_RGB_UNORM_BLOCK;
1392         case angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK:
1393             return angle::FormatID::BC1_RGBA_UNORM_BLOCK;
1394         case angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK:
1395             return angle::FormatID::BC2_RGBA_UNORM_BLOCK;
1396         case angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK:
1397             return angle::FormatID::BC3_RGBA_UNORM_BLOCK;
1398         case angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK:
1399             return angle::FormatID::BC7_RGBA_UNORM_BLOCK;
1400         case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
1401             return angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK;
1402         case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
1403             return angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK;
1404         case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
1405             return angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK;
1406         case angle::FormatID::ASTC_4x4_SRGB_BLOCK:
1407             return angle::FormatID::ASTC_4x4_UNORM_BLOCK;
1408         case angle::FormatID::ASTC_5x4_SRGB_BLOCK:
1409             return angle::FormatID::ASTC_5x4_UNORM_BLOCK;
1410         case angle::FormatID::ASTC_5x5_SRGB_BLOCK:
1411             return angle::FormatID::ASTC_5x5_UNORM_BLOCK;
1412         case angle::FormatID::ASTC_6x5_SRGB_BLOCK:
1413             return angle::FormatID::ASTC_6x5_UNORM_BLOCK;
1414         case angle::FormatID::ASTC_6x6_SRGB_BLOCK:
1415             return angle::FormatID::ASTC_6x6_UNORM_BLOCK;
1416         case angle::FormatID::ASTC_8x5_SRGB_BLOCK:
1417             return angle::FormatID::ASTC_8x5_UNORM_BLOCK;
1418         case angle::FormatID::ASTC_8x6_SRGB_BLOCK:
1419             return angle::FormatID::ASTC_8x6_UNORM_BLOCK;
1420         case angle::FormatID::ASTC_8x8_SRGB_BLOCK:
1421             return angle::FormatID::ASTC_8x8_UNORM_BLOCK;
1422         case angle::FormatID::ASTC_10x5_SRGB_BLOCK:
1423             return angle::FormatID::ASTC_10x5_UNORM_BLOCK;
1424         case angle::FormatID::ASTC_10x6_SRGB_BLOCK:
1425             return angle::FormatID::ASTC_10x6_UNORM_BLOCK;
1426         case angle::FormatID::ASTC_10x8_SRGB_BLOCK:
1427             return angle::FormatID::ASTC_10x8_UNORM_BLOCK;
1428         case angle::FormatID::ASTC_10x10_SRGB_BLOCK:
1429             return angle::FormatID::ASTC_10x10_UNORM_BLOCK;
1430         case angle::FormatID::ASTC_12x10_SRGB_BLOCK:
1431             return angle::FormatID::ASTC_12x10_UNORM_BLOCK;
1432         case angle::FormatID::ASTC_12x12_SRGB_BLOCK:
1433             return angle::FormatID::ASTC_12x12_UNORM_BLOCK;
1434         default:
1435             return angle::FormatID::NONE;
1436     }
1437 }
1438 
IsOverridableLinearFormat(angle::FormatID formatID)1439 bool IsOverridableLinearFormat(angle::FormatID formatID)
1440 {
1441     return ConvertToSRGB(formatID) != angle::FormatID::NONE;
1442 }
1443 }  // namespace rx
1444