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 
ShouldUseVirtualizedContexts(const egl::AttributeMap & attribs,bool defaultValue)464 bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue)
465 {
466     EGLAttrib virtualizedContextRequest =
467         attribs.get(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE, EGL_DONT_CARE);
468     if (defaultValue)
469     {
470         return (virtualizedContextRequest != EGL_FALSE);
471     }
472     else
473     {
474         return (virtualizedContextRequest == EGL_TRUE);
475     }
476 }
477 
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)478 void CopyImageCHROMIUM(const uint8_t *sourceData,
479                        size_t sourceRowPitch,
480                        size_t sourcePixelBytes,
481                        size_t sourceDepthPitch,
482                        PixelReadFunction pixelReadFunction,
483                        uint8_t *destData,
484                        size_t destRowPitch,
485                        size_t destPixelBytes,
486                        size_t destDepthPitch,
487                        PixelWriteFunction pixelWriteFunction,
488                        GLenum destUnsizedFormat,
489                        GLenum destComponentType,
490                        size_t width,
491                        size_t height,
492                        size_t depth,
493                        bool unpackFlipY,
494                        bool unpackPremultiplyAlpha,
495                        bool unpackUnmultiplyAlpha)
496 {
497     using ConversionFunction              = void (*)(gl::ColorF *);
498     ConversionFunction conversionFunction = CopyColor;
499     if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
500     {
501         if (unpackPremultiplyAlpha)
502         {
503             conversionFunction = PremultiplyAlpha;
504         }
505         else
506         {
507             conversionFunction = UnmultiplyAlpha;
508         }
509     }
510 
511     auto clipChannelsFunction = ClipChannelsNoOp;
512     switch (destUnsizedFormat)
513     {
514         case GL_RED:
515             clipChannelsFunction = ClipChannelsR;
516             break;
517         case GL_RG:
518             clipChannelsFunction = ClipChannelsRG;
519             break;
520         case GL_RGB:
521             clipChannelsFunction = ClipChannelsRGB;
522             break;
523         case GL_LUMINANCE:
524             clipChannelsFunction = ClipChannelsLuminance;
525             break;
526         case GL_ALPHA:
527             clipChannelsFunction = ClipChannelsAlpha;
528             break;
529     }
530 
531     auto writeFunction = (destComponentType == GL_UNSIGNED_INT) ? WriteUintColor : WriteFloatColor;
532 
533     for (size_t z = 0; z < depth; z++)
534     {
535         for (size_t y = 0; y < height; y++)
536         {
537             for (size_t x = 0; x < width; x++)
538             {
539                 const uint8_t *sourcePixelData =
540                     sourceData + y * sourceRowPitch + x * sourcePixelBytes + z * sourceDepthPitch;
541 
542                 gl::ColorF sourceColor;
543                 pixelReadFunction(sourcePixelData, reinterpret_cast<uint8_t *>(&sourceColor));
544 
545                 conversionFunction(&sourceColor);
546                 clipChannelsFunction(&sourceColor);
547 
548                 size_t destY = 0;
549                 if (unpackFlipY)
550                 {
551                     destY += (height - 1);
552                     destY -= y;
553                 }
554                 else
555                 {
556                     destY += y;
557                 }
558 
559                 uint8_t *destPixelData =
560                     destData + destY * destRowPitch + x * destPixelBytes + z * destDepthPitch;
561                 writeFunction(sourceColor, pixelWriteFunction, destPixelData);
562             }
563         }
564     }
565 }
566 
567 // IncompleteTextureSet implementation.
IncompleteTextureSet()568 IncompleteTextureSet::IncompleteTextureSet() : mIncompleteTextureBufferAttachment(nullptr) {}
569 
~IncompleteTextureSet()570 IncompleteTextureSet::~IncompleteTextureSet() {}
571 
onDestroy(const gl::Context * context)572 void IncompleteTextureSet::onDestroy(const gl::Context *context)
573 {
574     // Clear incomplete textures.
575     for (auto &incompleteTextures : mIncompleteTextures)
576     {
577         for (auto &incompleteTexture : incompleteTextures)
578         {
579             if (incompleteTexture.get() != nullptr)
580             {
581                 incompleteTexture->onDestroy(context);
582                 incompleteTexture.set(context, nullptr);
583             }
584         }
585     }
586     if (mIncompleteTextureBufferAttachment != nullptr)
587     {
588         mIncompleteTextureBufferAttachment->onDestroy(context);
589         mIncompleteTextureBufferAttachment = nullptr;
590     }
591 }
592 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::SamplerFormat format,MultisampleTextureInitializer * multisampleInitializer,gl::Texture ** textureOut)593 angle::Result IncompleteTextureSet::getIncompleteTexture(
594     const gl::Context *context,
595     gl::TextureType type,
596     gl::SamplerFormat format,
597     MultisampleTextureInitializer *multisampleInitializer,
598     gl::Texture **textureOut)
599 {
600     *textureOut = mIncompleteTextures[format][type].get();
601     if (*textureOut != nullptr)
602     {
603         return angle::Result::Continue;
604     }
605 
606     ContextImpl *implFactory = context->getImplementation();
607 
608     const gl::Extents colorSize(1, 1, 1);
609     gl::PixelUnpackState unpack;
610     unpack.alignment = 1;
611     const gl::Box area(0, 0, 0, 1, 1, 1);
612     const IncompleteTextureParameters &incompleteTextureParam =
613         kIncompleteTextureParameters[format];
614 
615     // If a texture is external use a 2D texture for the incomplete texture
616     gl::TextureType createType = (type == gl::TextureType::External) ? gl::TextureType::_2D : type;
617 
618     gl::Texture *tex =
619         new gl::Texture(implFactory, {std::numeric_limits<GLuint>::max()}, createType);
620     angle::UniqueObjectPointer<gl::Texture, gl::Context> t(tex, context);
621 
622     // This is a bit of a kludge but is necessary to consume the error.
623     gl::Context *mutableContext = const_cast<gl::Context *>(context);
624 
625     if (createType == gl::TextureType::Buffer)
626     {
627         constexpr uint32_t kBufferInitData = 0;
628         mIncompleteTextureBufferAttachment =
629             new gl::Buffer(implFactory, {std::numeric_limits<GLuint>::max()});
630         ANGLE_TRY(mIncompleteTextureBufferAttachment->bufferData(
631             mutableContext, gl::BufferBinding::Texture, &kBufferInitData, sizeof(kBufferInitData),
632             gl::BufferUsage::StaticDraw));
633     }
634     else if (createType == gl::TextureType::_2DMultisample)
635     {
636         ANGLE_TRY(t->setStorageMultisample(mutableContext, createType, 1,
637                                            incompleteTextureParam.sizedInternalFormat, colorSize,
638                                            true));
639     }
640     else
641     {
642         ANGLE_TRY(t->setStorage(mutableContext, createType, 1,
643                                 incompleteTextureParam.sizedInternalFormat, colorSize));
644     }
645 
646     if (type == gl::TextureType::CubeMap)
647     {
648         for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
649         {
650             ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr, face, 0, area,
651                                      incompleteTextureParam.format, incompleteTextureParam.type,
652                                      incompleteTextureParam.clearColor));
653         }
654     }
655     else if (type == gl::TextureType::_2DMultisample)
656     {
657         // Call a specialized clear function to init a multisample texture.
658         ANGLE_TRY(multisampleInitializer->initializeMultisampleTextureToBlack(context, t.get()));
659     }
660     else if (type == gl::TextureType::Buffer)
661     {
662         ANGLE_TRY(t->setBuffer(context, mIncompleteTextureBufferAttachment,
663                                incompleteTextureParam.sizedInternalFormat));
664     }
665     else
666     {
667         ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
668                                  gl::NonCubeTextureTypeToTarget(createType), 0, area,
669                                  incompleteTextureParam.format, incompleteTextureParam.type,
670                                  incompleteTextureParam.clearColor));
671     }
672 
673     if (format == gl::SamplerFormat::Shadow)
674     {
675         // To avoid the undefined spec behavior for shadow samplers with a depth texture, we set the
676         // compare mode to GL_COMPARE_REF_TO_TEXTURE
677         ASSERT(!t->hasObservers());
678         t->setCompareMode(context, GL_COMPARE_REF_TO_TEXTURE);
679     }
680 
681     ANGLE_TRY(t->syncState(context, gl::Command::Other));
682 
683     mIncompleteTextures[format][type].set(context, t.release());
684     *textureOut = mIncompleteTextures[format][type].get();
685     return angle::Result::Continue;
686 }
687 
688 #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
689     template void SetFloatUniformMatrix##api<cols, rows>::Run(     \
690         unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *)
691 
692 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
693 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
694 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
695 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
696 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
697 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3);
698 
699 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2);
700 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3);
701 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3);
702 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2);
703 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4);
704 ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4);
705 
706 #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
707 
708 #define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
709     template void SetFloatUniformMatrix##api<cols, 4>::Run(unsigned int, unsigned int, GLsizei, \
710                                                            GLboolean, const GLfloat *, uint8_t *)
711 
712 template <int cols>
713 struct SetFloatUniformMatrixGLSL<cols, 4>
714 {
715     static void Run(unsigned int arrayElementOffset,
716                     unsigned int elementCount,
717                     GLsizei countIn,
718                     GLboolean transpose,
719                     const GLfloat *value,
720                     uint8_t *targetData);
721 };
722 
723 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
724 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
725 ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
726 
727 #undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC
728 
729 #define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
730     template void SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \
731                                                            GLboolean, const GLfloat *, uint8_t *)
732 
733 template <int rows>
734 struct SetFloatUniformMatrixHLSL<4, rows>
735 {
736     static void Run(unsigned int arrayElementOffset,
737                     unsigned int elementCount,
738                     GLsizei countIn,
739                     GLboolean transpose,
740                     const GLfloat *value,
741                     uint8_t *targetData);
742 };
743 
744 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
745 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
746 ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
747 
748 #undef ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC
749 
750 template <int cols>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)751 void SetFloatUniformMatrixGLSL<cols, 4>::Run(unsigned int arrayElementOffset,
752                                              unsigned int elementCount,
753                                              GLsizei countIn,
754                                              GLboolean transpose,
755                                              const GLfloat *value,
756                                              uint8_t *targetData)
757 {
758     const bool isSrcColumnMajor = !transpose;
759     if (isSrcColumnMajor)
760     {
761         // Both src and dst matrixs are has same layout,
762         // a single memcpy updates all the matrices
763         constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4;
764         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
765                                   targetData);
766     }
767     else
768     {
769         // fallback to general cases
770         SetFloatUniformMatrix<false, cols, 4, true, cols, 4>(arrayElementOffset, elementCount,
771                                                              countIn, value, targetData);
772     }
773 }
774 
775 template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)776 void SetFloatUniformMatrixGLSL<cols, rows>::Run(unsigned int arrayElementOffset,
777                                                 unsigned int elementCount,
778                                                 GLsizei countIn,
779                                                 GLboolean transpose,
780                                                 const GLfloat *value,
781                                                 uint8_t *targetData)
782 {
783     const bool isSrcColumnMajor = !transpose;
784     // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
785     if (isSrcColumnMajor)
786     {
787         SetFloatUniformMatrix<true, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
788                                                                countIn, value, targetData);
789     }
790     else
791     {
792         SetFloatUniformMatrix<false, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
793                                                                 countIn, value, targetData);
794     }
795 }
796 
797 template <int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)798 void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset,
799                                              unsigned int elementCount,
800                                              GLsizei countIn,
801                                              GLboolean transpose,
802                                              const GLfloat *value,
803                                              uint8_t *targetData)
804 {
805     const bool isSrcColumnMajor = !transpose;
806     if (!isSrcColumnMajor)
807     {
808         // Both src and dst matrixs are has same layout,
809         // a single memcpy updates all the matrices
810         constexpr size_t srcMatrixSize = sizeof(GLfloat) * 4 * rows;
811         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
812                                   targetData);
813     }
814     else
815     {
816         // fallback to general cases
817         SetFloatUniformMatrix<true, 4, rows, false, 4, rows>(arrayElementOffset, elementCount,
818                                                              countIn, value, targetData);
819     }
820 }
821 
822 template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)823 void SetFloatUniformMatrixHLSL<cols, rows>::Run(unsigned int arrayElementOffset,
824                                                 unsigned int elementCount,
825                                                 GLsizei countIn,
826                                                 GLboolean transpose,
827                                                 const GLfloat *value,
828                                                 uint8_t *targetData)
829 {
830     const bool isSrcColumnMajor = !transpose;
831     // Internally store matrices as row-major to accomodate HLSL matrix indexing.  Each row is
832     // padded to 4 columns.
833     if (!isSrcColumnMajor)
834     {
835         SetFloatUniformMatrix<false, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
836                                                                  countIn, value, targetData);
837     }
838     else
839     {
840         SetFloatUniformMatrix<true, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
841                                                                 countIn, value, targetData);
842     }
843 }
844 
845 template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
846 template void GetMatrixUniform<GLuint>(GLenum, GLuint *, const GLuint *, bool);
847 
GetMatrixUniform(GLenum type,GLfloat * dataOut,const GLfloat * source,bool transpose)848 void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose)
849 {
850     int columns = gl::VariableColumnCount(type);
851     int rows    = gl::VariableRowCount(type);
852     for (GLint col = 0; col < columns; ++col)
853     {
854         for (GLint row = 0; row < rows; ++row)
855         {
856             GLfloat *outptr = dataOut + ((col * rows) + row);
857             const GLfloat *inptr =
858                 transpose ? source + ((row * 4) + col) : source + ((col * 4) + row);
859             *outptr = *inptr;
860         }
861     }
862 }
863 
864 template <typename NonFloatT>
GetMatrixUniform(GLenum type,NonFloatT * dataOut,const NonFloatT * source,bool transpose)865 void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose)
866 {
867     UNREACHABLE();
868 }
869 
GetFormatFromFormatType(GLenum format,GLenum type)870 const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type)
871 {
872     GLenum sizedInternalFormat    = gl::GetInternalFormatInfo(format, type).sizedInternalFormat;
873     angle::FormatID angleFormatID = angle::Format::InternalFormatToID(sizedInternalFormat);
874     return angle::Format::Get(angleFormatID);
875 }
876 
ComputeStartVertex(ContextImpl * contextImpl,const gl::IndexRange & indexRange,GLint baseVertex,GLint * firstVertexOut)877 angle::Result ComputeStartVertex(ContextImpl *contextImpl,
878                                  const gl::IndexRange &indexRange,
879                                  GLint baseVertex,
880                                  GLint *firstVertexOut)
881 {
882     // The entire index range should be within the limits of a 32-bit uint because the largest
883     // GL index type is GL_UNSIGNED_INT.
884     ASSERT(indexRange.start <= std::numeric_limits<uint32_t>::max() &&
885            indexRange.end <= std::numeric_limits<uint32_t>::max());
886 
887     // The base vertex is only used in DrawElementsIndirect. Given the assertion above and the
888     // type of mBaseVertex (GLint), adding them both as 64-bit ints is safe.
889     int64_t startVertexInt64 =
890         static_cast<int64_t>(baseVertex) + static_cast<int64_t>(indexRange.start);
891 
892     // OpenGL ES 3.2 spec section 10.5: "Behavior of DrawElementsOneInstance is undefined if the
893     // vertex ID is negative for any element"
894     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 >= 0);
895 
896     // OpenGL ES 3.2 spec section 10.5: "If the vertex ID is larger than the maximum value
897     // representable by type, it should behave as if the calculation were upconverted to 32-bit
898     // unsigned integers(with wrapping on overflow conditions)." ANGLE does not fully handle
899     // these rules, an overflow error is returned if the start vertex cannot be stored in a
900     // 32-bit signed integer.
901     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max());
902 
903     *firstVertexOut = static_cast<GLint>(startVertexInt64);
904     return angle::Result::Continue;
905 }
906 
GetVertexRangeInfo(const gl::Context * context,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLint baseVertex,GLint * startVertexOut,size_t * vertexCountOut)907 angle::Result GetVertexRangeInfo(const gl::Context *context,
908                                  GLint firstVertex,
909                                  GLsizei vertexOrIndexCount,
910                                  gl::DrawElementsType indexTypeOrInvalid,
911                                  const void *indices,
912                                  GLint baseVertex,
913                                  GLint *startVertexOut,
914                                  size_t *vertexCountOut)
915 {
916     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
917     {
918         gl::IndexRange indexRange;
919         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
920             context, indexTypeOrInvalid, vertexOrIndexCount, indices, &indexRange));
921         ANGLE_TRY(ComputeStartVertex(context->getImplementation(), indexRange, baseVertex,
922                                      startVertexOut));
923         *vertexCountOut = indexRange.vertexCount();
924     }
925     else
926     {
927         *startVertexOut = firstVertex;
928         *vertexCountOut = vertexOrIndexCount;
929     }
930     return angle::Result::Continue;
931 }
932 
ClipRectToScissor(const gl::State & glState,const gl::Rectangle & rect,bool invertY)933 gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY)
934 {
935     // If the scissor test isn't enabled, assume it has infinite size.  Its intersection with the
936     // rect would be the rect itself.
937     //
938     // Note that on Vulkan, returning this (as opposed to a fixed max-int-sized rect) could lead to
939     // unnecessary pipeline creations if two otherwise identical pipelines are used on framebuffers
940     // with different sizes.  If such usage is observed in an application, we should investigate
941     // possible optimizations.
942     if (!glState.isScissorTestEnabled())
943     {
944         return rect;
945     }
946 
947     gl::Rectangle clippedRect;
948     if (!gl::ClipRectangle(glState.getScissor(), rect, &clippedRect))
949     {
950         return gl::Rectangle();
951     }
952 
953     if (invertY)
954     {
955         clippedRect.y = rect.height - clippedRect.y - clippedRect.height;
956     }
957 
958     return clippedRect;
959 }
960 
LogFeatureStatus(const angle::FeatureSetBase & features,const std::vector<std::string> & featureNames,bool enabled)961 void LogFeatureStatus(const angle::FeatureSetBase &features,
962                       const std::vector<std::string> &featureNames,
963                       bool enabled)
964 {
965     for (const std::string &name : featureNames)
966     {
967         if (features.getFeatures().find(name) != features.getFeatures().end())
968         {
969             INFO() << "Feature: " << name << (enabled ? " enabled" : " disabled");
970         }
971     }
972 }
973 
ApplyFeatureOverrides(angle::FeatureSetBase * features,const egl::DisplayState & state)974 void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state)
975 {
976     features->overrideFeatures(state.featureOverridesEnabled, true);
977     features->overrideFeatures(state.featureOverridesDisabled, false);
978 
979     // Override with environment as well.
980     constexpr char kAngleFeatureOverridesEnabledEnvName[]  = "ANGLE_FEATURE_OVERRIDES_ENABLED";
981     constexpr char kAngleFeatureOverridesDisabledEnvName[] = "ANGLE_FEATURE_OVERRIDES_DISABLED";
982     constexpr char kAngleFeatureOverridesEnabledPropertyName[] =
983         "debug.angle.feature_overrides_enabled";
984     constexpr char kAngleFeatureOverridesDisabledPropertyName[] =
985         "debug.angle.feature_overrides_disabled";
986     std::vector<std::string> overridesEnabled =
987         angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
988             kAngleFeatureOverridesEnabledEnvName, kAngleFeatureOverridesEnabledPropertyName, ":");
989     std::vector<std::string> overridesDisabled =
990         angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
991             kAngleFeatureOverridesDisabledEnvName, kAngleFeatureOverridesDisabledPropertyName, ":");
992     features->overrideFeatures(overridesEnabled, true);
993     LogFeatureStatus(*features, overridesEnabled, true);
994 
995     features->overrideFeatures(overridesDisabled, false);
996     LogFeatureStatus(*features, overridesDisabled, false);
997 }
998 
GetSamplePosition(GLsizei sampleCount,size_t index,GLfloat * xy)999 void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
1000 {
1001     ASSERT(gl::isPow2(sampleCount));
1002     if (sampleCount > 16)
1003     {
1004         // Vulkan (and D3D11) doesn't have standard sample positions for 32 and 64 samples (and no
1005         // drivers are known to support that many samples)
1006         xy[0] = 0.5f;
1007         xy[1] = 0.5f;
1008     }
1009     else
1010     {
1011         size_t indexKey = static_cast<size_t>(gl::log2(sampleCount));
1012         ASSERT(indexKey < kSamplePositions.size() &&
1013                (2 * index + 1) < kSamplePositions[indexKey].size());
1014 
1015         xy[0] = kSamplePositions[indexKey][2 * index];
1016         xy[1] = kSamplePositions[indexKey][2 * index + 1];
1017     }
1018 }
1019 
1020 // These macros are to avoid code too much duplication for variations of multi draw types
1021 #define DRAW_ARRAYS__ contextImpl->drawArrays(context, mode, firsts[drawID], counts[drawID])
1022 #define DRAW_ARRAYS_INSTANCED_                                                      \
1023     contextImpl->drawArraysInstanced(context, mode, firsts[drawID], counts[drawID], \
1024                                      instanceCounts[drawID])
1025 #define DRAW_ELEMENTS__ \
1026     contextImpl->drawElements(context, mode, counts[drawID], type, indices[drawID])
1027 #define DRAW_ELEMENTS_INSTANCED_                                                             \
1028     contextImpl->drawElementsInstanced(context, mode, counts[drawID], type, indices[drawID], \
1029                                        instanceCounts[drawID])
1030 #define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE                                                     \
1031     contextImpl->drawArraysInstancedBaseInstance(context, mode, firsts[drawID], counts[drawID], \
1032                                                  instanceCounts[drawID], baseInstances[drawID])
1033 #define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE                             \
1034     contextImpl->drawElementsInstancedBaseVertexBaseInstance(                         \
1035         context, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID], \
1036         baseVertices[drawID], baseInstances[drawID])
1037 #define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
1038 
1039 #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
1040     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)                                     \
1041     {                                                                                          \
1042         if (ANGLE_NOOP_DRAW(instanced))                                                        \
1043         {                                                                                      \
1044             ANGLE_TRY(contextImpl->handleNoopDrawEvent());                                     \
1045             continue;                                                                          \
1046         }                                                                                      \
1047         ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID);                                          \
1048         ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]);                    \
1049         ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]);               \
1050         ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi));                                       \
1051         ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced);                                        \
1052         gl::MarkShaderStorageUsage(context);                                                   \
1053     }
1054 
MultiDrawArraysGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)1055 angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
1056                                      const gl::Context *context,
1057                                      gl::PrimitiveMode mode,
1058                                      const GLint *firsts,
1059                                      const GLsizei *counts,
1060                                      GLsizei drawcount)
1061 {
1062     gl::Program *programObject = context->getState().getLinkedProgram(context);
1063     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1064     if (hasDrawID)
1065     {
1066         MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0)
1067     }
1068     else
1069     {
1070         MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0)
1071     }
1072 
1073     return angle::Result::Continue;
1074 }
1075 
MultiDrawArraysInstancedGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)1076 angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
1077                                               const gl::Context *context,
1078                                               gl::PrimitiveMode mode,
1079                                               const GLint *firsts,
1080                                               const GLsizei *counts,
1081                                               const GLsizei *instanceCounts,
1082                                               GLsizei drawcount)
1083 {
1084     gl::Program *programObject = context->getState().getLinkedProgram(context);
1085     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1086     if (hasDrawID)
1087     {
1088         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0)
1089     }
1090     else
1091     {
1092         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0)
1093     }
1094 
1095     return angle::Result::Continue;
1096 }
1097 
MultiDrawElementsGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)1098 angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
1099                                        const gl::Context *context,
1100                                        gl::PrimitiveMode mode,
1101                                        const GLsizei *counts,
1102                                        gl::DrawElementsType type,
1103                                        const GLvoid *const *indices,
1104                                        GLsizei drawcount)
1105 {
1106     gl::Program *programObject = context->getState().getLinkedProgram(context);
1107     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1108     if (hasDrawID)
1109     {
1110         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0)
1111     }
1112     else
1113     {
1114         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0)
1115     }
1116 
1117     return angle::Result::Continue;
1118 }
1119 
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)1120 angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
1121                                                 const gl::Context *context,
1122                                                 gl::PrimitiveMode mode,
1123                                                 const GLsizei *counts,
1124                                                 gl::DrawElementsType type,
1125                                                 const GLvoid *const *indices,
1126                                                 const GLsizei *instanceCounts,
1127                                                 GLsizei drawcount)
1128 {
1129     gl::Program *programObject = context->getState().getLinkedProgram(context);
1130     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1131     if (hasDrawID)
1132     {
1133         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0)
1134     }
1135     else
1136     {
1137         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0)
1138     }
1139 
1140     return angle::Result::Continue;
1141 }
1142 
MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)1143 angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
1144                                                           const gl::Context *context,
1145                                                           gl::PrimitiveMode mode,
1146                                                           const GLint *firsts,
1147                                                           const GLsizei *counts,
1148                                                           const GLsizei *instanceCounts,
1149                                                           const GLuint *baseInstances,
1150                                                           GLsizei drawcount)
1151 {
1152     gl::Program *programObject = context->getState().getLinkedProgram(context);
1153     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1154     const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
1155     ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance);
1156 
1157     if (hasDrawID && hasBaseInstance)
1158     {
1159         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1)
1160     }
1161     else if (hasDrawID)
1162     {
1163         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0)
1164     }
1165     else if (hasBaseInstance)
1166     {
1167         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1)
1168     }
1169     else
1170     {
1171         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0)
1172     }
1173 
1174     return angle::Result::Continue;
1175 }
1176 
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)1177 angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
1178                                                                       const gl::Context *context,
1179                                                                       gl::PrimitiveMode mode,
1180                                                                       const GLsizei *counts,
1181                                                                       gl::DrawElementsType type,
1182                                                                       const GLvoid *const *indices,
1183                                                                       const GLsizei *instanceCounts,
1184                                                                       const GLint *baseVertices,
1185                                                                       const GLuint *baseInstances,
1186                                                                       GLsizei drawcount)
1187 {
1188     gl::Program *programObject = context->getState().getLinkedProgram(context);
1189     const bool hasDrawID       = programObject && programObject->hasDrawIDUniform();
1190     const bool hasBaseVertex   = programObject && programObject->hasBaseVertexUniform();
1191     const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
1192     ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance);
1193 
1194     if (hasDrawID)
1195     {
1196         if (hasBaseVertex)
1197         {
1198             if (hasBaseInstance)
1199             {
1200                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1)
1201             }
1202             else
1203             {
1204                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0)
1205             }
1206         }
1207         else
1208         {
1209             if (hasBaseInstance)
1210             {
1211                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1)
1212             }
1213             else
1214             {
1215                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0)
1216             }
1217         }
1218     }
1219     else
1220     {
1221         if (hasBaseVertex)
1222         {
1223             if (hasBaseInstance)
1224             {
1225                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1)
1226             }
1227             else
1228             {
1229                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0)
1230             }
1231         }
1232         else
1233         {
1234             if (hasBaseInstance)
1235             {
1236                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1)
1237             }
1238             else
1239             {
1240                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0)
1241             }
1242         }
1243     }
1244 
1245     return angle::Result::Continue;
1246 }
1247 
ResetBaseVertexBaseInstance(gl::Program * programObject,bool resetBaseVertex,bool resetBaseInstance)1248 ResetBaseVertexBaseInstance::ResetBaseVertexBaseInstance(gl::Program *programObject,
1249                                                          bool resetBaseVertex,
1250                                                          bool resetBaseInstance)
1251     : mProgramObject(programObject),
1252       mResetBaseVertex(resetBaseVertex),
1253       mResetBaseInstance(resetBaseInstance)
1254 {}
1255 
~ResetBaseVertexBaseInstance()1256 ResetBaseVertexBaseInstance::~ResetBaseVertexBaseInstance()
1257 {
1258     if (mProgramObject)
1259     {
1260         // Reset emulated uniforms to zero to avoid affecting other draw calls
1261         if (mResetBaseVertex)
1262         {
1263             mProgramObject->setBaseVertexUniform(0);
1264         }
1265 
1266         if (mResetBaseInstance)
1267         {
1268             mProgramObject->setBaseInstanceUniform(0);
1269         }
1270     }
1271 }
1272 
ConvertToSRGB(angle::FormatID formatID)1273 angle::FormatID ConvertToSRGB(angle::FormatID formatID)
1274 {
1275     switch (formatID)
1276     {
1277         case angle::FormatID::R8_UNORM:
1278             return angle::FormatID::R8_UNORM_SRGB;
1279         case angle::FormatID::R8G8_UNORM:
1280             return angle::FormatID::R8G8_UNORM_SRGB;
1281         case angle::FormatID::R8G8B8_UNORM:
1282             return angle::FormatID::R8G8B8_UNORM_SRGB;
1283         case angle::FormatID::R8G8B8A8_UNORM:
1284             return angle::FormatID::R8G8B8A8_UNORM_SRGB;
1285         case angle::FormatID::B8G8R8A8_UNORM:
1286             return angle::FormatID::B8G8R8A8_UNORM_SRGB;
1287         case angle::FormatID::BC1_RGB_UNORM_BLOCK:
1288             return angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
1289         case angle::FormatID::BC1_RGBA_UNORM_BLOCK:
1290             return angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
1291         case angle::FormatID::BC2_RGBA_UNORM_BLOCK:
1292             return angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
1293         case angle::FormatID::BC3_RGBA_UNORM_BLOCK:
1294             return angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
1295         case angle::FormatID::BC7_RGBA_UNORM_BLOCK:
1296             return angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK;
1297         case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
1298             return angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK;
1299         case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
1300             return angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK;
1301         case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
1302             return angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK;
1303         case angle::FormatID::ASTC_4x4_UNORM_BLOCK:
1304             return angle::FormatID::ASTC_4x4_SRGB_BLOCK;
1305         case angle::FormatID::ASTC_5x4_UNORM_BLOCK:
1306             return angle::FormatID::ASTC_5x4_SRGB_BLOCK;
1307         case angle::FormatID::ASTC_5x5_UNORM_BLOCK:
1308             return angle::FormatID::ASTC_5x5_SRGB_BLOCK;
1309         case angle::FormatID::ASTC_6x5_UNORM_BLOCK:
1310             return angle::FormatID::ASTC_6x5_SRGB_BLOCK;
1311         case angle::FormatID::ASTC_6x6_UNORM_BLOCK:
1312             return angle::FormatID::ASTC_6x6_SRGB_BLOCK;
1313         case angle::FormatID::ASTC_8x5_UNORM_BLOCK:
1314             return angle::FormatID::ASTC_8x5_SRGB_BLOCK;
1315         case angle::FormatID::ASTC_8x6_UNORM_BLOCK:
1316             return angle::FormatID::ASTC_8x6_SRGB_BLOCK;
1317         case angle::FormatID::ASTC_8x8_UNORM_BLOCK:
1318             return angle::FormatID::ASTC_8x8_SRGB_BLOCK;
1319         case angle::FormatID::ASTC_10x5_UNORM_BLOCK:
1320             return angle::FormatID::ASTC_10x5_SRGB_BLOCK;
1321         case angle::FormatID::ASTC_10x6_UNORM_BLOCK:
1322             return angle::FormatID::ASTC_10x6_SRGB_BLOCK;
1323         case angle::FormatID::ASTC_10x8_UNORM_BLOCK:
1324             return angle::FormatID::ASTC_10x8_SRGB_BLOCK;
1325         case angle::FormatID::ASTC_10x10_UNORM_BLOCK:
1326             return angle::FormatID::ASTC_10x10_SRGB_BLOCK;
1327         case angle::FormatID::ASTC_12x10_UNORM_BLOCK:
1328             return angle::FormatID::ASTC_12x10_SRGB_BLOCK;
1329         case angle::FormatID::ASTC_12x12_UNORM_BLOCK:
1330             return angle::FormatID::ASTC_12x12_SRGB_BLOCK;
1331         default:
1332             return angle::FormatID::NONE;
1333     }
1334 }
1335 
ConvertToLinear(angle::FormatID formatID)1336 angle::FormatID ConvertToLinear(angle::FormatID formatID)
1337 {
1338     switch (formatID)
1339     {
1340         case angle::FormatID::R8_UNORM_SRGB:
1341             return angle::FormatID::R8_UNORM;
1342         case angle::FormatID::R8G8_UNORM_SRGB:
1343             return angle::FormatID::R8G8_UNORM;
1344         case angle::FormatID::R8G8B8_UNORM_SRGB:
1345             return angle::FormatID::R8G8B8_UNORM;
1346         case angle::FormatID::R8G8B8A8_UNORM_SRGB:
1347             return angle::FormatID::R8G8B8A8_UNORM;
1348         case angle::FormatID::B8G8R8A8_UNORM_SRGB:
1349             return angle::FormatID::B8G8R8A8_UNORM;
1350         case angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK:
1351             return angle::FormatID::BC1_RGB_UNORM_BLOCK;
1352         case angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK:
1353             return angle::FormatID::BC1_RGBA_UNORM_BLOCK;
1354         case angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK:
1355             return angle::FormatID::BC2_RGBA_UNORM_BLOCK;
1356         case angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK:
1357             return angle::FormatID::BC3_RGBA_UNORM_BLOCK;
1358         case angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK:
1359             return angle::FormatID::BC7_RGBA_UNORM_BLOCK;
1360         case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
1361             return angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK;
1362         case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
1363             return angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK;
1364         case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
1365             return angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK;
1366         case angle::FormatID::ASTC_4x4_SRGB_BLOCK:
1367             return angle::FormatID::ASTC_4x4_UNORM_BLOCK;
1368         case angle::FormatID::ASTC_5x4_SRGB_BLOCK:
1369             return angle::FormatID::ASTC_5x4_UNORM_BLOCK;
1370         case angle::FormatID::ASTC_5x5_SRGB_BLOCK:
1371             return angle::FormatID::ASTC_5x5_UNORM_BLOCK;
1372         case angle::FormatID::ASTC_6x5_SRGB_BLOCK:
1373             return angle::FormatID::ASTC_6x5_UNORM_BLOCK;
1374         case angle::FormatID::ASTC_6x6_SRGB_BLOCK:
1375             return angle::FormatID::ASTC_6x6_UNORM_BLOCK;
1376         case angle::FormatID::ASTC_8x5_SRGB_BLOCK:
1377             return angle::FormatID::ASTC_8x5_UNORM_BLOCK;
1378         case angle::FormatID::ASTC_8x6_SRGB_BLOCK:
1379             return angle::FormatID::ASTC_8x6_UNORM_BLOCK;
1380         case angle::FormatID::ASTC_8x8_SRGB_BLOCK:
1381             return angle::FormatID::ASTC_8x8_UNORM_BLOCK;
1382         case angle::FormatID::ASTC_10x5_SRGB_BLOCK:
1383             return angle::FormatID::ASTC_10x5_UNORM_BLOCK;
1384         case angle::FormatID::ASTC_10x6_SRGB_BLOCK:
1385             return angle::FormatID::ASTC_10x6_UNORM_BLOCK;
1386         case angle::FormatID::ASTC_10x8_SRGB_BLOCK:
1387             return angle::FormatID::ASTC_10x8_UNORM_BLOCK;
1388         case angle::FormatID::ASTC_10x10_SRGB_BLOCK:
1389             return angle::FormatID::ASTC_10x10_UNORM_BLOCK;
1390         case angle::FormatID::ASTC_12x10_SRGB_BLOCK:
1391             return angle::FormatID::ASTC_12x10_UNORM_BLOCK;
1392         case angle::FormatID::ASTC_12x12_SRGB_BLOCK:
1393             return angle::FormatID::ASTC_12x12_UNORM_BLOCK;
1394         default:
1395             return angle::FormatID::NONE;
1396     }
1397 }
1398 
IsOverridableLinearFormat(angle::FormatID formatID)1399 bool IsOverridableLinearFormat(angle::FormatID formatID)
1400 {
1401     return ConvertToSRGB(formatID) != angle::FormatID::NONE;
1402 }
1403 }  // namespace rx
1404