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