xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/renderer_utils.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // renderer_utils:
7*8975f5c5SAndroid Build Coastguard Worker //   Helper methods pertaining to most or all back-ends.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/renderer_utils.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/base/anglebase/numerics/checked_math.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "image_util/copyimage.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "image_util/imageformats.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/AttributeMap.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.inl.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ContextImpl.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/Format.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "platform/Feature.h"
26*8975f5c5SAndroid Build Coastguard Worker 
27*8975f5c5SAndroid Build Coastguard Worker #include <string.h>
28*8975f5c5SAndroid Build Coastguard Worker #include <cctype>
29*8975f5c5SAndroid Build Coastguard Worker 
30*8975f5c5SAndroid Build Coastguard Worker namespace angle
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker namespace
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker // For the sake of feature name matching, underscore is ignored, and the names are matched
35*8975f5c5SAndroid Build Coastguard Worker // case-insensitive.  This allows feature names to be overriden both in snake_case (previously used
36*8975f5c5SAndroid Build Coastguard Worker // by ANGLE) and camelCase.  The second string (user-provided name) can end in `*` for wildcard
37*8975f5c5SAndroid Build Coastguard Worker // matching.
FeatureNameMatch(const std::string & a,const std::string & b)38*8975f5c5SAndroid Build Coastguard Worker bool FeatureNameMatch(const std::string &a, const std::string &b)
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker     size_t ai = 0;
41*8975f5c5SAndroid Build Coastguard Worker     size_t bi = 0;
42*8975f5c5SAndroid Build Coastguard Worker 
43*8975f5c5SAndroid Build Coastguard Worker     while (ai < a.size() && bi < b.size())
44*8975f5c5SAndroid Build Coastguard Worker     {
45*8975f5c5SAndroid Build Coastguard Worker         if (a[ai] == '_')
46*8975f5c5SAndroid Build Coastguard Worker         {
47*8975f5c5SAndroid Build Coastguard Worker             ++ai;
48*8975f5c5SAndroid Build Coastguard Worker         }
49*8975f5c5SAndroid Build Coastguard Worker         if (b[bi] == '_')
50*8975f5c5SAndroid Build Coastguard Worker         {
51*8975f5c5SAndroid Build Coastguard Worker             ++bi;
52*8975f5c5SAndroid Build Coastguard Worker         }
53*8975f5c5SAndroid Build Coastguard Worker         if (b[bi] == '*' && bi + 1 == b.size())
54*8975f5c5SAndroid Build Coastguard Worker         {
55*8975f5c5SAndroid Build Coastguard Worker             // If selected feature name ends in wildcard, match it.
56*8975f5c5SAndroid Build Coastguard Worker             return true;
57*8975f5c5SAndroid Build Coastguard Worker         }
58*8975f5c5SAndroid Build Coastguard Worker         if (std::tolower(a[ai++]) != std::tolower(b[bi++]))
59*8975f5c5SAndroid Build Coastguard Worker         {
60*8975f5c5SAndroid Build Coastguard Worker             return false;
61*8975f5c5SAndroid Build Coastguard Worker         }
62*8975f5c5SAndroid Build Coastguard Worker     }
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker     return ai == a.size() && bi == b.size();
65*8975f5c5SAndroid Build Coastguard Worker }
66*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
67*8975f5c5SAndroid Build Coastguard Worker 
applyOverride(bool state)68*8975f5c5SAndroid Build Coastguard Worker void FeatureInfo::applyOverride(bool state)
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker     enabled     = state;
71*8975f5c5SAndroid Build Coastguard Worker     hasOverride = true;
72*8975f5c5SAndroid Build Coastguard Worker }
73*8975f5c5SAndroid Build Coastguard Worker 
74*8975f5c5SAndroid Build Coastguard Worker // FeatureSetBase implementation
reset()75*8975f5c5SAndroid Build Coastguard Worker void FeatureSetBase::reset()
76*8975f5c5SAndroid Build Coastguard Worker {
77*8975f5c5SAndroid Build Coastguard Worker     for (auto iter : members)
78*8975f5c5SAndroid Build Coastguard Worker     {
79*8975f5c5SAndroid Build Coastguard Worker         FeatureInfo *feature = iter.second;
80*8975f5c5SAndroid Build Coastguard Worker         feature->enabled     = false;
81*8975f5c5SAndroid Build Coastguard Worker         feature->hasOverride = false;
82*8975f5c5SAndroid Build Coastguard Worker     }
83*8975f5c5SAndroid Build Coastguard Worker }
84*8975f5c5SAndroid Build Coastguard Worker 
overrideFeatures(const std::vector<std::string> & featureNames,bool enabled)85*8975f5c5SAndroid Build Coastguard Worker void FeatureSetBase::overrideFeatures(const std::vector<std::string> &featureNames, bool enabled)
86*8975f5c5SAndroid Build Coastguard Worker {
87*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &name : featureNames)
88*8975f5c5SAndroid Build Coastguard Worker     {
89*8975f5c5SAndroid Build Coastguard Worker         const bool hasWildcard = name.back() == '*';
90*8975f5c5SAndroid Build Coastguard Worker         for (auto iter : members)
91*8975f5c5SAndroid Build Coastguard Worker         {
92*8975f5c5SAndroid Build Coastguard Worker             const std::string &featureName = iter.first;
93*8975f5c5SAndroid Build Coastguard Worker             FeatureInfo *feature           = iter.second;
94*8975f5c5SAndroid Build Coastguard Worker 
95*8975f5c5SAndroid Build Coastguard Worker             if (!FeatureNameMatch(featureName, name))
96*8975f5c5SAndroid Build Coastguard Worker             {
97*8975f5c5SAndroid Build Coastguard Worker                 continue;
98*8975f5c5SAndroid Build Coastguard Worker             }
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker             feature->applyOverride(enabled);
101*8975f5c5SAndroid Build Coastguard Worker 
102*8975f5c5SAndroid Build Coastguard Worker             // If name has a wildcard, try to match it with all features.  Otherwise, bail on first
103*8975f5c5SAndroid Build Coastguard Worker             // match, as names are unique.
104*8975f5c5SAndroid Build Coastguard Worker             if (!hasWildcard)
105*8975f5c5SAndroid Build Coastguard Worker             {
106*8975f5c5SAndroid Build Coastguard Worker                 break;
107*8975f5c5SAndroid Build Coastguard Worker             }
108*8975f5c5SAndroid Build Coastguard Worker         }
109*8975f5c5SAndroid Build Coastguard Worker     }
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker 
populateFeatureList(FeatureList * features) const112*8975f5c5SAndroid Build Coastguard Worker void FeatureSetBase::populateFeatureList(FeatureList *features) const
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker     for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++)
115*8975f5c5SAndroid Build Coastguard Worker     {
116*8975f5c5SAndroid Build Coastguard Worker         features->push_back(it->second);
117*8975f5c5SAndroid Build Coastguard Worker     }
118*8975f5c5SAndroid Build Coastguard Worker }
119*8975f5c5SAndroid Build Coastguard Worker }  // namespace angle
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker namespace rx
122*8975f5c5SAndroid Build Coastguard Worker {
123*8975f5c5SAndroid Build Coastguard Worker 
124*8975f5c5SAndroid Build Coastguard Worker namespace
125*8975f5c5SAndroid Build Coastguard Worker {
126*8975f5c5SAndroid Build Coastguard Worker // Both D3D and Vulkan support the same set of standard sample positions for 1, 2, 4, 8, and 16
127*8975f5c5SAndroid Build Coastguard Worker // samples.  See:
128*8975f5c5SAndroid Build Coastguard Worker //
129*8975f5c5SAndroid Build Coastguard Worker // - https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx
130*8975f5c5SAndroid Build Coastguard Worker //
131*8975f5c5SAndroid Build Coastguard Worker // -
132*8975f5c5SAndroid Build Coastguard Worker // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#primsrast-multisampling
133*8975f5c5SAndroid Build Coastguard Worker using SamplePositionsArray                                     = std::array<float, 32>;
134*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
135*8975f5c5SAndroid Build Coastguard Worker     {{{0.5f, 0.5f}},
136*8975f5c5SAndroid Build Coastguard Worker      {{0.75f, 0.75f, 0.25f, 0.25f}},
137*8975f5c5SAndroid Build Coastguard Worker      {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
138*8975f5c5SAndroid Build Coastguard Worker      {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
139*8975f5c5SAndroid Build Coastguard Worker        0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
140*8975f5c5SAndroid Build Coastguard Worker      {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f,  0.75f,   0.4375f,
141*8975f5c5SAndroid Build Coastguard Worker        0.1875f, 0.375f,  0.625f,  0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
142*8975f5c5SAndroid Build Coastguard Worker        0.375f,  0.875f,  0.5f,    0.0625f, 0.25f,   0.125f,  0.125f,  0.75f,
143*8975f5c5SAndroid Build Coastguard Worker        0.0f,    0.5f,    0.9375f, 0.25f,   0.875f,  0.9375f, 0.0625f, 0.0f}}}};
144*8975f5c5SAndroid Build Coastguard Worker 
145*8975f5c5SAndroid Build Coastguard Worker struct IncompleteTextureParameters
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker     GLenum sizedInternalFormat;
148*8975f5c5SAndroid Build Coastguard Worker     GLenum format;
149*8975f5c5SAndroid Build Coastguard Worker     GLenum type;
150*8975f5c5SAndroid Build Coastguard Worker     GLubyte clearColor[4];
151*8975f5c5SAndroid Build Coastguard Worker };
152*8975f5c5SAndroid Build Coastguard Worker 
153*8975f5c5SAndroid Build Coastguard Worker // Note that for gl::SamplerFormat::Shadow, the clearColor datatype needs to be GLushort and as such
154*8975f5c5SAndroid Build Coastguard Worker // we will reinterpret GLubyte[4] as GLushort[2].
155*8975f5c5SAndroid Build Coastguard Worker constexpr angle::PackedEnumMap<gl::SamplerFormat, IncompleteTextureParameters>
156*8975f5c5SAndroid Build Coastguard Worker     kIncompleteTextureParameters = {
157*8975f5c5SAndroid Build Coastguard Worker         {gl::SamplerFormat::Float, {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, {0, 0, 0, 255}}},
158*8975f5c5SAndroid Build Coastguard Worker         {gl::SamplerFormat::Unsigned,
159*8975f5c5SAndroid Build Coastguard Worker          {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, {0, 0, 0, 255}}},
160*8975f5c5SAndroid Build Coastguard Worker         {gl::SamplerFormat::Signed, {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, {0, 0, 0, 127}}},
161*8975f5c5SAndroid Build Coastguard Worker         {gl::SamplerFormat::Shadow,
162*8975f5c5SAndroid Build Coastguard Worker          {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, {0, 0, 0, 0}}}};
163*8975f5c5SAndroid Build Coastguard Worker 
CopyColor(gl::ColorF * color)164*8975f5c5SAndroid Build Coastguard Worker void CopyColor(gl::ColorF *color)
165*8975f5c5SAndroid Build Coastguard Worker {
166*8975f5c5SAndroid Build Coastguard Worker     // No-op
167*8975f5c5SAndroid Build Coastguard Worker }
168*8975f5c5SAndroid Build Coastguard Worker 
PremultiplyAlpha(gl::ColorF * color)169*8975f5c5SAndroid Build Coastguard Worker void PremultiplyAlpha(gl::ColorF *color)
170*8975f5c5SAndroid Build Coastguard Worker {
171*8975f5c5SAndroid Build Coastguard Worker     color->red *= color->alpha;
172*8975f5c5SAndroid Build Coastguard Worker     color->green *= color->alpha;
173*8975f5c5SAndroid Build Coastguard Worker     color->blue *= color->alpha;
174*8975f5c5SAndroid Build Coastguard Worker }
175*8975f5c5SAndroid Build Coastguard Worker 
UnmultiplyAlpha(gl::ColorF * color)176*8975f5c5SAndroid Build Coastguard Worker void UnmultiplyAlpha(gl::ColorF *color)
177*8975f5c5SAndroid Build Coastguard Worker {
178*8975f5c5SAndroid Build Coastguard Worker     if (color->alpha != 0.0f)
179*8975f5c5SAndroid Build Coastguard Worker     {
180*8975f5c5SAndroid Build Coastguard Worker         float invAlpha = 1.0f / color->alpha;
181*8975f5c5SAndroid Build Coastguard Worker         color->red *= invAlpha;
182*8975f5c5SAndroid Build Coastguard Worker         color->green *= invAlpha;
183*8975f5c5SAndroid Build Coastguard Worker         color->blue *= invAlpha;
184*8975f5c5SAndroid Build Coastguard Worker     }
185*8975f5c5SAndroid Build Coastguard Worker }
186*8975f5c5SAndroid Build Coastguard Worker 
ClipChannelsR(gl::ColorF * color)187*8975f5c5SAndroid Build Coastguard Worker void ClipChannelsR(gl::ColorF *color)
188*8975f5c5SAndroid Build Coastguard Worker {
189*8975f5c5SAndroid Build Coastguard Worker     color->green = 0.0f;
190*8975f5c5SAndroid Build Coastguard Worker     color->blue  = 0.0f;
191*8975f5c5SAndroid Build Coastguard Worker     color->alpha = 1.0f;
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker 
ClipChannelsRG(gl::ColorF * color)194*8975f5c5SAndroid Build Coastguard Worker void ClipChannelsRG(gl::ColorF *color)
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker     color->blue  = 0.0f;
197*8975f5c5SAndroid Build Coastguard Worker     color->alpha = 1.0f;
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker 
ClipChannelsRGB(gl::ColorF * color)200*8975f5c5SAndroid Build Coastguard Worker void ClipChannelsRGB(gl::ColorF *color)
201*8975f5c5SAndroid Build Coastguard Worker {
202*8975f5c5SAndroid Build Coastguard Worker     color->alpha = 1.0f;
203*8975f5c5SAndroid Build Coastguard Worker }
204*8975f5c5SAndroid Build Coastguard Worker 
ClipChannelsLuminance(gl::ColorF * color)205*8975f5c5SAndroid Build Coastguard Worker void ClipChannelsLuminance(gl::ColorF *color)
206*8975f5c5SAndroid Build Coastguard Worker {
207*8975f5c5SAndroid Build Coastguard Worker     color->alpha = 1.0f;
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker 
ClipChannelsAlpha(gl::ColorF * color)210*8975f5c5SAndroid Build Coastguard Worker void ClipChannelsAlpha(gl::ColorF *color)
211*8975f5c5SAndroid Build Coastguard Worker {
212*8975f5c5SAndroid Build Coastguard Worker     color->red   = 0.0f;
213*8975f5c5SAndroid Build Coastguard Worker     color->green = 0.0f;
214*8975f5c5SAndroid Build Coastguard Worker     color->blue  = 0.0f;
215*8975f5c5SAndroid Build Coastguard Worker }
216*8975f5c5SAndroid Build Coastguard Worker 
ClipChannelsNoOp(gl::ColorF * color)217*8975f5c5SAndroid Build Coastguard Worker void ClipChannelsNoOp(gl::ColorF *color) {}
218*8975f5c5SAndroid Build Coastguard Worker 
WriteUintColor(const gl::ColorF & color,PixelWriteFunction colorWriteFunction,uint8_t * destPixelData)219*8975f5c5SAndroid Build Coastguard Worker void WriteUintColor(const gl::ColorF &color,
220*8975f5c5SAndroid Build Coastguard Worker                     PixelWriteFunction colorWriteFunction,
221*8975f5c5SAndroid Build Coastguard Worker                     uint8_t *destPixelData)
222*8975f5c5SAndroid Build Coastguard Worker {
223*8975f5c5SAndroid Build Coastguard Worker     gl::ColorUI destColor(
224*8975f5c5SAndroid Build Coastguard Worker         static_cast<unsigned int>(color.red * 255), static_cast<unsigned int>(color.green * 255),
225*8975f5c5SAndroid Build Coastguard Worker         static_cast<unsigned int>(color.blue * 255), static_cast<unsigned int>(color.alpha * 255));
226*8975f5c5SAndroid Build Coastguard Worker     colorWriteFunction(reinterpret_cast<const uint8_t *>(&destColor), destPixelData);
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker 
WriteFloatColor(const gl::ColorF & color,PixelWriteFunction colorWriteFunction,uint8_t * destPixelData)229*8975f5c5SAndroid Build Coastguard Worker void WriteFloatColor(const gl::ColorF &color,
230*8975f5c5SAndroid Build Coastguard Worker                      PixelWriteFunction colorWriteFunction,
231*8975f5c5SAndroid Build Coastguard Worker                      uint8_t *destPixelData)
232*8975f5c5SAndroid Build Coastguard Worker {
233*8975f5c5SAndroid Build Coastguard Worker     colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
234*8975f5c5SAndroid Build Coastguard Worker }
235*8975f5c5SAndroid Build Coastguard Worker 
236*8975f5c5SAndroid Build Coastguard Worker template <int cols, int rows, bool IsColumnMajor>
GetFlattenedIndex(int col,int row)237*8975f5c5SAndroid Build Coastguard Worker constexpr inline int GetFlattenedIndex(int col, int row)
238*8975f5c5SAndroid Build Coastguard Worker {
239*8975f5c5SAndroid Build Coastguard Worker     if (IsColumnMajor)
240*8975f5c5SAndroid Build Coastguard Worker     {
241*8975f5c5SAndroid Build Coastguard Worker         return col * rows + row;
242*8975f5c5SAndroid Build Coastguard Worker     }
243*8975f5c5SAndroid Build Coastguard Worker     else
244*8975f5c5SAndroid Build Coastguard Worker     {
245*8975f5c5SAndroid Build Coastguard Worker         return row * cols + col;
246*8975f5c5SAndroid Build Coastguard Worker     }
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker 
249*8975f5c5SAndroid Build Coastguard Worker template <typename T,
250*8975f5c5SAndroid Build Coastguard Worker           bool IsSrcColumnMajor,
251*8975f5c5SAndroid Build Coastguard Worker           int colsSrc,
252*8975f5c5SAndroid Build Coastguard Worker           int rowsSrc,
253*8975f5c5SAndroid Build Coastguard Worker           bool IsDstColumnMajor,
254*8975f5c5SAndroid Build Coastguard Worker           int colsDst,
255*8975f5c5SAndroid Build Coastguard Worker           int rowsDst>
ExpandMatrix(T * target,const GLfloat * value)256*8975f5c5SAndroid Build Coastguard Worker void ExpandMatrix(T *target, const GLfloat *value)
257*8975f5c5SAndroid Build Coastguard Worker {
258*8975f5c5SAndroid Build Coastguard Worker     static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!");
259*8975f5c5SAndroid Build Coastguard Worker 
260*8975f5c5SAndroid Build Coastguard Worker     // Clamp the staging data's size to the last written value so that data packed just after this
261*8975f5c5SAndroid Build Coastguard Worker     // matrix is not overwritten.
262*8975f5c5SAndroid Build Coastguard Worker     constexpr int kDstFlatSize =
263*8975f5c5SAndroid Build Coastguard Worker         GetFlattenedIndex<colsDst, rowsDst, IsDstColumnMajor>(colsSrc - 1, rowsSrc - 1) + 1;
264*8975f5c5SAndroid Build Coastguard Worker     T staging[kDstFlatSize]    = {0};
265*8975f5c5SAndroid Build Coastguard Worker 
266*8975f5c5SAndroid Build Coastguard Worker     for (int r = 0; r < rowsSrc; r++)
267*8975f5c5SAndroid Build Coastguard Worker     {
268*8975f5c5SAndroid Build Coastguard Worker         for (int c = 0; c < colsSrc; c++)
269*8975f5c5SAndroid Build Coastguard Worker         {
270*8975f5c5SAndroid Build Coastguard Worker             int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc, IsSrcColumnMajor>(c, r);
271*8975f5c5SAndroid Build Coastguard Worker             int dstIndex = GetFlattenedIndex<colsDst, rowsDst, IsDstColumnMajor>(c, r);
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker             staging[dstIndex] = static_cast<T>(value[srcIndex]);
274*8975f5c5SAndroid Build Coastguard Worker         }
275*8975f5c5SAndroid Build Coastguard Worker     }
276*8975f5c5SAndroid Build Coastguard Worker 
277*8975f5c5SAndroid Build Coastguard Worker     memcpy(target, staging, kDstFlatSize * sizeof(T));
278*8975f5c5SAndroid Build Coastguard Worker }
279*8975f5c5SAndroid Build Coastguard Worker 
280*8975f5c5SAndroid Build Coastguard Worker template <bool IsSrcColumMajor,
281*8975f5c5SAndroid Build Coastguard Worker           int colsSrc,
282*8975f5c5SAndroid Build Coastguard Worker           int rowsSrc,
283*8975f5c5SAndroid Build Coastguard Worker           bool IsDstColumnMajor,
284*8975f5c5SAndroid Build Coastguard Worker           int colsDst,
285*8975f5c5SAndroid Build Coastguard Worker           int rowsDst>
SetFloatUniformMatrix(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,const GLfloat * value,uint8_t * targetData)286*8975f5c5SAndroid Build Coastguard Worker void SetFloatUniformMatrix(unsigned int arrayElementOffset,
287*8975f5c5SAndroid Build Coastguard Worker                            unsigned int elementCount,
288*8975f5c5SAndroid Build Coastguard Worker                            GLsizei countIn,
289*8975f5c5SAndroid Build Coastguard Worker                            const GLfloat *value,
290*8975f5c5SAndroid Build Coastguard Worker                            uint8_t *targetData)
291*8975f5c5SAndroid Build Coastguard Worker {
292*8975f5c5SAndroid Build Coastguard Worker     unsigned int count =
293*8975f5c5SAndroid Build Coastguard Worker         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
294*8975f5c5SAndroid Build Coastguard Worker 
295*8975f5c5SAndroid Build Coastguard Worker     const unsigned int targetMatrixStride = colsDst * rowsDst;
296*8975f5c5SAndroid Build Coastguard Worker     GLfloat *target                       = reinterpret_cast<GLfloat *>(
297*8975f5c5SAndroid Build Coastguard Worker         targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
298*8975f5c5SAndroid Build Coastguard Worker 
299*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < count; i++)
300*8975f5c5SAndroid Build Coastguard Worker     {
301*8975f5c5SAndroid Build Coastguard Worker         ExpandMatrix<GLfloat, IsSrcColumMajor, colsSrc, rowsSrc, IsDstColumnMajor, colsDst,
302*8975f5c5SAndroid Build Coastguard Worker                      rowsDst>(target, value);
303*8975f5c5SAndroid Build Coastguard Worker 
304*8975f5c5SAndroid Build Coastguard Worker         target += targetMatrixStride;
305*8975f5c5SAndroid Build Coastguard Worker         value += colsSrc * rowsSrc;
306*8975f5c5SAndroid Build Coastguard Worker     }
307*8975f5c5SAndroid Build Coastguard Worker }
308*8975f5c5SAndroid Build Coastguard Worker 
SetFloatUniformMatrixFast(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,size_t matrixSize,const GLfloat * value,uint8_t * targetData)309*8975f5c5SAndroid Build Coastguard Worker void SetFloatUniformMatrixFast(unsigned int arrayElementOffset,
310*8975f5c5SAndroid Build Coastguard Worker                                unsigned int elementCount,
311*8975f5c5SAndroid Build Coastguard Worker                                GLsizei countIn,
312*8975f5c5SAndroid Build Coastguard Worker                                size_t matrixSize,
313*8975f5c5SAndroid Build Coastguard Worker                                const GLfloat *value,
314*8975f5c5SAndroid Build Coastguard Worker                                uint8_t *targetData)
315*8975f5c5SAndroid Build Coastguard Worker {
316*8975f5c5SAndroid Build Coastguard Worker     const unsigned int count =
317*8975f5c5SAndroid Build Coastguard Worker         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
318*8975f5c5SAndroid Build Coastguard Worker 
319*8975f5c5SAndroid Build Coastguard Worker     const uint8_t *valueData = reinterpret_cast<const uint8_t *>(value);
320*8975f5c5SAndroid Build Coastguard Worker     targetData               = targetData + arrayElementOffset * matrixSize;
321*8975f5c5SAndroid Build Coastguard Worker 
322*8975f5c5SAndroid Build Coastguard Worker     memcpy(targetData, valueData, matrixSize * count);
323*8975f5c5SAndroid Build Coastguard Worker }
324*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
325*8975f5c5SAndroid Build Coastguard Worker 
IsRotatedAspectRatio(SurfaceRotation rotation)326*8975f5c5SAndroid Build Coastguard Worker bool IsRotatedAspectRatio(SurfaceRotation rotation)
327*8975f5c5SAndroid Build Coastguard Worker {
328*8975f5c5SAndroid Build Coastguard Worker     switch (rotation)
329*8975f5c5SAndroid Build Coastguard Worker     {
330*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated90Degrees:
331*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated270Degrees:
332*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::FlippedRotated90Degrees:
333*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::FlippedRotated270Degrees:
334*8975f5c5SAndroid Build Coastguard Worker             return true;
335*8975f5c5SAndroid Build Coastguard Worker         default:
336*8975f5c5SAndroid Build Coastguard Worker             return false;
337*8975f5c5SAndroid Build Coastguard Worker     }
338*8975f5c5SAndroid Build Coastguard Worker }
339*8975f5c5SAndroid Build Coastguard Worker 
RotateRectangle(const SurfaceRotation rotation,const bool flipY,const int framebufferWidth,const int framebufferHeight,const gl::Rectangle & incoming,gl::Rectangle * outgoing)340*8975f5c5SAndroid Build Coastguard Worker void RotateRectangle(const SurfaceRotation rotation,
341*8975f5c5SAndroid Build Coastguard Worker                      const bool flipY,
342*8975f5c5SAndroid Build Coastguard Worker                      const int framebufferWidth,
343*8975f5c5SAndroid Build Coastguard Worker                      const int framebufferHeight,
344*8975f5c5SAndroid Build Coastguard Worker                      const gl::Rectangle &incoming,
345*8975f5c5SAndroid Build Coastguard Worker                      gl::Rectangle *outgoing)
346*8975f5c5SAndroid Build Coastguard Worker {
347*8975f5c5SAndroid Build Coastguard Worker     // GLES's y-axis points up; Vulkan's points down.
348*8975f5c5SAndroid Build Coastguard Worker     switch (rotation)
349*8975f5c5SAndroid Build Coastguard Worker     {
350*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Identity:
351*8975f5c5SAndroid Build Coastguard Worker             // Do not rotate gl_Position (surface matches the device's orientation):
352*8975f5c5SAndroid Build Coastguard Worker             outgoing->x     = incoming.x;
353*8975f5c5SAndroid Build Coastguard Worker             outgoing->y     = flipY ? framebufferHeight - incoming.y - incoming.height : incoming.y;
354*8975f5c5SAndroid Build Coastguard Worker             outgoing->width = incoming.width;
355*8975f5c5SAndroid Build Coastguard Worker             outgoing->height = incoming.height;
356*8975f5c5SAndroid Build Coastguard Worker             break;
357*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated90Degrees:
358*8975f5c5SAndroid Build Coastguard Worker             // Rotate gl_Position 90 degrees:
359*8975f5c5SAndroid Build Coastguard Worker             outgoing->x      = incoming.y;
360*8975f5c5SAndroid Build Coastguard Worker             outgoing->y      = flipY ? incoming.x : framebufferWidth - incoming.x - incoming.width;
361*8975f5c5SAndroid Build Coastguard Worker             outgoing->width  = incoming.height;
362*8975f5c5SAndroid Build Coastguard Worker             outgoing->height = incoming.width;
363*8975f5c5SAndroid Build Coastguard Worker             break;
364*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated180Degrees:
365*8975f5c5SAndroid Build Coastguard Worker             // Rotate gl_Position 180 degrees:
366*8975f5c5SAndroid Build Coastguard Worker             outgoing->x     = framebufferWidth - incoming.x - incoming.width;
367*8975f5c5SAndroid Build Coastguard Worker             outgoing->y     = flipY ? incoming.y : framebufferHeight - incoming.y - incoming.height;
368*8975f5c5SAndroid Build Coastguard Worker             outgoing->width = incoming.width;
369*8975f5c5SAndroid Build Coastguard Worker             outgoing->height = incoming.height;
370*8975f5c5SAndroid Build Coastguard Worker             break;
371*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated270Degrees:
372*8975f5c5SAndroid Build Coastguard Worker             // Rotate gl_Position 270 degrees:
373*8975f5c5SAndroid Build Coastguard Worker             outgoing->x      = framebufferHeight - incoming.y - incoming.height;
374*8975f5c5SAndroid Build Coastguard Worker             outgoing->y      = flipY ? framebufferWidth - incoming.x - incoming.width : incoming.x;
375*8975f5c5SAndroid Build Coastguard Worker             outgoing->width  = incoming.height;
376*8975f5c5SAndroid Build Coastguard Worker             outgoing->height = incoming.width;
377*8975f5c5SAndroid Build Coastguard Worker             break;
378*8975f5c5SAndroid Build Coastguard Worker         default:
379*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
380*8975f5c5SAndroid Build Coastguard Worker             break;
381*8975f5c5SAndroid Build Coastguard Worker     }
382*8975f5c5SAndroid Build Coastguard Worker }
383*8975f5c5SAndroid Build Coastguard Worker 
PackPixelsParams()384*8975f5c5SAndroid Build Coastguard Worker PackPixelsParams::PackPixelsParams()
385*8975f5c5SAndroid Build Coastguard Worker     : destFormat(nullptr),
386*8975f5c5SAndroid Build Coastguard Worker       outputPitch(0),
387*8975f5c5SAndroid Build Coastguard Worker       packBuffer(nullptr),
388*8975f5c5SAndroid Build Coastguard Worker       offset(0),
389*8975f5c5SAndroid Build Coastguard Worker       rotation(SurfaceRotation::Identity)
390*8975f5c5SAndroid Build Coastguard Worker {}
391*8975f5c5SAndroid Build Coastguard Worker 
PackPixelsParams(const gl::Rectangle & areaIn,const angle::Format & destFormat,GLuint outputPitchIn,bool reverseRowOrderIn,gl::Buffer * packBufferIn,ptrdiff_t offsetIn)392*8975f5c5SAndroid Build Coastguard Worker PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
393*8975f5c5SAndroid Build Coastguard Worker                                    const angle::Format &destFormat,
394*8975f5c5SAndroid Build Coastguard Worker                                    GLuint outputPitchIn,
395*8975f5c5SAndroid Build Coastguard Worker                                    bool reverseRowOrderIn,
396*8975f5c5SAndroid Build Coastguard Worker                                    gl::Buffer *packBufferIn,
397*8975f5c5SAndroid Build Coastguard Worker                                    ptrdiff_t offsetIn)
398*8975f5c5SAndroid Build Coastguard Worker     : area(areaIn),
399*8975f5c5SAndroid Build Coastguard Worker       destFormat(&destFormat),
400*8975f5c5SAndroid Build Coastguard Worker       outputPitch(outputPitchIn),
401*8975f5c5SAndroid Build Coastguard Worker       packBuffer(packBufferIn),
402*8975f5c5SAndroid Build Coastguard Worker       reverseRowOrder(reverseRowOrderIn),
403*8975f5c5SAndroid Build Coastguard Worker       offset(offsetIn),
404*8975f5c5SAndroid Build Coastguard Worker       rotation(SurfaceRotation::Identity)
405*8975f5c5SAndroid Build Coastguard Worker {}
406*8975f5c5SAndroid Build Coastguard Worker 
PackPixels(const PackPixelsParams & params,const angle::Format & sourceFormat,int inputPitchIn,const uint8_t * sourceIn,uint8_t * destWithoutOffset)407*8975f5c5SAndroid Build Coastguard Worker void PackPixels(const PackPixelsParams &params,
408*8975f5c5SAndroid Build Coastguard Worker                 const angle::Format &sourceFormat,
409*8975f5c5SAndroid Build Coastguard Worker                 int inputPitchIn,
410*8975f5c5SAndroid Build Coastguard Worker                 const uint8_t *sourceIn,
411*8975f5c5SAndroid Build Coastguard Worker                 uint8_t *destWithoutOffset)
412*8975f5c5SAndroid Build Coastguard Worker {
413*8975f5c5SAndroid Build Coastguard Worker     uint8_t *destWithOffset = destWithoutOffset + params.offset;
414*8975f5c5SAndroid Build Coastguard Worker 
415*8975f5c5SAndroid Build Coastguard Worker     const uint8_t *source = sourceIn;
416*8975f5c5SAndroid Build Coastguard Worker     int inputPitch        = inputPitchIn;
417*8975f5c5SAndroid Build Coastguard Worker     int destWidth         = params.area.width;
418*8975f5c5SAndroid Build Coastguard Worker     int destHeight        = params.area.height;
419*8975f5c5SAndroid Build Coastguard Worker     int xAxisPitch        = 0;
420*8975f5c5SAndroid Build Coastguard Worker     int yAxisPitch        = 0;
421*8975f5c5SAndroid Build Coastguard Worker     switch (params.rotation)
422*8975f5c5SAndroid Build Coastguard Worker     {
423*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Identity:
424*8975f5c5SAndroid Build Coastguard Worker             // The source image is not rotated (i.e. matches the device's orientation), and may or
425*8975f5c5SAndroid Build Coastguard Worker             // may not be y-flipped.  The image is row-major.  Each source row (one step along the
426*8975f5c5SAndroid Build Coastguard Worker             // y-axis for each step in the dest y-axis) is inputPitch past the previous row.  Along
427*8975f5c5SAndroid Build Coastguard Worker             // a row, each source pixel (one step along the x-axis for each step in the dest
428*8975f5c5SAndroid Build Coastguard Worker             // x-axis) is sourceFormat.pixelBytes past the previous pixel.
429*8975f5c5SAndroid Build Coastguard Worker             xAxisPitch = sourceFormat.pixelBytes;
430*8975f5c5SAndroid Build Coastguard Worker             if (params.reverseRowOrder)
431*8975f5c5SAndroid Build Coastguard Worker             {
432*8975f5c5SAndroid Build Coastguard Worker                 // The source image is y-flipped, which means we start at the last row, and each
433*8975f5c5SAndroid Build Coastguard Worker                 // source row is BEFORE the previous row.
434*8975f5c5SAndroid Build Coastguard Worker                 source += inputPitchIn * (params.area.height - 1);
435*8975f5c5SAndroid Build Coastguard Worker                 inputPitch = -inputPitch;
436*8975f5c5SAndroid Build Coastguard Worker                 yAxisPitch = -inputPitchIn;
437*8975f5c5SAndroid Build Coastguard Worker             }
438*8975f5c5SAndroid Build Coastguard Worker             else
439*8975f5c5SAndroid Build Coastguard Worker             {
440*8975f5c5SAndroid Build Coastguard Worker                 yAxisPitch = inputPitchIn;
441*8975f5c5SAndroid Build Coastguard Worker             }
442*8975f5c5SAndroid Build Coastguard Worker             break;
443*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated90Degrees:
444*8975f5c5SAndroid Build Coastguard Worker             // The source image is rotated 90 degrees counter-clockwise.  Y-flip is always applied
445*8975f5c5SAndroid Build Coastguard Worker             // to rotated images.  The image is column-major.  Each source column (one step along
446*8975f5c5SAndroid Build Coastguard Worker             // the source x-axis for each step in the dest y-axis) is inputPitch past the previous
447*8975f5c5SAndroid Build Coastguard Worker             // column.  Along a column, each source pixel (one step along the y-axis for each step
448*8975f5c5SAndroid Build Coastguard Worker             // in the dest x-axis) is sourceFormat.pixelBytes past the previous pixel.
449*8975f5c5SAndroid Build Coastguard Worker             xAxisPitch = inputPitchIn;
450*8975f5c5SAndroid Build Coastguard Worker             yAxisPitch = sourceFormat.pixelBytes;
451*8975f5c5SAndroid Build Coastguard Worker             destWidth  = params.area.height;
452*8975f5c5SAndroid Build Coastguard Worker             destHeight = params.area.width;
453*8975f5c5SAndroid Build Coastguard Worker             break;
454*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated180Degrees:
455*8975f5c5SAndroid Build Coastguard Worker             // The source image is rotated 180 degrees.  Y-flip is always applied to rotated
456*8975f5c5SAndroid Build Coastguard Worker             // images.  The image is row-major, but upside down.  Each source row (one step along
457*8975f5c5SAndroid Build Coastguard Worker             // the y-axis for each step in the dest y-axis) is inputPitch after the previous row.
458*8975f5c5SAndroid Build Coastguard Worker             // Along a row, each source pixel (one step along the x-axis for each step in the dest
459*8975f5c5SAndroid Build Coastguard Worker             // x-axis) is sourceFormat.pixelBytes BEFORE the previous pixel.
460*8975f5c5SAndroid Build Coastguard Worker             xAxisPitch = -static_cast<int>(sourceFormat.pixelBytes);
461*8975f5c5SAndroid Build Coastguard Worker             yAxisPitch = inputPitchIn;
462*8975f5c5SAndroid Build Coastguard Worker             source += sourceFormat.pixelBytes * (params.area.width - 1);
463*8975f5c5SAndroid Build Coastguard Worker             break;
464*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated270Degrees:
465*8975f5c5SAndroid Build Coastguard Worker             // The source image is rotated 270 degrees counter-clockwise (or 90 degrees clockwise).
466*8975f5c5SAndroid Build Coastguard Worker             // Y-flip is always applied to rotated images.  The image is column-major, where each
467*8975f5c5SAndroid Build Coastguard Worker             // column (one step in the source x-axis for one step in the dest y-axis) is inputPitch
468*8975f5c5SAndroid Build Coastguard Worker             // BEFORE the previous column.  Along a column, each source pixel (one step along the
469*8975f5c5SAndroid Build Coastguard Worker             // y-axis for each step in the dest x-axis) is sourceFormat.pixelBytes BEFORE the
470*8975f5c5SAndroid Build Coastguard Worker             // previous pixel.  The first pixel is at the end of the source.
471*8975f5c5SAndroid Build Coastguard Worker             xAxisPitch = -inputPitchIn;
472*8975f5c5SAndroid Build Coastguard Worker             yAxisPitch = -static_cast<int>(sourceFormat.pixelBytes);
473*8975f5c5SAndroid Build Coastguard Worker             destWidth  = params.area.height;
474*8975f5c5SAndroid Build Coastguard Worker             destHeight = params.area.width;
475*8975f5c5SAndroid Build Coastguard Worker             source += inputPitch * (params.area.height - 1) +
476*8975f5c5SAndroid Build Coastguard Worker                       sourceFormat.pixelBytes * (params.area.width - 1);
477*8975f5c5SAndroid Build Coastguard Worker             break;
478*8975f5c5SAndroid Build Coastguard Worker         default:
479*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
480*8975f5c5SAndroid Build Coastguard Worker             break;
481*8975f5c5SAndroid Build Coastguard Worker     }
482*8975f5c5SAndroid Build Coastguard Worker 
483*8975f5c5SAndroid Build Coastguard Worker     if (params.rotation == SurfaceRotation::Identity && sourceFormat == *params.destFormat)
484*8975f5c5SAndroid Build Coastguard Worker     {
485*8975f5c5SAndroid Build Coastguard Worker         // Direct copy possible
486*8975f5c5SAndroid Build Coastguard Worker         for (int y = 0; y < params.area.height; ++y)
487*8975f5c5SAndroid Build Coastguard Worker         {
488*8975f5c5SAndroid Build Coastguard Worker             memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
489*8975f5c5SAndroid Build Coastguard Worker                    params.area.width * sourceFormat.pixelBytes);
490*8975f5c5SAndroid Build Coastguard Worker         }
491*8975f5c5SAndroid Build Coastguard Worker         return;
492*8975f5c5SAndroid Build Coastguard Worker     }
493*8975f5c5SAndroid Build Coastguard Worker 
494*8975f5c5SAndroid Build Coastguard Worker     FastCopyFunction fastCopyFunc = sourceFormat.fastCopyFunctions.get(params.destFormat->id);
495*8975f5c5SAndroid Build Coastguard Worker 
496*8975f5c5SAndroid Build Coastguard Worker     if (fastCopyFunc)
497*8975f5c5SAndroid Build Coastguard Worker     {
498*8975f5c5SAndroid Build Coastguard Worker         // Fast copy is possible through some special function
499*8975f5c5SAndroid Build Coastguard Worker         fastCopyFunc(source, xAxisPitch, yAxisPitch, destWithOffset, params.destFormat->pixelBytes,
500*8975f5c5SAndroid Build Coastguard Worker                      params.outputPitch, destWidth, destHeight);
501*8975f5c5SAndroid Build Coastguard Worker         return;
502*8975f5c5SAndroid Build Coastguard Worker     }
503*8975f5c5SAndroid Build Coastguard Worker 
504*8975f5c5SAndroid Build Coastguard Worker     PixelWriteFunction pixelWriteFunction = params.destFormat->pixelWriteFunction;
505*8975f5c5SAndroid Build Coastguard Worker     ASSERT(pixelWriteFunction != nullptr);
506*8975f5c5SAndroid Build Coastguard Worker 
507*8975f5c5SAndroid Build Coastguard Worker     // Maximum size of any Color<T> type used.
508*8975f5c5SAndroid Build Coastguard Worker     uint8_t temp[16];
509*8975f5c5SAndroid Build Coastguard Worker     static_assert(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) &&
510*8975f5c5SAndroid Build Coastguard Worker                       sizeof(temp) >= sizeof(gl::ColorI) &&
511*8975f5c5SAndroid Build Coastguard Worker                       sizeof(temp) >= sizeof(angle::DepthStencil),
512*8975f5c5SAndroid Build Coastguard Worker                   "Unexpected size of pixel struct.");
513*8975f5c5SAndroid Build Coastguard Worker 
514*8975f5c5SAndroid Build Coastguard Worker     PixelReadFunction pixelReadFunction = sourceFormat.pixelReadFunction;
515*8975f5c5SAndroid Build Coastguard Worker     ASSERT(pixelReadFunction != nullptr);
516*8975f5c5SAndroid Build Coastguard Worker 
517*8975f5c5SAndroid Build Coastguard Worker     for (int y = 0; y < destHeight; ++y)
518*8975f5c5SAndroid Build Coastguard Worker     {
519*8975f5c5SAndroid Build Coastguard Worker         for (int x = 0; x < destWidth; ++x)
520*8975f5c5SAndroid Build Coastguard Worker         {
521*8975f5c5SAndroid Build Coastguard Worker             uint8_t *dest =
522*8975f5c5SAndroid Build Coastguard Worker                 destWithOffset + y * params.outputPitch + x * params.destFormat->pixelBytes;
523*8975f5c5SAndroid Build Coastguard Worker             const uint8_t *src = source + y * yAxisPitch + x * xAxisPitch;
524*8975f5c5SAndroid Build Coastguard Worker 
525*8975f5c5SAndroid Build Coastguard Worker             // readFunc and writeFunc will be using the same type of color, CopyTexImage
526*8975f5c5SAndroid Build Coastguard Worker             // will not allow the copy otherwise.
527*8975f5c5SAndroid Build Coastguard Worker             pixelReadFunction(src, temp);
528*8975f5c5SAndroid Build Coastguard Worker             pixelWriteFunction(temp, dest);
529*8975f5c5SAndroid Build Coastguard Worker         }
530*8975f5c5SAndroid Build Coastguard Worker     }
531*8975f5c5SAndroid Build Coastguard Worker }
532*8975f5c5SAndroid Build Coastguard Worker 
GetPackPixelsParams(const gl::InternalFormat & sizedFormatInfo,GLuint outputPitch,const gl::PixelPackState & packState,gl::Buffer * packBuffer,const gl::Rectangle & area,const gl::Rectangle & clippedArea,rx::PackPixelsParams * paramsOut,GLuint * skipBytesOut)533*8975f5c5SAndroid Build Coastguard Worker angle::Result GetPackPixelsParams(const gl::InternalFormat &sizedFormatInfo,
534*8975f5c5SAndroid Build Coastguard Worker                                   GLuint outputPitch,
535*8975f5c5SAndroid Build Coastguard Worker                                   const gl::PixelPackState &packState,
536*8975f5c5SAndroid Build Coastguard Worker                                   gl::Buffer *packBuffer,
537*8975f5c5SAndroid Build Coastguard Worker                                   const gl::Rectangle &area,
538*8975f5c5SAndroid Build Coastguard Worker                                   const gl::Rectangle &clippedArea,
539*8975f5c5SAndroid Build Coastguard Worker                                   rx::PackPixelsParams *paramsOut,
540*8975f5c5SAndroid Build Coastguard Worker                                   GLuint *skipBytesOut)
541*8975f5c5SAndroid Build Coastguard Worker {
542*8975f5c5SAndroid Build Coastguard Worker     angle::CheckedNumeric<GLuint> checkedSkipBytes = *skipBytesOut;
543*8975f5c5SAndroid Build Coastguard Worker     checkedSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes +
544*8975f5c5SAndroid Build Coastguard Worker                         (clippedArea.y - area.y) * outputPitch;
545*8975f5c5SAndroid Build Coastguard Worker     if (!checkedSkipBytes.AssignIfValid(skipBytesOut))
546*8975f5c5SAndroid Build Coastguard Worker     {
547*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
548*8975f5c5SAndroid Build Coastguard Worker     }
549*8975f5c5SAndroid Build Coastguard Worker 
550*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID angleFormatID =
551*8975f5c5SAndroid Build Coastguard Worker         angle::Format::InternalFormatToID(sizedFormatInfo.sizedInternalFormat);
552*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &angleFormat = angle::Format::Get(angleFormatID);
553*8975f5c5SAndroid Build Coastguard Worker 
554*8975f5c5SAndroid Build Coastguard Worker     *paramsOut = rx::PackPixelsParams(clippedArea, angleFormat, outputPitch,
555*8975f5c5SAndroid Build Coastguard Worker                                       packState.reverseRowOrder, packBuffer, 0);
556*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
557*8975f5c5SAndroid Build Coastguard Worker }
558*8975f5c5SAndroid Build Coastguard Worker 
has(angle::FormatID formatID) const559*8975f5c5SAndroid Build Coastguard Worker bool FastCopyFunctionMap::has(angle::FormatID formatID) const
560*8975f5c5SAndroid Build Coastguard Worker {
561*8975f5c5SAndroid Build Coastguard Worker     return (get(formatID) != nullptr);
562*8975f5c5SAndroid Build Coastguard Worker }
563*8975f5c5SAndroid Build Coastguard Worker 
564*8975f5c5SAndroid Build Coastguard Worker namespace
565*8975f5c5SAndroid Build Coastguard Worker {
566*8975f5c5SAndroid Build Coastguard Worker 
getEntry(const FastCopyFunctionMap::Entry * entry,size_t numEntries,angle::FormatID formatID)567*8975f5c5SAndroid Build Coastguard Worker const FastCopyFunctionMap::Entry *getEntry(const FastCopyFunctionMap::Entry *entry,
568*8975f5c5SAndroid Build Coastguard Worker                                            size_t numEntries,
569*8975f5c5SAndroid Build Coastguard Worker                                            angle::FormatID formatID)
570*8975f5c5SAndroid Build Coastguard Worker {
571*8975f5c5SAndroid Build Coastguard Worker     const FastCopyFunctionMap::Entry *end = entry + numEntries;
572*8975f5c5SAndroid Build Coastguard Worker     while (entry != end)
573*8975f5c5SAndroid Build Coastguard Worker     {
574*8975f5c5SAndroid Build Coastguard Worker         if (entry->formatID == formatID)
575*8975f5c5SAndroid Build Coastguard Worker         {
576*8975f5c5SAndroid Build Coastguard Worker             return entry;
577*8975f5c5SAndroid Build Coastguard Worker         }
578*8975f5c5SAndroid Build Coastguard Worker         ++entry;
579*8975f5c5SAndroid Build Coastguard Worker     }
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker     return nullptr;
582*8975f5c5SAndroid Build Coastguard Worker }
583*8975f5c5SAndroid Build Coastguard Worker 
584*8975f5c5SAndroid Build Coastguard Worker }  // namespace
585*8975f5c5SAndroid Build Coastguard Worker 
get(angle::FormatID formatID) const586*8975f5c5SAndroid Build Coastguard Worker FastCopyFunction FastCopyFunctionMap::get(angle::FormatID formatID) const
587*8975f5c5SAndroid Build Coastguard Worker {
588*8975f5c5SAndroid Build Coastguard Worker     const FastCopyFunctionMap::Entry *entry = getEntry(mData, mSize, formatID);
589*8975f5c5SAndroid Build Coastguard Worker     return entry ? entry->func : nullptr;
590*8975f5c5SAndroid Build Coastguard Worker }
591*8975f5c5SAndroid Build Coastguard Worker 
ShouldUseDebugLayers(const egl::AttributeMap & attribs)592*8975f5c5SAndroid Build Coastguard Worker bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
593*8975f5c5SAndroid Build Coastguard Worker {
594*8975f5c5SAndroid Build Coastguard Worker     EGLAttrib debugSetting =
595*8975f5c5SAndroid Build Coastguard Worker         attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
596*8975f5c5SAndroid Build Coastguard Worker 
597*8975f5c5SAndroid Build Coastguard Worker     // Prefer to enable debug layers when available.
598*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_ENABLE_ASSERTS)
599*8975f5c5SAndroid Build Coastguard Worker     return (debugSetting != EGL_FALSE);
600*8975f5c5SAndroid Build Coastguard Worker #else
601*8975f5c5SAndroid Build Coastguard Worker     return (debugSetting == EGL_TRUE);
602*8975f5c5SAndroid Build Coastguard Worker #endif  // defined(ANGLE_ENABLE_ASSERTS)
603*8975f5c5SAndroid Build Coastguard Worker }
604*8975f5c5SAndroid Build Coastguard Worker 
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)605*8975f5c5SAndroid Build Coastguard Worker void CopyImageCHROMIUM(const uint8_t *sourceData,
606*8975f5c5SAndroid Build Coastguard Worker                        size_t sourceRowPitch,
607*8975f5c5SAndroid Build Coastguard Worker                        size_t sourcePixelBytes,
608*8975f5c5SAndroid Build Coastguard Worker                        size_t sourceDepthPitch,
609*8975f5c5SAndroid Build Coastguard Worker                        PixelReadFunction pixelReadFunction,
610*8975f5c5SAndroid Build Coastguard Worker                        uint8_t *destData,
611*8975f5c5SAndroid Build Coastguard Worker                        size_t destRowPitch,
612*8975f5c5SAndroid Build Coastguard Worker                        size_t destPixelBytes,
613*8975f5c5SAndroid Build Coastguard Worker                        size_t destDepthPitch,
614*8975f5c5SAndroid Build Coastguard Worker                        PixelWriteFunction pixelWriteFunction,
615*8975f5c5SAndroid Build Coastguard Worker                        GLenum destUnsizedFormat,
616*8975f5c5SAndroid Build Coastguard Worker                        GLenum destComponentType,
617*8975f5c5SAndroid Build Coastguard Worker                        size_t width,
618*8975f5c5SAndroid Build Coastguard Worker                        size_t height,
619*8975f5c5SAndroid Build Coastguard Worker                        size_t depth,
620*8975f5c5SAndroid Build Coastguard Worker                        bool unpackFlipY,
621*8975f5c5SAndroid Build Coastguard Worker                        bool unpackPremultiplyAlpha,
622*8975f5c5SAndroid Build Coastguard Worker                        bool unpackUnmultiplyAlpha)
623*8975f5c5SAndroid Build Coastguard Worker {
624*8975f5c5SAndroid Build Coastguard Worker     using ConversionFunction              = void (*)(gl::ColorF *);
625*8975f5c5SAndroid Build Coastguard Worker     ConversionFunction conversionFunction = CopyColor;
626*8975f5c5SAndroid Build Coastguard Worker     if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
627*8975f5c5SAndroid Build Coastguard Worker     {
628*8975f5c5SAndroid Build Coastguard Worker         if (unpackPremultiplyAlpha)
629*8975f5c5SAndroid Build Coastguard Worker         {
630*8975f5c5SAndroid Build Coastguard Worker             conversionFunction = PremultiplyAlpha;
631*8975f5c5SAndroid Build Coastguard Worker         }
632*8975f5c5SAndroid Build Coastguard Worker         else
633*8975f5c5SAndroid Build Coastguard Worker         {
634*8975f5c5SAndroid Build Coastguard Worker             conversionFunction = UnmultiplyAlpha;
635*8975f5c5SAndroid Build Coastguard Worker         }
636*8975f5c5SAndroid Build Coastguard Worker     }
637*8975f5c5SAndroid Build Coastguard Worker 
638*8975f5c5SAndroid Build Coastguard Worker     auto clipChannelsFunction = ClipChannelsNoOp;
639*8975f5c5SAndroid Build Coastguard Worker     switch (destUnsizedFormat)
640*8975f5c5SAndroid Build Coastguard Worker     {
641*8975f5c5SAndroid Build Coastguard Worker         case GL_RED:
642*8975f5c5SAndroid Build Coastguard Worker             clipChannelsFunction = ClipChannelsR;
643*8975f5c5SAndroid Build Coastguard Worker             break;
644*8975f5c5SAndroid Build Coastguard Worker         case GL_RG:
645*8975f5c5SAndroid Build Coastguard Worker             clipChannelsFunction = ClipChannelsRG;
646*8975f5c5SAndroid Build Coastguard Worker             break;
647*8975f5c5SAndroid Build Coastguard Worker         case GL_RGB:
648*8975f5c5SAndroid Build Coastguard Worker             clipChannelsFunction = ClipChannelsRGB;
649*8975f5c5SAndroid Build Coastguard Worker             break;
650*8975f5c5SAndroid Build Coastguard Worker         case GL_LUMINANCE:
651*8975f5c5SAndroid Build Coastguard Worker             clipChannelsFunction = ClipChannelsLuminance;
652*8975f5c5SAndroid Build Coastguard Worker             break;
653*8975f5c5SAndroid Build Coastguard Worker         case GL_ALPHA:
654*8975f5c5SAndroid Build Coastguard Worker             clipChannelsFunction = ClipChannelsAlpha;
655*8975f5c5SAndroid Build Coastguard Worker             break;
656*8975f5c5SAndroid Build Coastguard Worker     }
657*8975f5c5SAndroid Build Coastguard Worker 
658*8975f5c5SAndroid Build Coastguard Worker     auto writeFunction = (destComponentType == GL_UNSIGNED_INT) ? WriteUintColor : WriteFloatColor;
659*8975f5c5SAndroid Build Coastguard Worker 
660*8975f5c5SAndroid Build Coastguard Worker     for (size_t z = 0; z < depth; z++)
661*8975f5c5SAndroid Build Coastguard Worker     {
662*8975f5c5SAndroid Build Coastguard Worker         for (size_t y = 0; y < height; y++)
663*8975f5c5SAndroid Build Coastguard Worker         {
664*8975f5c5SAndroid Build Coastguard Worker             for (size_t x = 0; x < width; x++)
665*8975f5c5SAndroid Build Coastguard Worker             {
666*8975f5c5SAndroid Build Coastguard Worker                 const uint8_t *sourcePixelData =
667*8975f5c5SAndroid Build Coastguard Worker                     sourceData + y * sourceRowPitch + x * sourcePixelBytes + z * sourceDepthPitch;
668*8975f5c5SAndroid Build Coastguard Worker 
669*8975f5c5SAndroid Build Coastguard Worker                 gl::ColorF sourceColor;
670*8975f5c5SAndroid Build Coastguard Worker                 pixelReadFunction(sourcePixelData, reinterpret_cast<uint8_t *>(&sourceColor));
671*8975f5c5SAndroid Build Coastguard Worker 
672*8975f5c5SAndroid Build Coastguard Worker                 conversionFunction(&sourceColor);
673*8975f5c5SAndroid Build Coastguard Worker                 clipChannelsFunction(&sourceColor);
674*8975f5c5SAndroid Build Coastguard Worker 
675*8975f5c5SAndroid Build Coastguard Worker                 size_t destY = 0;
676*8975f5c5SAndroid Build Coastguard Worker                 if (unpackFlipY)
677*8975f5c5SAndroid Build Coastguard Worker                 {
678*8975f5c5SAndroid Build Coastguard Worker                     destY += (height - 1);
679*8975f5c5SAndroid Build Coastguard Worker                     destY -= y;
680*8975f5c5SAndroid Build Coastguard Worker                 }
681*8975f5c5SAndroid Build Coastguard Worker                 else
682*8975f5c5SAndroid Build Coastguard Worker                 {
683*8975f5c5SAndroid Build Coastguard Worker                     destY += y;
684*8975f5c5SAndroid Build Coastguard Worker                 }
685*8975f5c5SAndroid Build Coastguard Worker 
686*8975f5c5SAndroid Build Coastguard Worker                 uint8_t *destPixelData =
687*8975f5c5SAndroid Build Coastguard Worker                     destData + destY * destRowPitch + x * destPixelBytes + z * destDepthPitch;
688*8975f5c5SAndroid Build Coastguard Worker                 writeFunction(sourceColor, pixelWriteFunction, destPixelData);
689*8975f5c5SAndroid Build Coastguard Worker             }
690*8975f5c5SAndroid Build Coastguard Worker         }
691*8975f5c5SAndroid Build Coastguard Worker     }
692*8975f5c5SAndroid Build Coastguard Worker }
693*8975f5c5SAndroid Build Coastguard Worker 
694*8975f5c5SAndroid Build Coastguard Worker // IncompleteTextureSet implementation.
IncompleteTextureSet()695*8975f5c5SAndroid Build Coastguard Worker IncompleteTextureSet::IncompleteTextureSet() {}
696*8975f5c5SAndroid Build Coastguard Worker 
~IncompleteTextureSet()697*8975f5c5SAndroid Build Coastguard Worker IncompleteTextureSet::~IncompleteTextureSet() {}
698*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const gl::Context * context)699*8975f5c5SAndroid Build Coastguard Worker void IncompleteTextureSet::onDestroy(const gl::Context *context)
700*8975f5c5SAndroid Build Coastguard Worker {
701*8975f5c5SAndroid Build Coastguard Worker     // Clear incomplete textures.
702*8975f5c5SAndroid Build Coastguard Worker     for (auto &incompleteTextures : mIncompleteTextures)
703*8975f5c5SAndroid Build Coastguard Worker     {
704*8975f5c5SAndroid Build Coastguard Worker         for (auto &incompleteTexture : incompleteTextures)
705*8975f5c5SAndroid Build Coastguard Worker         {
706*8975f5c5SAndroid Build Coastguard Worker             if (incompleteTexture.get() != nullptr)
707*8975f5c5SAndroid Build Coastguard Worker             {
708*8975f5c5SAndroid Build Coastguard Worker                 incompleteTexture->onDestroy(context);
709*8975f5c5SAndroid Build Coastguard Worker                 incompleteTexture.set(context, nullptr);
710*8975f5c5SAndroid Build Coastguard Worker             }
711*8975f5c5SAndroid Build Coastguard Worker         }
712*8975f5c5SAndroid Build Coastguard Worker     }
713*8975f5c5SAndroid Build Coastguard Worker }
714*8975f5c5SAndroid Build Coastguard Worker 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::SamplerFormat format,MultisampleTextureInitializer * multisampleInitializer,gl::Texture ** textureOut)715*8975f5c5SAndroid Build Coastguard Worker angle::Result IncompleteTextureSet::getIncompleteTexture(
716*8975f5c5SAndroid Build Coastguard Worker     const gl::Context *context,
717*8975f5c5SAndroid Build Coastguard Worker     gl::TextureType type,
718*8975f5c5SAndroid Build Coastguard Worker     gl::SamplerFormat format,
719*8975f5c5SAndroid Build Coastguard Worker     MultisampleTextureInitializer *multisampleInitializer,
720*8975f5c5SAndroid Build Coastguard Worker     gl::Texture **textureOut)
721*8975f5c5SAndroid Build Coastguard Worker {
722*8975f5c5SAndroid Build Coastguard Worker     *textureOut = mIncompleteTextures[format][type].get();
723*8975f5c5SAndroid Build Coastguard Worker     if (*textureOut != nullptr)
724*8975f5c5SAndroid Build Coastguard Worker     {
725*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
726*8975f5c5SAndroid Build Coastguard Worker     }
727*8975f5c5SAndroid Build Coastguard Worker 
728*8975f5c5SAndroid Build Coastguard Worker     ContextImpl *implFactory = context->getImplementation();
729*8975f5c5SAndroid Build Coastguard Worker 
730*8975f5c5SAndroid Build Coastguard Worker     gl::Extents colorSize(1, 1, 1);
731*8975f5c5SAndroid Build Coastguard Worker     gl::PixelUnpackState unpack;
732*8975f5c5SAndroid Build Coastguard Worker     unpack.alignment = 1;
733*8975f5c5SAndroid Build Coastguard Worker     gl::Box area(0, 0, 0, 1, 1, 1);
734*8975f5c5SAndroid Build Coastguard Worker     const IncompleteTextureParameters &incompleteTextureParam =
735*8975f5c5SAndroid Build Coastguard Worker         kIncompleteTextureParameters[format];
736*8975f5c5SAndroid Build Coastguard Worker 
737*8975f5c5SAndroid Build Coastguard Worker     // Cube map arrays are expected to have layer counts that are multiples of 6
738*8975f5c5SAndroid Build Coastguard Worker     constexpr int kCubeMapArraySize = 6;
739*8975f5c5SAndroid Build Coastguard Worker     if (type == gl::TextureType::CubeMapArray)
740*8975f5c5SAndroid Build Coastguard Worker     {
741*8975f5c5SAndroid Build Coastguard Worker         // From the GLES 3.2 spec:
742*8975f5c5SAndroid Build Coastguard Worker         //   8.18. IMMUTABLE-FORMAT TEXTURE IMAGES
743*8975f5c5SAndroid Build Coastguard Worker         //   TexStorage3D Errors
744*8975f5c5SAndroid Build Coastguard Worker         //   An INVALID_OPERATION error is generated if any of the following conditions hold:
745*8975f5c5SAndroid Build Coastguard Worker         //     * target is TEXTURE_CUBE_MAP_ARRAY and depth is not a multiple of 6
746*8975f5c5SAndroid Build Coastguard Worker         // Since ANGLE treats incomplete textures as immutable, respect that here.
747*8975f5c5SAndroid Build Coastguard Worker         colorSize.depth = kCubeMapArraySize;
748*8975f5c5SAndroid Build Coastguard Worker         area.depth      = kCubeMapArraySize;
749*8975f5c5SAndroid Build Coastguard Worker     }
750*8975f5c5SAndroid Build Coastguard Worker 
751*8975f5c5SAndroid Build Coastguard Worker     // If a texture is external use a 2D texture for the incomplete texture
752*8975f5c5SAndroid Build Coastguard Worker     gl::TextureType createType = (type == gl::TextureType::External) ? gl::TextureType::_2D : type;
753*8975f5c5SAndroid Build Coastguard Worker 
754*8975f5c5SAndroid Build Coastguard Worker     gl::Texture *tex =
755*8975f5c5SAndroid Build Coastguard Worker         new gl::Texture(implFactory, {std::numeric_limits<GLuint>::max()}, createType);
756*8975f5c5SAndroid Build Coastguard Worker     angle::UniqueObjectPointer<gl::Texture, gl::Context> t(tex, context);
757*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *incompleteTextureBufferAttachment = nullptr;
758*8975f5c5SAndroid Build Coastguard Worker 
759*8975f5c5SAndroid Build Coastguard Worker     // This is a bit of a kludge but is necessary to consume the error.
760*8975f5c5SAndroid Build Coastguard Worker     gl::Context *mutableContext = const_cast<gl::Context *>(context);
761*8975f5c5SAndroid Build Coastguard Worker 
762*8975f5c5SAndroid Build Coastguard Worker     if (createType == gl::TextureType::Buffer)
763*8975f5c5SAndroid Build Coastguard Worker     {
764*8975f5c5SAndroid Build Coastguard Worker         constexpr uint32_t kBufferInitData = 0;
765*8975f5c5SAndroid Build Coastguard Worker         incompleteTextureBufferAttachment =
766*8975f5c5SAndroid Build Coastguard Worker             new gl::Buffer(implFactory, {std::numeric_limits<GLuint>::max()});
767*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(incompleteTextureBufferAttachment->bufferData(
768*8975f5c5SAndroid Build Coastguard Worker             mutableContext, gl::BufferBinding::Texture, &kBufferInitData, sizeof(kBufferInitData),
769*8975f5c5SAndroid Build Coastguard Worker             gl::BufferUsage::StaticDraw));
770*8975f5c5SAndroid Build Coastguard Worker     }
771*8975f5c5SAndroid Build Coastguard Worker     else if (createType == gl::TextureType::_2DMultisample)
772*8975f5c5SAndroid Build Coastguard Worker     {
773*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(t->setStorageMultisample(mutableContext, createType, 1,
774*8975f5c5SAndroid Build Coastguard Worker                                            incompleteTextureParam.sizedInternalFormat, colorSize,
775*8975f5c5SAndroid Build Coastguard Worker                                            true));
776*8975f5c5SAndroid Build Coastguard Worker     }
777*8975f5c5SAndroid Build Coastguard Worker     else
778*8975f5c5SAndroid Build Coastguard Worker     {
779*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(t->setStorage(mutableContext, createType, 1,
780*8975f5c5SAndroid Build Coastguard Worker                                 incompleteTextureParam.sizedInternalFormat, colorSize));
781*8975f5c5SAndroid Build Coastguard Worker     }
782*8975f5c5SAndroid Build Coastguard Worker     t->markInternalIncompleteTexture();
783*8975f5c5SAndroid Build Coastguard Worker 
784*8975f5c5SAndroid Build Coastguard Worker     if (type == gl::TextureType::CubeMap)
785*8975f5c5SAndroid Build Coastguard Worker     {
786*8975f5c5SAndroid Build Coastguard Worker         for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
787*8975f5c5SAndroid Build Coastguard Worker         {
788*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr, face, 0, area,
789*8975f5c5SAndroid Build Coastguard Worker                                      incompleteTextureParam.format, incompleteTextureParam.type,
790*8975f5c5SAndroid Build Coastguard Worker                                      incompleteTextureParam.clearColor));
791*8975f5c5SAndroid Build Coastguard Worker         }
792*8975f5c5SAndroid Build Coastguard Worker     }
793*8975f5c5SAndroid Build Coastguard Worker     else if (type == gl::TextureType::CubeMapArray)
794*8975f5c5SAndroid Build Coastguard Worker     {
795*8975f5c5SAndroid Build Coastguard Worker         // We need to provide enough pixel data to fill the array of six faces
796*8975f5c5SAndroid Build Coastguard Worker         GLubyte incompleteCubeArrayPixels[kCubeMapArraySize][4];
797*8975f5c5SAndroid Build Coastguard Worker         for (int i = 0; i < kCubeMapArraySize; ++i)
798*8975f5c5SAndroid Build Coastguard Worker         {
799*8975f5c5SAndroid Build Coastguard Worker             incompleteCubeArrayPixels[i][0] = incompleteTextureParam.clearColor[0];
800*8975f5c5SAndroid Build Coastguard Worker             incompleteCubeArrayPixels[i][1] = incompleteTextureParam.clearColor[1];
801*8975f5c5SAndroid Build Coastguard Worker             incompleteCubeArrayPixels[i][2] = incompleteTextureParam.clearColor[2];
802*8975f5c5SAndroid Build Coastguard Worker             incompleteCubeArrayPixels[i][3] = incompleteTextureParam.clearColor[3];
803*8975f5c5SAndroid Build Coastguard Worker         }
804*8975f5c5SAndroid Build Coastguard Worker 
805*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
806*8975f5c5SAndroid Build Coastguard Worker                                  gl::NonCubeTextureTypeToTarget(createType), 0, area,
807*8975f5c5SAndroid Build Coastguard Worker                                  incompleteTextureParam.format, incompleteTextureParam.type,
808*8975f5c5SAndroid Build Coastguard Worker                                  *incompleteCubeArrayPixels));
809*8975f5c5SAndroid Build Coastguard Worker     }
810*8975f5c5SAndroid Build Coastguard Worker     else if (type == gl::TextureType::_2DMultisample)
811*8975f5c5SAndroid Build Coastguard Worker     {
812*8975f5c5SAndroid Build Coastguard Worker         // Call a specialized clear function to init a multisample texture.
813*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(multisampleInitializer->initializeMultisampleTextureToBlack(context, t.get()));
814*8975f5c5SAndroid Build Coastguard Worker     }
815*8975f5c5SAndroid Build Coastguard Worker     else if (type == gl::TextureType::Buffer)
816*8975f5c5SAndroid Build Coastguard Worker     {
817*8975f5c5SAndroid Build Coastguard Worker         ASSERT(incompleteTextureBufferAttachment != nullptr);
818*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(t->setBuffer(context, incompleteTextureBufferAttachment,
819*8975f5c5SAndroid Build Coastguard Worker                                incompleteTextureParam.sizedInternalFormat));
820*8975f5c5SAndroid Build Coastguard Worker     }
821*8975f5c5SAndroid Build Coastguard Worker     else
822*8975f5c5SAndroid Build Coastguard Worker     {
823*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
824*8975f5c5SAndroid Build Coastguard Worker                                  gl::NonCubeTextureTypeToTarget(createType), 0, area,
825*8975f5c5SAndroid Build Coastguard Worker                                  incompleteTextureParam.format, incompleteTextureParam.type,
826*8975f5c5SAndroid Build Coastguard Worker                                  incompleteTextureParam.clearColor));
827*8975f5c5SAndroid Build Coastguard Worker     }
828*8975f5c5SAndroid Build Coastguard Worker 
829*8975f5c5SAndroid Build Coastguard Worker     if (format == gl::SamplerFormat::Shadow)
830*8975f5c5SAndroid Build Coastguard Worker     {
831*8975f5c5SAndroid Build Coastguard Worker         // To avoid the undefined spec behavior for shadow samplers with a depth texture, we set the
832*8975f5c5SAndroid Build Coastguard Worker         // compare mode to GL_COMPARE_REF_TO_TEXTURE
833*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!t->hasObservers());
834*8975f5c5SAndroid Build Coastguard Worker         t->setCompareMode(context, GL_COMPARE_REF_TO_TEXTURE);
835*8975f5c5SAndroid Build Coastguard Worker     }
836*8975f5c5SAndroid Build Coastguard Worker 
837*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(t->syncState(context, gl::Command::Other));
838*8975f5c5SAndroid Build Coastguard Worker 
839*8975f5c5SAndroid Build Coastguard Worker     mIncompleteTextures[format][type].set(context, t.release());
840*8975f5c5SAndroid Build Coastguard Worker     *textureOut = mIncompleteTextures[format][type].get();
841*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
842*8975f5c5SAndroid Build Coastguard Worker }
843*8975f5c5SAndroid Build Coastguard Worker 
844*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
845*8975f5c5SAndroid Build Coastguard Worker     template void SetFloatUniformMatrix##api<cols, rows>::Run(     \
846*8975f5c5SAndroid Build Coastguard Worker         unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *)
847*8975f5c5SAndroid Build Coastguard Worker 
848*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
849*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
850*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
851*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
852*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
853*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3);
854*8975f5c5SAndroid Build Coastguard Worker 
855*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2);
856*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3);
857*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3);
858*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2);
859*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4);
860*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4);
861*8975f5c5SAndroid Build Coastguard Worker 
862*8975f5c5SAndroid Build Coastguard Worker #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
863*8975f5c5SAndroid Build Coastguard Worker 
864*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
865*8975f5c5SAndroid Build Coastguard Worker     template void SetFloatUniformMatrix##api<cols, 4>::Run(unsigned int, unsigned int, GLsizei, \
866*8975f5c5SAndroid Build Coastguard Worker                                                            GLboolean, const GLfloat *, uint8_t *)
867*8975f5c5SAndroid Build Coastguard Worker 
868*8975f5c5SAndroid Build Coastguard Worker template <int cols>
869*8975f5c5SAndroid Build Coastguard Worker struct SetFloatUniformMatrixGLSL<cols, 4>
870*8975f5c5SAndroid Build Coastguard Worker {
871*8975f5c5SAndroid Build Coastguard Worker     static void Run(unsigned int arrayElementOffset,
872*8975f5c5SAndroid Build Coastguard Worker                     unsigned int elementCount,
873*8975f5c5SAndroid Build Coastguard Worker                     GLsizei countIn,
874*8975f5c5SAndroid Build Coastguard Worker                     GLboolean transpose,
875*8975f5c5SAndroid Build Coastguard Worker                     const GLfloat *value,
876*8975f5c5SAndroid Build Coastguard Worker                     uint8_t *targetData);
877*8975f5c5SAndroid Build Coastguard Worker };
878*8975f5c5SAndroid Build Coastguard Worker 
879*8975f5c5SAndroid Build Coastguard Worker ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
880*8975f5c5SAndroid Build Coastguard Worker ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
881*8975f5c5SAndroid Build Coastguard Worker ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
882*8975f5c5SAndroid Build Coastguard Worker 
883*8975f5c5SAndroid Build Coastguard Worker #undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC
884*8975f5c5SAndroid Build Coastguard Worker 
885*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows)                      \
886*8975f5c5SAndroid Build Coastguard Worker     template void SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \
887*8975f5c5SAndroid Build Coastguard Worker                                                            GLboolean, const GLfloat *, uint8_t *)
888*8975f5c5SAndroid Build Coastguard Worker 
889*8975f5c5SAndroid Build Coastguard Worker template <int rows>
890*8975f5c5SAndroid Build Coastguard Worker struct SetFloatUniformMatrixHLSL<4, rows>
891*8975f5c5SAndroid Build Coastguard Worker {
892*8975f5c5SAndroid Build Coastguard Worker     static void Run(unsigned int arrayElementOffset,
893*8975f5c5SAndroid Build Coastguard Worker                     unsigned int elementCount,
894*8975f5c5SAndroid Build Coastguard Worker                     GLsizei countIn,
895*8975f5c5SAndroid Build Coastguard Worker                     GLboolean transpose,
896*8975f5c5SAndroid Build Coastguard Worker                     const GLfloat *value,
897*8975f5c5SAndroid Build Coastguard Worker                     uint8_t *targetData);
898*8975f5c5SAndroid Build Coastguard Worker };
899*8975f5c5SAndroid Build Coastguard Worker 
900*8975f5c5SAndroid Build Coastguard Worker ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
901*8975f5c5SAndroid Build Coastguard Worker ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
902*8975f5c5SAndroid Build Coastguard Worker ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
903*8975f5c5SAndroid Build Coastguard Worker 
904*8975f5c5SAndroid Build Coastguard Worker #undef ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC
905*8975f5c5SAndroid Build Coastguard Worker 
906*8975f5c5SAndroid Build Coastguard Worker template <int cols>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)907*8975f5c5SAndroid Build Coastguard Worker void SetFloatUniformMatrixGLSL<cols, 4>::Run(unsigned int arrayElementOffset,
908*8975f5c5SAndroid Build Coastguard Worker                                              unsigned int elementCount,
909*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei countIn,
910*8975f5c5SAndroid Build Coastguard Worker                                              GLboolean transpose,
911*8975f5c5SAndroid Build Coastguard Worker                                              const GLfloat *value,
912*8975f5c5SAndroid Build Coastguard Worker                                              uint8_t *targetData)
913*8975f5c5SAndroid Build Coastguard Worker {
914*8975f5c5SAndroid Build Coastguard Worker     const bool isSrcColumnMajor = !transpose;
915*8975f5c5SAndroid Build Coastguard Worker     if (isSrcColumnMajor)
916*8975f5c5SAndroid Build Coastguard Worker     {
917*8975f5c5SAndroid Build Coastguard Worker         // Both src and dst matrixs are has same layout,
918*8975f5c5SAndroid Build Coastguard Worker         // a single memcpy updates all the matrices
919*8975f5c5SAndroid Build Coastguard Worker         constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4;
920*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
921*8975f5c5SAndroid Build Coastguard Worker                                   targetData);
922*8975f5c5SAndroid Build Coastguard Worker     }
923*8975f5c5SAndroid Build Coastguard Worker     else
924*8975f5c5SAndroid Build Coastguard Worker     {
925*8975f5c5SAndroid Build Coastguard Worker         // fallback to general cases
926*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrix<false, cols, 4, true, cols, 4>(arrayElementOffset, elementCount,
927*8975f5c5SAndroid Build Coastguard Worker                                                              countIn, value, targetData);
928*8975f5c5SAndroid Build Coastguard Worker     }
929*8975f5c5SAndroid Build Coastguard Worker }
930*8975f5c5SAndroid Build Coastguard Worker 
931*8975f5c5SAndroid Build Coastguard Worker template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)932*8975f5c5SAndroid Build Coastguard Worker void SetFloatUniformMatrixGLSL<cols, rows>::Run(unsigned int arrayElementOffset,
933*8975f5c5SAndroid Build Coastguard Worker                                                 unsigned int elementCount,
934*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei countIn,
935*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
936*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value,
937*8975f5c5SAndroid Build Coastguard Worker                                                 uint8_t *targetData)
938*8975f5c5SAndroid Build Coastguard Worker {
939*8975f5c5SAndroid Build Coastguard Worker     const bool isSrcColumnMajor = !transpose;
940*8975f5c5SAndroid Build Coastguard Worker     // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
941*8975f5c5SAndroid Build Coastguard Worker     if (isSrcColumnMajor)
942*8975f5c5SAndroid Build Coastguard Worker     {
943*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrix<true, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
944*8975f5c5SAndroid Build Coastguard Worker                                                                countIn, value, targetData);
945*8975f5c5SAndroid Build Coastguard Worker     }
946*8975f5c5SAndroid Build Coastguard Worker     else
947*8975f5c5SAndroid Build Coastguard Worker     {
948*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrix<false, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
949*8975f5c5SAndroid Build Coastguard Worker                                                                 countIn, value, targetData);
950*8975f5c5SAndroid Build Coastguard Worker     }
951*8975f5c5SAndroid Build Coastguard Worker }
952*8975f5c5SAndroid Build Coastguard Worker 
953*8975f5c5SAndroid Build Coastguard Worker template <int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)954*8975f5c5SAndroid Build Coastguard Worker void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset,
955*8975f5c5SAndroid Build Coastguard Worker                                              unsigned int elementCount,
956*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei countIn,
957*8975f5c5SAndroid Build Coastguard Worker                                              GLboolean transpose,
958*8975f5c5SAndroid Build Coastguard Worker                                              const GLfloat *value,
959*8975f5c5SAndroid Build Coastguard Worker                                              uint8_t *targetData)
960*8975f5c5SAndroid Build Coastguard Worker {
961*8975f5c5SAndroid Build Coastguard Worker     const bool isSrcColumnMajor = !transpose;
962*8975f5c5SAndroid Build Coastguard Worker     if (!isSrcColumnMajor)
963*8975f5c5SAndroid Build Coastguard Worker     {
964*8975f5c5SAndroid Build Coastguard Worker         // Both src and dst matrixs are has same layout,
965*8975f5c5SAndroid Build Coastguard Worker         // a single memcpy updates all the matrices
966*8975f5c5SAndroid Build Coastguard Worker         constexpr size_t srcMatrixSize = sizeof(GLfloat) * 4 * rows;
967*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
968*8975f5c5SAndroid Build Coastguard Worker                                   targetData);
969*8975f5c5SAndroid Build Coastguard Worker     }
970*8975f5c5SAndroid Build Coastguard Worker     else
971*8975f5c5SAndroid Build Coastguard Worker     {
972*8975f5c5SAndroid Build Coastguard Worker         // fallback to general cases
973*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrix<true, 4, rows, false, 4, rows>(arrayElementOffset, elementCount,
974*8975f5c5SAndroid Build Coastguard Worker                                                              countIn, value, targetData);
975*8975f5c5SAndroid Build Coastguard Worker     }
976*8975f5c5SAndroid Build Coastguard Worker }
977*8975f5c5SAndroid Build Coastguard Worker 
978*8975f5c5SAndroid Build Coastguard Worker template <int cols, int rows>
Run(unsigned int arrayElementOffset,unsigned int elementCount,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData)979*8975f5c5SAndroid Build Coastguard Worker void SetFloatUniformMatrixHLSL<cols, rows>::Run(unsigned int arrayElementOffset,
980*8975f5c5SAndroid Build Coastguard Worker                                                 unsigned int elementCount,
981*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei countIn,
982*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
983*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value,
984*8975f5c5SAndroid Build Coastguard Worker                                                 uint8_t *targetData)
985*8975f5c5SAndroid Build Coastguard Worker {
986*8975f5c5SAndroid Build Coastguard Worker     const bool isSrcColumnMajor = !transpose;
987*8975f5c5SAndroid Build Coastguard Worker     // Internally store matrices as row-major to accomodate HLSL matrix indexing.  Each row is
988*8975f5c5SAndroid Build Coastguard Worker     // padded to 4 columns.
989*8975f5c5SAndroid Build Coastguard Worker     if (!isSrcColumnMajor)
990*8975f5c5SAndroid Build Coastguard Worker     {
991*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrix<false, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
992*8975f5c5SAndroid Build Coastguard Worker                                                                  countIn, value, targetData);
993*8975f5c5SAndroid Build Coastguard Worker     }
994*8975f5c5SAndroid Build Coastguard Worker     else
995*8975f5c5SAndroid Build Coastguard Worker     {
996*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrix<true, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
997*8975f5c5SAndroid Build Coastguard Worker                                                                 countIn, value, targetData);
998*8975f5c5SAndroid Build Coastguard Worker     }
999*8975f5c5SAndroid Build Coastguard Worker }
1000*8975f5c5SAndroid Build Coastguard Worker 
1001*8975f5c5SAndroid Build Coastguard Worker template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
1002*8975f5c5SAndroid Build Coastguard Worker template void GetMatrixUniform<GLuint>(GLenum, GLuint *, const GLuint *, bool);
1003*8975f5c5SAndroid Build Coastguard Worker 
GetMatrixUniform(GLenum type,GLfloat * dataOut,const GLfloat * source,bool transpose)1004*8975f5c5SAndroid Build Coastguard Worker void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose)
1005*8975f5c5SAndroid Build Coastguard Worker {
1006*8975f5c5SAndroid Build Coastguard Worker     int columns = gl::VariableColumnCount(type);
1007*8975f5c5SAndroid Build Coastguard Worker     int rows    = gl::VariableRowCount(type);
1008*8975f5c5SAndroid Build Coastguard Worker     for (GLint col = 0; col < columns; ++col)
1009*8975f5c5SAndroid Build Coastguard Worker     {
1010*8975f5c5SAndroid Build Coastguard Worker         for (GLint row = 0; row < rows; ++row)
1011*8975f5c5SAndroid Build Coastguard Worker         {
1012*8975f5c5SAndroid Build Coastguard Worker             GLfloat *outptr = dataOut + ((col * rows) + row);
1013*8975f5c5SAndroid Build Coastguard Worker             const GLfloat *inptr =
1014*8975f5c5SAndroid Build Coastguard Worker                 transpose ? source + ((row * 4) + col) : source + ((col * 4) + row);
1015*8975f5c5SAndroid Build Coastguard Worker             *outptr = *inptr;
1016*8975f5c5SAndroid Build Coastguard Worker         }
1017*8975f5c5SAndroid Build Coastguard Worker     }
1018*8975f5c5SAndroid Build Coastguard Worker }
1019*8975f5c5SAndroid Build Coastguard Worker 
1020*8975f5c5SAndroid Build Coastguard Worker template <typename NonFloatT>
GetMatrixUniform(GLenum type,NonFloatT * dataOut,const NonFloatT * source,bool transpose)1021*8975f5c5SAndroid Build Coastguard Worker void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose)
1022*8975f5c5SAndroid Build Coastguard Worker {
1023*8975f5c5SAndroid Build Coastguard Worker     UNREACHABLE();
1024*8975f5c5SAndroid Build Coastguard Worker }
1025*8975f5c5SAndroid Build Coastguard Worker 
1026*8975f5c5SAndroid Build Coastguard Worker BufferAndLayout::BufferAndLayout() = default;
1027*8975f5c5SAndroid Build Coastguard Worker 
1028*8975f5c5SAndroid Build Coastguard Worker BufferAndLayout::~BufferAndLayout() = default;
1029*8975f5c5SAndroid Build Coastguard Worker 
1030*8975f5c5SAndroid Build Coastguard Worker template <typename T>
UpdateBufferWithLayout(GLsizei count,uint32_t arrayIndex,int componentCount,const T * v,const sh::BlockMemberInfo & layoutInfo,angle::MemoryBuffer * uniformData)1031*8975f5c5SAndroid Build Coastguard Worker void UpdateBufferWithLayout(GLsizei count,
1032*8975f5c5SAndroid Build Coastguard Worker                             uint32_t arrayIndex,
1033*8975f5c5SAndroid Build Coastguard Worker                             int componentCount,
1034*8975f5c5SAndroid Build Coastguard Worker                             const T *v,
1035*8975f5c5SAndroid Build Coastguard Worker                             const sh::BlockMemberInfo &layoutInfo,
1036*8975f5c5SAndroid Build Coastguard Worker                             angle::MemoryBuffer *uniformData)
1037*8975f5c5SAndroid Build Coastguard Worker {
1038*8975f5c5SAndroid Build Coastguard Worker     const int elementSize = sizeof(T) * componentCount;
1039*8975f5c5SAndroid Build Coastguard Worker 
1040*8975f5c5SAndroid Build Coastguard Worker     uint8_t *dst = uniformData->data() + layoutInfo.offset;
1041*8975f5c5SAndroid Build Coastguard Worker     if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
1042*8975f5c5SAndroid Build Coastguard Worker     {
1043*8975f5c5SAndroid Build Coastguard Worker         uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride;
1044*8975f5c5SAndroid Build Coastguard Worker         uint8_t *writePtr    = dst + arrayOffset;
1045*8975f5c5SAndroid Build Coastguard Worker         ASSERT(writePtr + (elementSize * count) <= uniformData->data() + uniformData->size());
1046*8975f5c5SAndroid Build Coastguard Worker         memcpy(writePtr, v, elementSize * count);
1047*8975f5c5SAndroid Build Coastguard Worker     }
1048*8975f5c5SAndroid Build Coastguard Worker     else
1049*8975f5c5SAndroid Build Coastguard Worker     {
1050*8975f5c5SAndroid Build Coastguard Worker         // Have to respect the arrayStride between each element of the array.
1051*8975f5c5SAndroid Build Coastguard Worker         int maxIndex = arrayIndex + count;
1052*8975f5c5SAndroid Build Coastguard Worker         for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex;
1053*8975f5c5SAndroid Build Coastguard Worker              writeIndex++, readIndex++)
1054*8975f5c5SAndroid Build Coastguard Worker         {
1055*8975f5c5SAndroid Build Coastguard Worker             const int arrayOffset = writeIndex * layoutInfo.arrayStride;
1056*8975f5c5SAndroid Build Coastguard Worker             uint8_t *writePtr     = dst + arrayOffset;
1057*8975f5c5SAndroid Build Coastguard Worker             const T *readPtr      = v + (readIndex * componentCount);
1058*8975f5c5SAndroid Build Coastguard Worker             ASSERT(writePtr + elementSize <= uniformData->data() + uniformData->size());
1059*8975f5c5SAndroid Build Coastguard Worker             memcpy(writePtr, readPtr, elementSize);
1060*8975f5c5SAndroid Build Coastguard Worker         }
1061*8975f5c5SAndroid Build Coastguard Worker     }
1062*8975f5c5SAndroid Build Coastguard Worker }
1063*8975f5c5SAndroid Build Coastguard Worker 
1064*8975f5c5SAndroid Build Coastguard Worker template <typename T>
ReadFromBufferWithLayout(int componentCount,uint32_t arrayIndex,T * dst,const sh::BlockMemberInfo & layoutInfo,const angle::MemoryBuffer * uniformData)1065*8975f5c5SAndroid Build Coastguard Worker void ReadFromBufferWithLayout(int componentCount,
1066*8975f5c5SAndroid Build Coastguard Worker                               uint32_t arrayIndex,
1067*8975f5c5SAndroid Build Coastguard Worker                               T *dst,
1068*8975f5c5SAndroid Build Coastguard Worker                               const sh::BlockMemberInfo &layoutInfo,
1069*8975f5c5SAndroid Build Coastguard Worker                               const angle::MemoryBuffer *uniformData)
1070*8975f5c5SAndroid Build Coastguard Worker {
1071*8975f5c5SAndroid Build Coastguard Worker     ASSERT(layoutInfo.offset != -1);
1072*8975f5c5SAndroid Build Coastguard Worker 
1073*8975f5c5SAndroid Build Coastguard Worker     const int elementSize = sizeof(T) * componentCount;
1074*8975f5c5SAndroid Build Coastguard Worker     const uint8_t *source = uniformData->data() + layoutInfo.offset;
1075*8975f5c5SAndroid Build Coastguard Worker 
1076*8975f5c5SAndroid Build Coastguard Worker     if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
1077*8975f5c5SAndroid Build Coastguard Worker     {
1078*8975f5c5SAndroid Build Coastguard Worker         const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride;
1079*8975f5c5SAndroid Build Coastguard Worker         memcpy(dst, readPtr, elementSize);
1080*8975f5c5SAndroid Build Coastguard Worker     }
1081*8975f5c5SAndroid Build Coastguard Worker     else
1082*8975f5c5SAndroid Build Coastguard Worker     {
1083*8975f5c5SAndroid Build Coastguard Worker         // Have to respect the arrayStride between each element of the array.
1084*8975f5c5SAndroid Build Coastguard Worker         const int arrayOffset  = arrayIndex * layoutInfo.arrayStride;
1085*8975f5c5SAndroid Build Coastguard Worker         const uint8_t *readPtr = source + arrayOffset;
1086*8975f5c5SAndroid Build Coastguard Worker         memcpy(dst, readPtr, elementSize);
1087*8975f5c5SAndroid Build Coastguard Worker     }
1088*8975f5c5SAndroid Build Coastguard Worker }
1089*8975f5c5SAndroid Build Coastguard Worker 
1090*8975f5c5SAndroid Build Coastguard Worker template <typename T>
SetUniform(const gl::ProgramExecutable * executable,GLint location,GLsizei count,const T * v,GLenum entryPointType,DefaultUniformBlockMap * defaultUniformBlocks,gl::ShaderBitSet * defaultUniformBlocksDirty)1091*8975f5c5SAndroid Build Coastguard Worker void SetUniform(const gl::ProgramExecutable *executable,
1092*8975f5c5SAndroid Build Coastguard Worker                 GLint location,
1093*8975f5c5SAndroid Build Coastguard Worker                 GLsizei count,
1094*8975f5c5SAndroid Build Coastguard Worker                 const T *v,
1095*8975f5c5SAndroid Build Coastguard Worker                 GLenum entryPointType,
1096*8975f5c5SAndroid Build Coastguard Worker                 DefaultUniformBlockMap *defaultUniformBlocks,
1097*8975f5c5SAndroid Build Coastguard Worker                 gl::ShaderBitSet *defaultUniformBlocksDirty)
1098*8975f5c5SAndroid Build Coastguard Worker {
1099*8975f5c5SAndroid Build Coastguard Worker     const gl::VariableLocation &locationInfo = executable->getUniformLocations()[location];
1100*8975f5c5SAndroid Build Coastguard Worker     const gl::LinkedUniform &linkedUniform   = executable->getUniforms()[locationInfo.index];
1101*8975f5c5SAndroid Build Coastguard Worker 
1102*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!linkedUniform.isSampler());
1103*8975f5c5SAndroid Build Coastguard Worker 
1104*8975f5c5SAndroid Build Coastguard Worker     if (linkedUniform.getType() == entryPointType)
1105*8975f5c5SAndroid Build Coastguard Worker     {
1106*8975f5c5SAndroid Build Coastguard Worker         for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1107*8975f5c5SAndroid Build Coastguard Worker         {
1108*8975f5c5SAndroid Build Coastguard Worker             BufferAndLayout &uniformBlock         = *(*defaultUniformBlocks)[shaderType];
1109*8975f5c5SAndroid Build Coastguard Worker             const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1110*8975f5c5SAndroid Build Coastguard Worker 
1111*8975f5c5SAndroid Build Coastguard Worker             // Assume an offset of -1 means the block is unused.
1112*8975f5c5SAndroid Build Coastguard Worker             if (layoutInfo.offset == -1)
1113*8975f5c5SAndroid Build Coastguard Worker             {
1114*8975f5c5SAndroid Build Coastguard Worker                 continue;
1115*8975f5c5SAndroid Build Coastguard Worker             }
1116*8975f5c5SAndroid Build Coastguard Worker 
1117*8975f5c5SAndroid Build Coastguard Worker             const GLint componentCount = linkedUniform.getElementComponents();
1118*8975f5c5SAndroid Build Coastguard Worker             UpdateBufferWithLayout(count, locationInfo.arrayIndex, componentCount, v, layoutInfo,
1119*8975f5c5SAndroid Build Coastguard Worker                                    &uniformBlock.uniformData);
1120*8975f5c5SAndroid Build Coastguard Worker             defaultUniformBlocksDirty->set(shaderType);
1121*8975f5c5SAndroid Build Coastguard Worker         }
1122*8975f5c5SAndroid Build Coastguard Worker     }
1123*8975f5c5SAndroid Build Coastguard Worker     else
1124*8975f5c5SAndroid Build Coastguard Worker     {
1125*8975f5c5SAndroid Build Coastguard Worker         for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1126*8975f5c5SAndroid Build Coastguard Worker         {
1127*8975f5c5SAndroid Build Coastguard Worker             BufferAndLayout &uniformBlock         = *(*defaultUniformBlocks)[shaderType];
1128*8975f5c5SAndroid Build Coastguard Worker             const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1129*8975f5c5SAndroid Build Coastguard Worker 
1130*8975f5c5SAndroid Build Coastguard Worker             // Assume an offset of -1 means the block is unused.
1131*8975f5c5SAndroid Build Coastguard Worker             if (layoutInfo.offset == -1)
1132*8975f5c5SAndroid Build Coastguard Worker             {
1133*8975f5c5SAndroid Build Coastguard Worker                 continue;
1134*8975f5c5SAndroid Build Coastguard Worker             }
1135*8975f5c5SAndroid Build Coastguard Worker 
1136*8975f5c5SAndroid Build Coastguard Worker             const GLint componentCount = linkedUniform.getElementComponents();
1137*8975f5c5SAndroid Build Coastguard Worker 
1138*8975f5c5SAndroid Build Coastguard Worker             ASSERT(linkedUniform.getType() == gl::VariableBoolVectorType(entryPointType));
1139*8975f5c5SAndroid Build Coastguard Worker 
1140*8975f5c5SAndroid Build Coastguard Worker             GLint initialArrayOffset =
1141*8975f5c5SAndroid Build Coastguard Worker                 locationInfo.arrayIndex * layoutInfo.arrayStride + layoutInfo.offset;
1142*8975f5c5SAndroid Build Coastguard Worker             for (GLint i = 0; i < count; i++)
1143*8975f5c5SAndroid Build Coastguard Worker             {
1144*8975f5c5SAndroid Build Coastguard Worker                 GLint elementOffset = i * layoutInfo.arrayStride + initialArrayOffset;
1145*8975f5c5SAndroid Build Coastguard Worker                 GLint *dst =
1146*8975f5c5SAndroid Build Coastguard Worker                     reinterpret_cast<GLint *>(uniformBlock.uniformData.data() + elementOffset);
1147*8975f5c5SAndroid Build Coastguard Worker                 const T *source = v + i * componentCount;
1148*8975f5c5SAndroid Build Coastguard Worker 
1149*8975f5c5SAndroid Build Coastguard Worker                 for (int c = 0; c < componentCount; c++)
1150*8975f5c5SAndroid Build Coastguard Worker                 {
1151*8975f5c5SAndroid Build Coastguard Worker                     dst[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
1152*8975f5c5SAndroid Build Coastguard Worker                 }
1153*8975f5c5SAndroid Build Coastguard Worker             }
1154*8975f5c5SAndroid Build Coastguard Worker 
1155*8975f5c5SAndroid Build Coastguard Worker             defaultUniformBlocksDirty->set(shaderType);
1156*8975f5c5SAndroid Build Coastguard Worker         }
1157*8975f5c5SAndroid Build Coastguard Worker     }
1158*8975f5c5SAndroid Build Coastguard Worker }
1159*8975f5c5SAndroid Build Coastguard Worker template void SetUniform<GLint>(const gl::ProgramExecutable *executable,
1160*8975f5c5SAndroid Build Coastguard Worker                                 GLint location,
1161*8975f5c5SAndroid Build Coastguard Worker                                 GLsizei count,
1162*8975f5c5SAndroid Build Coastguard Worker                                 const GLint *v,
1163*8975f5c5SAndroid Build Coastguard Worker                                 GLenum entryPointType,
1164*8975f5c5SAndroid Build Coastguard Worker                                 DefaultUniformBlockMap *defaultUniformBlocks,
1165*8975f5c5SAndroid Build Coastguard Worker                                 gl::ShaderBitSet *defaultUniformBlocksDirty);
1166*8975f5c5SAndroid Build Coastguard Worker template void SetUniform<GLuint>(const gl::ProgramExecutable *executable,
1167*8975f5c5SAndroid Build Coastguard Worker                                  GLint location,
1168*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei count,
1169*8975f5c5SAndroid Build Coastguard Worker                                  const GLuint *v,
1170*8975f5c5SAndroid Build Coastguard Worker                                  GLenum entryPointType,
1171*8975f5c5SAndroid Build Coastguard Worker                                  DefaultUniformBlockMap *defaultUniformBlocks,
1172*8975f5c5SAndroid Build Coastguard Worker                                  gl::ShaderBitSet *defaultUniformBlocksDirty);
1173*8975f5c5SAndroid Build Coastguard Worker template void SetUniform<GLfloat>(const gl::ProgramExecutable *executable,
1174*8975f5c5SAndroid Build Coastguard Worker                                   GLint location,
1175*8975f5c5SAndroid Build Coastguard Worker                                   GLsizei count,
1176*8975f5c5SAndroid Build Coastguard Worker                                   const GLfloat *v,
1177*8975f5c5SAndroid Build Coastguard Worker                                   GLenum entryPointType,
1178*8975f5c5SAndroid Build Coastguard Worker                                   DefaultUniformBlockMap *defaultUniformBlocks,
1179*8975f5c5SAndroid Build Coastguard Worker                                   gl::ShaderBitSet *defaultUniformBlocksDirty);
1180*8975f5c5SAndroid Build Coastguard Worker 
1181*8975f5c5SAndroid Build Coastguard Worker template <int cols, int rows>
SetUniformMatrixfv(const gl::ProgramExecutable * executable,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value,DefaultUniformBlockMap * defaultUniformBlocks,gl::ShaderBitSet * defaultUniformBlocksDirty)1182*8975f5c5SAndroid Build Coastguard Worker void SetUniformMatrixfv(const gl::ProgramExecutable *executable,
1183*8975f5c5SAndroid Build Coastguard Worker                         GLint location,
1184*8975f5c5SAndroid Build Coastguard Worker                         GLsizei count,
1185*8975f5c5SAndroid Build Coastguard Worker                         GLboolean transpose,
1186*8975f5c5SAndroid Build Coastguard Worker                         const GLfloat *value,
1187*8975f5c5SAndroid Build Coastguard Worker                         DefaultUniformBlockMap *defaultUniformBlocks,
1188*8975f5c5SAndroid Build Coastguard Worker                         gl::ShaderBitSet *defaultUniformBlocksDirty)
1189*8975f5c5SAndroid Build Coastguard Worker {
1190*8975f5c5SAndroid Build Coastguard Worker     const gl::VariableLocation &locationInfo = executable->getUniformLocations()[location];
1191*8975f5c5SAndroid Build Coastguard Worker     const gl::LinkedUniform &linkedUniform   = executable->getUniforms()[locationInfo.index];
1192*8975f5c5SAndroid Build Coastguard Worker 
1193*8975f5c5SAndroid Build Coastguard Worker     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1194*8975f5c5SAndroid Build Coastguard Worker     {
1195*8975f5c5SAndroid Build Coastguard Worker         BufferAndLayout &uniformBlock         = *(*defaultUniformBlocks)[shaderType];
1196*8975f5c5SAndroid Build Coastguard Worker         const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1197*8975f5c5SAndroid Build Coastguard Worker 
1198*8975f5c5SAndroid Build Coastguard Worker         // Assume an offset of -1 means the block is unused.
1199*8975f5c5SAndroid Build Coastguard Worker         if (layoutInfo.offset == -1)
1200*8975f5c5SAndroid Build Coastguard Worker         {
1201*8975f5c5SAndroid Build Coastguard Worker             continue;
1202*8975f5c5SAndroid Build Coastguard Worker         }
1203*8975f5c5SAndroid Build Coastguard Worker 
1204*8975f5c5SAndroid Build Coastguard Worker         SetFloatUniformMatrixGLSL<cols, rows>::Run(
1205*8975f5c5SAndroid Build Coastguard Worker             locationInfo.arrayIndex, linkedUniform.getBasicTypeElementCount(), count, transpose,
1206*8975f5c5SAndroid Build Coastguard Worker             value, uniformBlock.uniformData.data() + layoutInfo.offset);
1207*8975f5c5SAndroid Build Coastguard Worker 
1208*8975f5c5SAndroid Build Coastguard Worker         defaultUniformBlocksDirty->set(shaderType);
1209*8975f5c5SAndroid Build Coastguard Worker     }
1210*8975f5c5SAndroid Build Coastguard Worker }
1211*8975f5c5SAndroid Build Coastguard Worker 
1212*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(cols, rows)                                   \
1213*8975f5c5SAndroid Build Coastguard Worker     template void SetUniformMatrixfv<cols, rows>(                                                \
1214*8975f5c5SAndroid Build Coastguard Worker         const gl::ProgramExecutable *executable, GLint location, GLsizei count,                  \
1215*8975f5c5SAndroid Build Coastguard Worker         GLboolean transpose, const GLfloat *value, DefaultUniformBlockMap *defaultUniformBlocks, \
1216*8975f5c5SAndroid Build Coastguard Worker         gl::ShaderBitSet *defaultUniformBlocksDirty)
1217*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(2, 2);
1218*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(2, 3);
1219*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(2, 4);
1220*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(3, 2);
1221*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(3, 3);
1222*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(3, 4);
1223*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(4, 2);
1224*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(4, 3);
1225*8975f5c5SAndroid Build Coastguard Worker ANGLE_SET_UNIFORM_MATRIX_FV_SPECIALIZATION(4, 4);
1226*8975f5c5SAndroid Build Coastguard Worker 
1227*8975f5c5SAndroid Build Coastguard Worker template <typename T>
GetUniform(const gl::ProgramExecutable * executable,GLint location,T * v,GLenum entryPointType,const DefaultUniformBlockMap * defaultUniformBlocks)1228*8975f5c5SAndroid Build Coastguard Worker void GetUniform(const gl::ProgramExecutable *executable,
1229*8975f5c5SAndroid Build Coastguard Worker                 GLint location,
1230*8975f5c5SAndroid Build Coastguard Worker                 T *v,
1231*8975f5c5SAndroid Build Coastguard Worker                 GLenum entryPointType,
1232*8975f5c5SAndroid Build Coastguard Worker                 const DefaultUniformBlockMap *defaultUniformBlocks)
1233*8975f5c5SAndroid Build Coastguard Worker {
1234*8975f5c5SAndroid Build Coastguard Worker     const gl::VariableLocation &locationInfo = executable->getUniformLocations()[location];
1235*8975f5c5SAndroid Build Coastguard Worker     const gl::LinkedUniform &linkedUniform   = executable->getUniforms()[locationInfo.index];
1236*8975f5c5SAndroid Build Coastguard Worker 
1237*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!linkedUniform.isSampler() && !linkedUniform.isImage());
1238*8975f5c5SAndroid Build Coastguard Worker 
1239*8975f5c5SAndroid Build Coastguard Worker     const gl::ShaderType shaderType = linkedUniform.getFirstActiveShaderType();
1240*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shaderType != gl::ShaderType::InvalidEnum);
1241*8975f5c5SAndroid Build Coastguard Worker 
1242*8975f5c5SAndroid Build Coastguard Worker     const BufferAndLayout &uniformBlock   = *(*defaultUniformBlocks)[shaderType];
1243*8975f5c5SAndroid Build Coastguard Worker     const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1244*8975f5c5SAndroid Build Coastguard Worker 
1245*8975f5c5SAndroid Build Coastguard Worker     ASSERT(linkedUniform.getUniformTypeInfo().componentType == entryPointType ||
1246*8975f5c5SAndroid Build Coastguard Worker            linkedUniform.getUniformTypeInfo().componentType ==
1247*8975f5c5SAndroid Build Coastguard Worker                gl::VariableBoolVectorType(entryPointType));
1248*8975f5c5SAndroid Build Coastguard Worker 
1249*8975f5c5SAndroid Build Coastguard Worker     if (gl::IsMatrixType(linkedUniform.getType()))
1250*8975f5c5SAndroid Build Coastguard Worker     {
1251*8975f5c5SAndroid Build Coastguard Worker         const uint8_t *ptrToElement = uniformBlock.uniformData.data() + layoutInfo.offset +
1252*8975f5c5SAndroid Build Coastguard Worker                                       (locationInfo.arrayIndex * layoutInfo.arrayStride);
1253*8975f5c5SAndroid Build Coastguard Worker         GetMatrixUniform(linkedUniform.getType(), v, reinterpret_cast<const T *>(ptrToElement),
1254*8975f5c5SAndroid Build Coastguard Worker                          false);
1255*8975f5c5SAndroid Build Coastguard Worker     }
1256*8975f5c5SAndroid Build Coastguard Worker     else
1257*8975f5c5SAndroid Build Coastguard Worker     {
1258*8975f5c5SAndroid Build Coastguard Worker         ReadFromBufferWithLayout(linkedUniform.getElementComponents(), locationInfo.arrayIndex, v,
1259*8975f5c5SAndroid Build Coastguard Worker                                  layoutInfo, &uniformBlock.uniformData);
1260*8975f5c5SAndroid Build Coastguard Worker     }
1261*8975f5c5SAndroid Build Coastguard Worker }
1262*8975f5c5SAndroid Build Coastguard Worker 
1263*8975f5c5SAndroid Build Coastguard Worker template void GetUniform<GLint>(const gl::ProgramExecutable *executable,
1264*8975f5c5SAndroid Build Coastguard Worker                                 GLint location,
1265*8975f5c5SAndroid Build Coastguard Worker                                 GLint *v,
1266*8975f5c5SAndroid Build Coastguard Worker                                 GLenum entryPointType,
1267*8975f5c5SAndroid Build Coastguard Worker                                 const DefaultUniformBlockMap *defaultUniformBlocks);
1268*8975f5c5SAndroid Build Coastguard Worker template void GetUniform<GLuint>(const gl::ProgramExecutable *executable,
1269*8975f5c5SAndroid Build Coastguard Worker                                  GLint location,
1270*8975f5c5SAndroid Build Coastguard Worker                                  GLuint *v,
1271*8975f5c5SAndroid Build Coastguard Worker                                  GLenum entryPointType,
1272*8975f5c5SAndroid Build Coastguard Worker                                  const DefaultUniformBlockMap *defaultUniformBlocks);
1273*8975f5c5SAndroid Build Coastguard Worker template void GetUniform<GLfloat>(const gl::ProgramExecutable *executable,
1274*8975f5c5SAndroid Build Coastguard Worker                                   GLint location,
1275*8975f5c5SAndroid Build Coastguard Worker                                   GLfloat *v,
1276*8975f5c5SAndroid Build Coastguard Worker                                   GLenum entryPointType,
1277*8975f5c5SAndroid Build Coastguard Worker                                   const DefaultUniformBlockMap *defaultUniformBlocks);
1278*8975f5c5SAndroid Build Coastguard Worker 
GetFormatFromFormatType(GLenum format,GLenum type)1279*8975f5c5SAndroid Build Coastguard Worker const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type)
1280*8975f5c5SAndroid Build Coastguard Worker {
1281*8975f5c5SAndroid Build Coastguard Worker     GLenum sizedInternalFormat    = gl::GetInternalFormatInfo(format, type).sizedInternalFormat;
1282*8975f5c5SAndroid Build Coastguard Worker     angle::FormatID angleFormatID = angle::Format::InternalFormatToID(sizedInternalFormat);
1283*8975f5c5SAndroid Build Coastguard Worker     return angle::Format::Get(angleFormatID);
1284*8975f5c5SAndroid Build Coastguard Worker }
1285*8975f5c5SAndroid Build Coastguard Worker 
ComputeStartVertex(ContextImpl * contextImpl,const gl::IndexRange & indexRange,GLint baseVertex,GLint * firstVertexOut)1286*8975f5c5SAndroid Build Coastguard Worker angle::Result ComputeStartVertex(ContextImpl *contextImpl,
1287*8975f5c5SAndroid Build Coastguard Worker                                  const gl::IndexRange &indexRange,
1288*8975f5c5SAndroid Build Coastguard Worker                                  GLint baseVertex,
1289*8975f5c5SAndroid Build Coastguard Worker                                  GLint *firstVertexOut)
1290*8975f5c5SAndroid Build Coastguard Worker {
1291*8975f5c5SAndroid Build Coastguard Worker     // The entire index range should be within the limits of a 32-bit uint because the largest
1292*8975f5c5SAndroid Build Coastguard Worker     // GL index type is GL_UNSIGNED_INT.
1293*8975f5c5SAndroid Build Coastguard Worker     ASSERT(indexRange.start <= std::numeric_limits<uint32_t>::max() &&
1294*8975f5c5SAndroid Build Coastguard Worker            indexRange.end <= std::numeric_limits<uint32_t>::max());
1295*8975f5c5SAndroid Build Coastguard Worker 
1296*8975f5c5SAndroid Build Coastguard Worker     // The base vertex is only used in DrawElementsIndirect. Given the assertion above and the
1297*8975f5c5SAndroid Build Coastguard Worker     // type of mBaseVertex (GLint), adding them both as 64-bit ints is safe.
1298*8975f5c5SAndroid Build Coastguard Worker     int64_t startVertexInt64 =
1299*8975f5c5SAndroid Build Coastguard Worker         static_cast<int64_t>(baseVertex) + static_cast<int64_t>(indexRange.start);
1300*8975f5c5SAndroid Build Coastguard Worker 
1301*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.2 spec section 10.5: "Behavior of DrawElementsOneInstance is undefined if the
1302*8975f5c5SAndroid Build Coastguard Worker     // vertex ID is negative for any element"
1303*8975f5c5SAndroid Build Coastguard Worker     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 >= 0);
1304*8975f5c5SAndroid Build Coastguard Worker 
1305*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.2 spec section 10.5: "If the vertex ID is larger than the maximum value
1306*8975f5c5SAndroid Build Coastguard Worker     // representable by type, it should behave as if the calculation were upconverted to 32-bit
1307*8975f5c5SAndroid Build Coastguard Worker     // unsigned integers(with wrapping on overflow conditions)." ANGLE does not fully handle
1308*8975f5c5SAndroid Build Coastguard Worker     // these rules, an overflow error is returned if the start vertex cannot be stored in a
1309*8975f5c5SAndroid Build Coastguard Worker     // 32-bit signed integer.
1310*8975f5c5SAndroid Build Coastguard Worker     ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max());
1311*8975f5c5SAndroid Build Coastguard Worker 
1312*8975f5c5SAndroid Build Coastguard Worker     *firstVertexOut = static_cast<GLint>(startVertexInt64);
1313*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1314*8975f5c5SAndroid Build Coastguard Worker }
1315*8975f5c5SAndroid Build Coastguard Worker 
GetVertexRangeInfo(const gl::Context * context,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLint baseVertex,GLint * startVertexOut,size_t * vertexCountOut)1316*8975f5c5SAndroid Build Coastguard Worker angle::Result GetVertexRangeInfo(const gl::Context *context,
1317*8975f5c5SAndroid Build Coastguard Worker                                  GLint firstVertex,
1318*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei vertexOrIndexCount,
1319*8975f5c5SAndroid Build Coastguard Worker                                  gl::DrawElementsType indexTypeOrInvalid,
1320*8975f5c5SAndroid Build Coastguard Worker                                  const void *indices,
1321*8975f5c5SAndroid Build Coastguard Worker                                  GLint baseVertex,
1322*8975f5c5SAndroid Build Coastguard Worker                                  GLint *startVertexOut,
1323*8975f5c5SAndroid Build Coastguard Worker                                  size_t *vertexCountOut)
1324*8975f5c5SAndroid Build Coastguard Worker {
1325*8975f5c5SAndroid Build Coastguard Worker     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
1326*8975f5c5SAndroid Build Coastguard Worker     {
1327*8975f5c5SAndroid Build Coastguard Worker         gl::IndexRange indexRange;
1328*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
1329*8975f5c5SAndroid Build Coastguard Worker             context, indexTypeOrInvalid, vertexOrIndexCount, indices, &indexRange));
1330*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ComputeStartVertex(context->getImplementation(), indexRange, baseVertex,
1331*8975f5c5SAndroid Build Coastguard Worker                                      startVertexOut));
1332*8975f5c5SAndroid Build Coastguard Worker         *vertexCountOut = indexRange.vertexCount();
1333*8975f5c5SAndroid Build Coastguard Worker     }
1334*8975f5c5SAndroid Build Coastguard Worker     else
1335*8975f5c5SAndroid Build Coastguard Worker     {
1336*8975f5c5SAndroid Build Coastguard Worker         *startVertexOut = firstVertex;
1337*8975f5c5SAndroid Build Coastguard Worker         *vertexCountOut = vertexOrIndexCount;
1338*8975f5c5SAndroid Build Coastguard Worker     }
1339*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1340*8975f5c5SAndroid Build Coastguard Worker }
1341*8975f5c5SAndroid Build Coastguard Worker 
ClipRectToScissor(const gl::State & glState,const gl::Rectangle & rect,bool invertY)1342*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY)
1343*8975f5c5SAndroid Build Coastguard Worker {
1344*8975f5c5SAndroid Build Coastguard Worker     // If the scissor test isn't enabled, assume it has infinite size.  Its intersection with the
1345*8975f5c5SAndroid Build Coastguard Worker     // rect would be the rect itself.
1346*8975f5c5SAndroid Build Coastguard Worker     //
1347*8975f5c5SAndroid Build Coastguard Worker     // Note that on Vulkan, returning this (as opposed to a fixed max-int-sized rect) could lead to
1348*8975f5c5SAndroid Build Coastguard Worker     // unnecessary pipeline creations if two otherwise identical pipelines are used on framebuffers
1349*8975f5c5SAndroid Build Coastguard Worker     // with different sizes.  If such usage is observed in an application, we should investigate
1350*8975f5c5SAndroid Build Coastguard Worker     // possible optimizations.
1351*8975f5c5SAndroid Build Coastguard Worker     if (!glState.isScissorTestEnabled())
1352*8975f5c5SAndroid Build Coastguard Worker     {
1353*8975f5c5SAndroid Build Coastguard Worker         return rect;
1354*8975f5c5SAndroid Build Coastguard Worker     }
1355*8975f5c5SAndroid Build Coastguard Worker 
1356*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle clippedRect;
1357*8975f5c5SAndroid Build Coastguard Worker     if (!gl::ClipRectangle(glState.getScissor(), rect, &clippedRect))
1358*8975f5c5SAndroid Build Coastguard Worker     {
1359*8975f5c5SAndroid Build Coastguard Worker         return gl::Rectangle();
1360*8975f5c5SAndroid Build Coastguard Worker     }
1361*8975f5c5SAndroid Build Coastguard Worker 
1362*8975f5c5SAndroid Build Coastguard Worker     if (invertY)
1363*8975f5c5SAndroid Build Coastguard Worker     {
1364*8975f5c5SAndroid Build Coastguard Worker         clippedRect.y = rect.height - clippedRect.y - clippedRect.height;
1365*8975f5c5SAndroid Build Coastguard Worker     }
1366*8975f5c5SAndroid Build Coastguard Worker 
1367*8975f5c5SAndroid Build Coastguard Worker     return clippedRect;
1368*8975f5c5SAndroid Build Coastguard Worker }
1369*8975f5c5SAndroid Build Coastguard Worker 
LogFeatureStatus(const angle::FeatureSetBase & features,const std::vector<std::string> & featureNames,bool enabled)1370*8975f5c5SAndroid Build Coastguard Worker void LogFeatureStatus(const angle::FeatureSetBase &features,
1371*8975f5c5SAndroid Build Coastguard Worker                       const std::vector<std::string> &featureNames,
1372*8975f5c5SAndroid Build Coastguard Worker                       bool enabled)
1373*8975f5c5SAndroid Build Coastguard Worker {
1374*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &name : featureNames)
1375*8975f5c5SAndroid Build Coastguard Worker     {
1376*8975f5c5SAndroid Build Coastguard Worker         const bool hasWildcard = name.back() == '*';
1377*8975f5c5SAndroid Build Coastguard Worker         for (auto iter : features.getFeatures())
1378*8975f5c5SAndroid Build Coastguard Worker         {
1379*8975f5c5SAndroid Build Coastguard Worker             const std::string &featureName = iter.first;
1380*8975f5c5SAndroid Build Coastguard Worker 
1381*8975f5c5SAndroid Build Coastguard Worker             if (!angle::FeatureNameMatch(featureName, name))
1382*8975f5c5SAndroid Build Coastguard Worker             {
1383*8975f5c5SAndroid Build Coastguard Worker                 continue;
1384*8975f5c5SAndroid Build Coastguard Worker             }
1385*8975f5c5SAndroid Build Coastguard Worker 
1386*8975f5c5SAndroid Build Coastguard Worker             INFO() << "Feature: " << featureName << (enabled ? " enabled" : " disabled");
1387*8975f5c5SAndroid Build Coastguard Worker 
1388*8975f5c5SAndroid Build Coastguard Worker             if (!hasWildcard)
1389*8975f5c5SAndroid Build Coastguard Worker             {
1390*8975f5c5SAndroid Build Coastguard Worker                 break;
1391*8975f5c5SAndroid Build Coastguard Worker             }
1392*8975f5c5SAndroid Build Coastguard Worker         }
1393*8975f5c5SAndroid Build Coastguard Worker     }
1394*8975f5c5SAndroid Build Coastguard Worker }
1395*8975f5c5SAndroid Build Coastguard Worker 
ApplyFeatureOverrides(angle::FeatureSetBase * features,const angle::FeatureOverrides & overrides)1396*8975f5c5SAndroid Build Coastguard Worker void ApplyFeatureOverrides(angle::FeatureSetBase *features,
1397*8975f5c5SAndroid Build Coastguard Worker                            const angle::FeatureOverrides &overrides)
1398*8975f5c5SAndroid Build Coastguard Worker {
1399*8975f5c5SAndroid Build Coastguard Worker     features->overrideFeatures(overrides.enabled, true);
1400*8975f5c5SAndroid Build Coastguard Worker     features->overrideFeatures(overrides.disabled, false);
1401*8975f5c5SAndroid Build Coastguard Worker 
1402*8975f5c5SAndroid Build Coastguard Worker     // Override with environment as well.
1403*8975f5c5SAndroid Build Coastguard Worker     constexpr char kAngleFeatureOverridesEnabledEnvName[]  = "ANGLE_FEATURE_OVERRIDES_ENABLED";
1404*8975f5c5SAndroid Build Coastguard Worker     constexpr char kAngleFeatureOverridesDisabledEnvName[] = "ANGLE_FEATURE_OVERRIDES_DISABLED";
1405*8975f5c5SAndroid Build Coastguard Worker     constexpr char kAngleFeatureOverridesEnabledPropertyName[] =
1406*8975f5c5SAndroid Build Coastguard Worker         "debug.angle.feature_overrides_enabled";
1407*8975f5c5SAndroid Build Coastguard Worker     constexpr char kAngleFeatureOverridesDisabledPropertyName[] =
1408*8975f5c5SAndroid Build Coastguard Worker         "debug.angle.feature_overrides_disabled";
1409*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> overridesEnabled =
1410*8975f5c5SAndroid Build Coastguard Worker         angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
1411*8975f5c5SAndroid Build Coastguard Worker             kAngleFeatureOverridesEnabledEnvName, kAngleFeatureOverridesEnabledPropertyName, ":");
1412*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> overridesDisabled =
1413*8975f5c5SAndroid Build Coastguard Worker         angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
1414*8975f5c5SAndroid Build Coastguard Worker             kAngleFeatureOverridesDisabledEnvName, kAngleFeatureOverridesDisabledPropertyName, ":");
1415*8975f5c5SAndroid Build Coastguard Worker 
1416*8975f5c5SAndroid Build Coastguard Worker     features->overrideFeatures(overridesEnabled, true);
1417*8975f5c5SAndroid Build Coastguard Worker     LogFeatureStatus(*features, overridesEnabled, true);
1418*8975f5c5SAndroid Build Coastguard Worker 
1419*8975f5c5SAndroid Build Coastguard Worker     features->overrideFeatures(overridesDisabled, false);
1420*8975f5c5SAndroid Build Coastguard Worker     LogFeatureStatus(*features, overridesDisabled, false);
1421*8975f5c5SAndroid Build Coastguard Worker }
1422*8975f5c5SAndroid Build Coastguard Worker 
GetSamplePosition(GLsizei sampleCount,size_t index,GLfloat * xy)1423*8975f5c5SAndroid Build Coastguard Worker void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
1424*8975f5c5SAndroid Build Coastguard Worker {
1425*8975f5c5SAndroid Build Coastguard Worker     ASSERT(gl::isPow2(sampleCount));
1426*8975f5c5SAndroid Build Coastguard Worker     if (sampleCount > 16)
1427*8975f5c5SAndroid Build Coastguard Worker     {
1428*8975f5c5SAndroid Build Coastguard Worker         // Vulkan (and D3D11) doesn't have standard sample positions for 32 and 64 samples (and no
1429*8975f5c5SAndroid Build Coastguard Worker         // drivers are known to support that many samples)
1430*8975f5c5SAndroid Build Coastguard Worker         xy[0] = 0.5f;
1431*8975f5c5SAndroid Build Coastguard Worker         xy[1] = 0.5f;
1432*8975f5c5SAndroid Build Coastguard Worker     }
1433*8975f5c5SAndroid Build Coastguard Worker     else
1434*8975f5c5SAndroid Build Coastguard Worker     {
1435*8975f5c5SAndroid Build Coastguard Worker         size_t indexKey = static_cast<size_t>(gl::log2(sampleCount));
1436*8975f5c5SAndroid Build Coastguard Worker         ASSERT(indexKey < kSamplePositions.size() &&
1437*8975f5c5SAndroid Build Coastguard Worker                (2 * index + 1) < kSamplePositions[indexKey].size());
1438*8975f5c5SAndroid Build Coastguard Worker 
1439*8975f5c5SAndroid Build Coastguard Worker         xy[0] = kSamplePositions[indexKey][2 * index];
1440*8975f5c5SAndroid Build Coastguard Worker         xy[1] = kSamplePositions[indexKey][2 * index + 1];
1441*8975f5c5SAndroid Build Coastguard Worker     }
1442*8975f5c5SAndroid Build Coastguard Worker }
1443*8975f5c5SAndroid Build Coastguard Worker 
1444*8975f5c5SAndroid Build Coastguard Worker // These macros are to avoid code too much duplication for variations of multi draw types
1445*8975f5c5SAndroid Build Coastguard Worker #define DRAW_ARRAYS__ contextImpl->drawArrays(context, mode, firsts[drawID], counts[drawID])
1446*8975f5c5SAndroid Build Coastguard Worker #define DRAW_ARRAYS_INSTANCED_                                                      \
1447*8975f5c5SAndroid Build Coastguard Worker     contextImpl->drawArraysInstanced(context, mode, firsts[drawID], counts[drawID], \
1448*8975f5c5SAndroid Build Coastguard Worker                                      instanceCounts[drawID])
1449*8975f5c5SAndroid Build Coastguard Worker #define DRAW_ELEMENTS__ \
1450*8975f5c5SAndroid Build Coastguard Worker     contextImpl->drawElements(context, mode, counts[drawID], type, indices[drawID])
1451*8975f5c5SAndroid Build Coastguard Worker #define DRAW_ELEMENTS_INSTANCED_                                                             \
1452*8975f5c5SAndroid Build Coastguard Worker     contextImpl->drawElementsInstanced(context, mode, counts[drawID], type, indices[drawID], \
1453*8975f5c5SAndroid Build Coastguard Worker                                        instanceCounts[drawID])
1454*8975f5c5SAndroid Build Coastguard Worker #define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE                                                     \
1455*8975f5c5SAndroid Build Coastguard Worker     contextImpl->drawArraysInstancedBaseInstance(context, mode, firsts[drawID], counts[drawID], \
1456*8975f5c5SAndroid Build Coastguard Worker                                                  instanceCounts[drawID], baseInstances[drawID])
1457*8975f5c5SAndroid Build Coastguard Worker #define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE                             \
1458*8975f5c5SAndroid Build Coastguard Worker     contextImpl->drawElementsInstancedBaseVertexBaseInstance(                         \
1459*8975f5c5SAndroid Build Coastguard Worker         context, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID], \
1460*8975f5c5SAndroid Build Coastguard Worker         baseVertices[drawID], baseInstances[drawID])
1461*8975f5c5SAndroid Build Coastguard Worker #define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
1462*8975f5c5SAndroid Build Coastguard Worker 
1463*8975f5c5SAndroid Build Coastguard Worker #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
1464*8975f5c5SAndroid Build Coastguard Worker     do                                                                                         \
1465*8975f5c5SAndroid Build Coastguard Worker     {                                                                                          \
1466*8975f5c5SAndroid Build Coastguard Worker         for (GLsizei drawID = 0; drawID < drawcount; ++drawID)                                 \
1467*8975f5c5SAndroid Build Coastguard Worker         {                                                                                      \
1468*8975f5c5SAndroid Build Coastguard Worker             if (ANGLE_NOOP_DRAW(instanced))                                                    \
1469*8975f5c5SAndroid Build Coastguard Worker             {                                                                                  \
1470*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(contextImpl->handleNoopDrawEvent());                                 \
1471*8975f5c5SAndroid Build Coastguard Worker                 continue;                                                                      \
1472*8975f5c5SAndroid Build Coastguard Worker             }                                                                                  \
1473*8975f5c5SAndroid Build Coastguard Worker             ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID);                                      \
1474*8975f5c5SAndroid Build Coastguard Worker             ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]);                \
1475*8975f5c5SAndroid Build Coastguard Worker             ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]);           \
1476*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi));                                   \
1477*8975f5c5SAndroid Build Coastguard Worker             ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced);                                    \
1478*8975f5c5SAndroid Build Coastguard Worker             gl::MarkShaderStorageUsage(context);                                               \
1479*8975f5c5SAndroid Build Coastguard Worker         }                                                                                      \
1480*8975f5c5SAndroid Build Coastguard Worker         /* reset the uniform to zero for non-multi-draw uses of the program */                 \
1481*8975f5c5SAndroid Build Coastguard Worker         ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(0);                                               \
1482*8975f5c5SAndroid Build Coastguard Worker     } while (0)
1483*8975f5c5SAndroid Build Coastguard Worker 
MultiDrawArraysGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)1484*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
1485*8975f5c5SAndroid Build Coastguard Worker                                      const gl::Context *context,
1486*8975f5c5SAndroid Build Coastguard Worker                                      gl::PrimitiveMode mode,
1487*8975f5c5SAndroid Build Coastguard Worker                                      const GLint *firsts,
1488*8975f5c5SAndroid Build Coastguard Worker                                      const GLsizei *counts,
1489*8975f5c5SAndroid Build Coastguard Worker                                      GLsizei drawcount)
1490*8975f5c5SAndroid Build Coastguard Worker {
1491*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
1492*8975f5c5SAndroid Build Coastguard Worker     const bool hasDrawID              = executable->hasDrawIDUniform();
1493*8975f5c5SAndroid Build Coastguard Worker     if (hasDrawID)
1494*8975f5c5SAndroid Build Coastguard Worker     {
1495*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0);
1496*8975f5c5SAndroid Build Coastguard Worker     }
1497*8975f5c5SAndroid Build Coastguard Worker     else
1498*8975f5c5SAndroid Build Coastguard Worker     {
1499*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0);
1500*8975f5c5SAndroid Build Coastguard Worker     }
1501*8975f5c5SAndroid Build Coastguard Worker 
1502*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1503*8975f5c5SAndroid Build Coastguard Worker }
1504*8975f5c5SAndroid Build Coastguard Worker 
MultiDrawArraysIndirectGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)1505*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawArraysIndirectGeneral(ContextImpl *contextImpl,
1506*8975f5c5SAndroid Build Coastguard Worker                                              const gl::Context *context,
1507*8975f5c5SAndroid Build Coastguard Worker                                              gl::PrimitiveMode mode,
1508*8975f5c5SAndroid Build Coastguard Worker                                              const void *indirect,
1509*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei drawcount,
1510*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei stride)
1511*8975f5c5SAndroid Build Coastguard Worker {
1512*8975f5c5SAndroid Build Coastguard Worker     const GLubyte *indirectPtr = static_cast<const GLubyte *>(indirect);
1513*8975f5c5SAndroid Build Coastguard Worker 
1514*8975f5c5SAndroid Build Coastguard Worker     for (auto count = 0; count < drawcount; count++)
1515*8975f5c5SAndroid Build Coastguard Worker     {
1516*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextImpl->drawArraysIndirect(
1517*8975f5c5SAndroid Build Coastguard Worker             context, mode, reinterpret_cast<const gl::DrawArraysIndirectCommand *>(indirectPtr)));
1518*8975f5c5SAndroid Build Coastguard Worker         if (stride == 0)
1519*8975f5c5SAndroid Build Coastguard Worker         {
1520*8975f5c5SAndroid Build Coastguard Worker             indirectPtr += sizeof(gl::DrawArraysIndirectCommand);
1521*8975f5c5SAndroid Build Coastguard Worker         }
1522*8975f5c5SAndroid Build Coastguard Worker         else
1523*8975f5c5SAndroid Build Coastguard Worker         {
1524*8975f5c5SAndroid Build Coastguard Worker             indirectPtr += stride;
1525*8975f5c5SAndroid Build Coastguard Worker         }
1526*8975f5c5SAndroid Build Coastguard Worker     }
1527*8975f5c5SAndroid Build Coastguard Worker 
1528*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1529*8975f5c5SAndroid Build Coastguard Worker }
1530*8975f5c5SAndroid Build Coastguard Worker 
MultiDrawArraysInstancedGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)1531*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
1532*8975f5c5SAndroid Build Coastguard Worker                                               const gl::Context *context,
1533*8975f5c5SAndroid Build Coastguard Worker                                               gl::PrimitiveMode mode,
1534*8975f5c5SAndroid Build Coastguard Worker                                               const GLint *firsts,
1535*8975f5c5SAndroid Build Coastguard Worker                                               const GLsizei *counts,
1536*8975f5c5SAndroid Build Coastguard Worker                                               const GLsizei *instanceCounts,
1537*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei drawcount)
1538*8975f5c5SAndroid Build Coastguard Worker {
1539*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
1540*8975f5c5SAndroid Build Coastguard Worker     const bool hasDrawID              = executable->hasDrawIDUniform();
1541*8975f5c5SAndroid Build Coastguard Worker     if (hasDrawID)
1542*8975f5c5SAndroid Build Coastguard Worker     {
1543*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0);
1544*8975f5c5SAndroid Build Coastguard Worker     }
1545*8975f5c5SAndroid Build Coastguard Worker     else
1546*8975f5c5SAndroid Build Coastguard Worker     {
1547*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0);
1548*8975f5c5SAndroid Build Coastguard Worker     }
1549*8975f5c5SAndroid Build Coastguard Worker 
1550*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1551*8975f5c5SAndroid Build Coastguard Worker }
1552*8975f5c5SAndroid Build Coastguard Worker 
MultiDrawElementsGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)1553*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
1554*8975f5c5SAndroid Build Coastguard Worker                                        const gl::Context *context,
1555*8975f5c5SAndroid Build Coastguard Worker                                        gl::PrimitiveMode mode,
1556*8975f5c5SAndroid Build Coastguard Worker                                        const GLsizei *counts,
1557*8975f5c5SAndroid Build Coastguard Worker                                        gl::DrawElementsType type,
1558*8975f5c5SAndroid Build Coastguard Worker                                        const GLvoid *const *indices,
1559*8975f5c5SAndroid Build Coastguard Worker                                        GLsizei drawcount)
1560*8975f5c5SAndroid Build Coastguard Worker {
1561*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
1562*8975f5c5SAndroid Build Coastguard Worker     const bool hasDrawID              = executable->hasDrawIDUniform();
1563*8975f5c5SAndroid Build Coastguard Worker     if (hasDrawID)
1564*8975f5c5SAndroid Build Coastguard Worker     {
1565*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0);
1566*8975f5c5SAndroid Build Coastguard Worker     }
1567*8975f5c5SAndroid Build Coastguard Worker     else
1568*8975f5c5SAndroid Build Coastguard Worker     {
1569*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0);
1570*8975f5c5SAndroid Build Coastguard Worker     }
1571*8975f5c5SAndroid Build Coastguard Worker 
1572*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1573*8975f5c5SAndroid Build Coastguard Worker }
1574*8975f5c5SAndroid Build Coastguard Worker 
MultiDrawElementsIndirectGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)1575*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawElementsIndirectGeneral(ContextImpl *contextImpl,
1576*8975f5c5SAndroid Build Coastguard Worker                                                const gl::Context *context,
1577*8975f5c5SAndroid Build Coastguard Worker                                                gl::PrimitiveMode mode,
1578*8975f5c5SAndroid Build Coastguard Worker                                                gl::DrawElementsType type,
1579*8975f5c5SAndroid Build Coastguard Worker                                                const void *indirect,
1580*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei drawcount,
1581*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei stride)
1582*8975f5c5SAndroid Build Coastguard Worker {
1583*8975f5c5SAndroid Build Coastguard Worker     const GLubyte *indirectPtr = static_cast<const GLubyte *>(indirect);
1584*8975f5c5SAndroid Build Coastguard Worker 
1585*8975f5c5SAndroid Build Coastguard Worker     for (auto count = 0; count < drawcount; count++)
1586*8975f5c5SAndroid Build Coastguard Worker     {
1587*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextImpl->drawElementsIndirect(
1588*8975f5c5SAndroid Build Coastguard Worker             context, mode, type,
1589*8975f5c5SAndroid Build Coastguard Worker             reinterpret_cast<const gl::DrawElementsIndirectCommand *>(indirectPtr)));
1590*8975f5c5SAndroid Build Coastguard Worker         if (stride == 0)
1591*8975f5c5SAndroid Build Coastguard Worker         {
1592*8975f5c5SAndroid Build Coastguard Worker             indirectPtr += sizeof(gl::DrawElementsIndirectCommand);
1593*8975f5c5SAndroid Build Coastguard Worker         }
1594*8975f5c5SAndroid Build Coastguard Worker         else
1595*8975f5c5SAndroid Build Coastguard Worker         {
1596*8975f5c5SAndroid Build Coastguard Worker             indirectPtr += stride;
1597*8975f5c5SAndroid Build Coastguard Worker         }
1598*8975f5c5SAndroid Build Coastguard Worker     }
1599*8975f5c5SAndroid Build Coastguard Worker 
1600*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1601*8975f5c5SAndroid Build Coastguard Worker }
1602*8975f5c5SAndroid Build Coastguard Worker 
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)1603*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
1604*8975f5c5SAndroid Build Coastguard Worker                                                 const gl::Context *context,
1605*8975f5c5SAndroid Build Coastguard Worker                                                 gl::PrimitiveMode mode,
1606*8975f5c5SAndroid Build Coastguard Worker                                                 const GLsizei *counts,
1607*8975f5c5SAndroid Build Coastguard Worker                                                 gl::DrawElementsType type,
1608*8975f5c5SAndroid Build Coastguard Worker                                                 const GLvoid *const *indices,
1609*8975f5c5SAndroid Build Coastguard Worker                                                 const GLsizei *instanceCounts,
1610*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei drawcount)
1611*8975f5c5SAndroid Build Coastguard Worker {
1612*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
1613*8975f5c5SAndroid Build Coastguard Worker     const bool hasDrawID              = executable->hasDrawIDUniform();
1614*8975f5c5SAndroid Build Coastguard Worker     if (hasDrawID)
1615*8975f5c5SAndroid Build Coastguard Worker     {
1616*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0);
1617*8975f5c5SAndroid Build Coastguard Worker     }
1618*8975f5c5SAndroid Build Coastguard Worker     else
1619*8975f5c5SAndroid Build Coastguard Worker     {
1620*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0);
1621*8975f5c5SAndroid Build Coastguard Worker     }
1622*8975f5c5SAndroid Build Coastguard Worker 
1623*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1624*8975f5c5SAndroid Build Coastguard Worker }
1625*8975f5c5SAndroid Build Coastguard Worker 
MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl * contextImpl,const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)1626*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
1627*8975f5c5SAndroid Build Coastguard Worker                                                           const gl::Context *context,
1628*8975f5c5SAndroid Build Coastguard Worker                                                           gl::PrimitiveMode mode,
1629*8975f5c5SAndroid Build Coastguard Worker                                                           const GLint *firsts,
1630*8975f5c5SAndroid Build Coastguard Worker                                                           const GLsizei *counts,
1631*8975f5c5SAndroid Build Coastguard Worker                                                           const GLsizei *instanceCounts,
1632*8975f5c5SAndroid Build Coastguard Worker                                                           const GLuint *baseInstances,
1633*8975f5c5SAndroid Build Coastguard Worker                                                           GLsizei drawcount)
1634*8975f5c5SAndroid Build Coastguard Worker {
1635*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
1636*8975f5c5SAndroid Build Coastguard Worker     const bool hasDrawID              = executable->hasDrawIDUniform();
1637*8975f5c5SAndroid Build Coastguard Worker     const bool hasBaseInstance        = executable->hasBaseInstanceUniform();
1638*8975f5c5SAndroid Build Coastguard Worker     ResetBaseVertexBaseInstance resetUniforms(executable, false, hasBaseInstance);
1639*8975f5c5SAndroid Build Coastguard Worker 
1640*8975f5c5SAndroid Build Coastguard Worker     if (hasDrawID && hasBaseInstance)
1641*8975f5c5SAndroid Build Coastguard Worker     {
1642*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1);
1643*8975f5c5SAndroid Build Coastguard Worker     }
1644*8975f5c5SAndroid Build Coastguard Worker     else if (hasDrawID)
1645*8975f5c5SAndroid Build Coastguard Worker     {
1646*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0);
1647*8975f5c5SAndroid Build Coastguard Worker     }
1648*8975f5c5SAndroid Build Coastguard Worker     else if (hasBaseInstance)
1649*8975f5c5SAndroid Build Coastguard Worker     {
1650*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1);
1651*8975f5c5SAndroid Build Coastguard Worker     }
1652*8975f5c5SAndroid Build Coastguard Worker     else
1653*8975f5c5SAndroid Build Coastguard Worker     {
1654*8975f5c5SAndroid Build Coastguard Worker         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0);
1655*8975f5c5SAndroid Build Coastguard Worker     }
1656*8975f5c5SAndroid Build Coastguard Worker 
1657*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1658*8975f5c5SAndroid Build Coastguard Worker }
1659*8975f5c5SAndroid Build Coastguard Worker 
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)1660*8975f5c5SAndroid Build Coastguard Worker angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
1661*8975f5c5SAndroid Build Coastguard Worker                                                                       const gl::Context *context,
1662*8975f5c5SAndroid Build Coastguard Worker                                                                       gl::PrimitiveMode mode,
1663*8975f5c5SAndroid Build Coastguard Worker                                                                       const GLsizei *counts,
1664*8975f5c5SAndroid Build Coastguard Worker                                                                       gl::DrawElementsType type,
1665*8975f5c5SAndroid Build Coastguard Worker                                                                       const GLvoid *const *indices,
1666*8975f5c5SAndroid Build Coastguard Worker                                                                       const GLsizei *instanceCounts,
1667*8975f5c5SAndroid Build Coastguard Worker                                                                       const GLint *baseVertices,
1668*8975f5c5SAndroid Build Coastguard Worker                                                                       const GLuint *baseInstances,
1669*8975f5c5SAndroid Build Coastguard Worker                                                                       GLsizei drawcount)
1670*8975f5c5SAndroid Build Coastguard Worker {
1671*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
1672*8975f5c5SAndroid Build Coastguard Worker     const bool hasDrawID              = executable->hasDrawIDUniform();
1673*8975f5c5SAndroid Build Coastguard Worker     const bool hasBaseVertex          = executable->hasBaseVertexUniform();
1674*8975f5c5SAndroid Build Coastguard Worker     const bool hasBaseInstance        = executable->hasBaseInstanceUniform();
1675*8975f5c5SAndroid Build Coastguard Worker     ResetBaseVertexBaseInstance resetUniforms(executable, hasBaseVertex, hasBaseInstance);
1676*8975f5c5SAndroid Build Coastguard Worker 
1677*8975f5c5SAndroid Build Coastguard Worker     if (hasDrawID)
1678*8975f5c5SAndroid Build Coastguard Worker     {
1679*8975f5c5SAndroid Build Coastguard Worker         if (hasBaseVertex)
1680*8975f5c5SAndroid Build Coastguard Worker         {
1681*8975f5c5SAndroid Build Coastguard Worker             if (hasBaseInstance)
1682*8975f5c5SAndroid Build Coastguard Worker             {
1683*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1);
1684*8975f5c5SAndroid Build Coastguard Worker             }
1685*8975f5c5SAndroid Build Coastguard Worker             else
1686*8975f5c5SAndroid Build Coastguard Worker             {
1687*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0);
1688*8975f5c5SAndroid Build Coastguard Worker             }
1689*8975f5c5SAndroid Build Coastguard Worker         }
1690*8975f5c5SAndroid Build Coastguard Worker         else
1691*8975f5c5SAndroid Build Coastguard Worker         {
1692*8975f5c5SAndroid Build Coastguard Worker             if (hasBaseInstance)
1693*8975f5c5SAndroid Build Coastguard Worker             {
1694*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1);
1695*8975f5c5SAndroid Build Coastguard Worker             }
1696*8975f5c5SAndroid Build Coastguard Worker             else
1697*8975f5c5SAndroid Build Coastguard Worker             {
1698*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0);
1699*8975f5c5SAndroid Build Coastguard Worker             }
1700*8975f5c5SAndroid Build Coastguard Worker         }
1701*8975f5c5SAndroid Build Coastguard Worker     }
1702*8975f5c5SAndroid Build Coastguard Worker     else
1703*8975f5c5SAndroid Build Coastguard Worker     {
1704*8975f5c5SAndroid Build Coastguard Worker         if (hasBaseVertex)
1705*8975f5c5SAndroid Build Coastguard Worker         {
1706*8975f5c5SAndroid Build Coastguard Worker             if (hasBaseInstance)
1707*8975f5c5SAndroid Build Coastguard Worker             {
1708*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1);
1709*8975f5c5SAndroid Build Coastguard Worker             }
1710*8975f5c5SAndroid Build Coastguard Worker             else
1711*8975f5c5SAndroid Build Coastguard Worker             {
1712*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0);
1713*8975f5c5SAndroid Build Coastguard Worker             }
1714*8975f5c5SAndroid Build Coastguard Worker         }
1715*8975f5c5SAndroid Build Coastguard Worker         else
1716*8975f5c5SAndroid Build Coastguard Worker         {
1717*8975f5c5SAndroid Build Coastguard Worker             if (hasBaseInstance)
1718*8975f5c5SAndroid Build Coastguard Worker             {
1719*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1);
1720*8975f5c5SAndroid Build Coastguard Worker             }
1721*8975f5c5SAndroid Build Coastguard Worker             else
1722*8975f5c5SAndroid Build Coastguard Worker             {
1723*8975f5c5SAndroid Build Coastguard Worker                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0);
1724*8975f5c5SAndroid Build Coastguard Worker             }
1725*8975f5c5SAndroid Build Coastguard Worker         }
1726*8975f5c5SAndroid Build Coastguard Worker     }
1727*8975f5c5SAndroid Build Coastguard Worker 
1728*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1729*8975f5c5SAndroid Build Coastguard Worker }
1730*8975f5c5SAndroid Build Coastguard Worker 
ResetBaseVertexBaseInstance(gl::ProgramExecutable * executable,bool resetBaseVertex,bool resetBaseInstance)1731*8975f5c5SAndroid Build Coastguard Worker ResetBaseVertexBaseInstance::ResetBaseVertexBaseInstance(gl::ProgramExecutable *executable,
1732*8975f5c5SAndroid Build Coastguard Worker                                                          bool resetBaseVertex,
1733*8975f5c5SAndroid Build Coastguard Worker                                                          bool resetBaseInstance)
1734*8975f5c5SAndroid Build Coastguard Worker     : mExecutable(executable),
1735*8975f5c5SAndroid Build Coastguard Worker       mResetBaseVertex(resetBaseVertex),
1736*8975f5c5SAndroid Build Coastguard Worker       mResetBaseInstance(resetBaseInstance)
1737*8975f5c5SAndroid Build Coastguard Worker {}
1738*8975f5c5SAndroid Build Coastguard Worker 
~ResetBaseVertexBaseInstance()1739*8975f5c5SAndroid Build Coastguard Worker ResetBaseVertexBaseInstance::~ResetBaseVertexBaseInstance()
1740*8975f5c5SAndroid Build Coastguard Worker {
1741*8975f5c5SAndroid Build Coastguard Worker     if (mExecutable)
1742*8975f5c5SAndroid Build Coastguard Worker     {
1743*8975f5c5SAndroid Build Coastguard Worker         // Reset emulated uniforms to zero to avoid affecting other draw calls
1744*8975f5c5SAndroid Build Coastguard Worker         if (mResetBaseVertex)
1745*8975f5c5SAndroid Build Coastguard Worker         {
1746*8975f5c5SAndroid Build Coastguard Worker             mExecutable->setBaseVertexUniform(0);
1747*8975f5c5SAndroid Build Coastguard Worker         }
1748*8975f5c5SAndroid Build Coastguard Worker 
1749*8975f5c5SAndroid Build Coastguard Worker         if (mResetBaseInstance)
1750*8975f5c5SAndroid Build Coastguard Worker         {
1751*8975f5c5SAndroid Build Coastguard Worker             mExecutable->setBaseInstanceUniform(0);
1752*8975f5c5SAndroid Build Coastguard Worker         }
1753*8975f5c5SAndroid Build Coastguard Worker     }
1754*8975f5c5SAndroid Build Coastguard Worker }
1755*8975f5c5SAndroid Build Coastguard Worker 
ConvertToSRGB(angle::FormatID formatID)1756*8975f5c5SAndroid Build Coastguard Worker angle::FormatID ConvertToSRGB(angle::FormatID formatID)
1757*8975f5c5SAndroid Build Coastguard Worker {
1758*8975f5c5SAndroid Build Coastguard Worker     switch (formatID)
1759*8975f5c5SAndroid Build Coastguard Worker     {
1760*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8_UNORM:
1761*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8_UNORM_SRGB;
1762*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8G8_UNORM:
1763*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8G8_UNORM_SRGB;
1764*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8G8B8_UNORM:
1765*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8G8B8_UNORM_SRGB;
1766*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8G8B8A8_UNORM:
1767*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8G8B8A8_UNORM_SRGB;
1768*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::B8G8R8A8_UNORM:
1769*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::B8G8R8A8_UNORM_SRGB;
1770*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC1_RGB_UNORM_BLOCK:
1771*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
1772*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC1_RGBA_UNORM_BLOCK:
1773*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
1774*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC2_RGBA_UNORM_BLOCK:
1775*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
1776*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC3_RGBA_UNORM_BLOCK:
1777*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
1778*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC7_RGBA_UNORM_BLOCK:
1779*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK;
1780*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
1781*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK;
1782*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
1783*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK;
1784*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
1785*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK;
1786*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_4x4_UNORM_BLOCK:
1787*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_4x4_SRGB_BLOCK;
1788*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_5x4_UNORM_BLOCK:
1789*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_5x4_SRGB_BLOCK;
1790*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_5x5_UNORM_BLOCK:
1791*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_5x5_SRGB_BLOCK;
1792*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_6x5_UNORM_BLOCK:
1793*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_6x5_SRGB_BLOCK;
1794*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_6x6_UNORM_BLOCK:
1795*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_6x6_SRGB_BLOCK;
1796*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_8x5_UNORM_BLOCK:
1797*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_8x5_SRGB_BLOCK;
1798*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_8x6_UNORM_BLOCK:
1799*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_8x6_SRGB_BLOCK;
1800*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_8x8_UNORM_BLOCK:
1801*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_8x8_SRGB_BLOCK;
1802*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x5_UNORM_BLOCK:
1803*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x5_SRGB_BLOCK;
1804*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x6_UNORM_BLOCK:
1805*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x6_SRGB_BLOCK;
1806*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x8_UNORM_BLOCK:
1807*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x8_SRGB_BLOCK;
1808*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x10_UNORM_BLOCK:
1809*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x10_SRGB_BLOCK;
1810*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_12x10_UNORM_BLOCK:
1811*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_12x10_SRGB_BLOCK;
1812*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_12x12_UNORM_BLOCK:
1813*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_12x12_SRGB_BLOCK;
1814*8975f5c5SAndroid Build Coastguard Worker         default:
1815*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::NONE;
1816*8975f5c5SAndroid Build Coastguard Worker     }
1817*8975f5c5SAndroid Build Coastguard Worker }
1818*8975f5c5SAndroid Build Coastguard Worker 
ConvertToLinear(angle::FormatID formatID)1819*8975f5c5SAndroid Build Coastguard Worker angle::FormatID ConvertToLinear(angle::FormatID formatID)
1820*8975f5c5SAndroid Build Coastguard Worker {
1821*8975f5c5SAndroid Build Coastguard Worker     switch (formatID)
1822*8975f5c5SAndroid Build Coastguard Worker     {
1823*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8_UNORM_SRGB:
1824*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8_UNORM;
1825*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8G8_UNORM_SRGB:
1826*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8G8_UNORM;
1827*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8G8B8_UNORM_SRGB:
1828*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8G8B8_UNORM;
1829*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::R8G8B8A8_UNORM_SRGB:
1830*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::R8G8B8A8_UNORM;
1831*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::B8G8R8A8_UNORM_SRGB:
1832*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::B8G8R8A8_UNORM;
1833*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK:
1834*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC1_RGB_UNORM_BLOCK;
1835*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK:
1836*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC1_RGBA_UNORM_BLOCK;
1837*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK:
1838*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC2_RGBA_UNORM_BLOCK;
1839*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK:
1840*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC3_RGBA_UNORM_BLOCK;
1841*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK:
1842*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::BC7_RGBA_UNORM_BLOCK;
1843*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
1844*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK;
1845*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
1846*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK;
1847*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
1848*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK;
1849*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_4x4_SRGB_BLOCK:
1850*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_4x4_UNORM_BLOCK;
1851*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_5x4_SRGB_BLOCK:
1852*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_5x4_UNORM_BLOCK;
1853*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_5x5_SRGB_BLOCK:
1854*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_5x5_UNORM_BLOCK;
1855*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_6x5_SRGB_BLOCK:
1856*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_6x5_UNORM_BLOCK;
1857*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_6x6_SRGB_BLOCK:
1858*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_6x6_UNORM_BLOCK;
1859*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_8x5_SRGB_BLOCK:
1860*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_8x5_UNORM_BLOCK;
1861*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_8x6_SRGB_BLOCK:
1862*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_8x6_UNORM_BLOCK;
1863*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_8x8_SRGB_BLOCK:
1864*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_8x8_UNORM_BLOCK;
1865*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x5_SRGB_BLOCK:
1866*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x5_UNORM_BLOCK;
1867*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x6_SRGB_BLOCK:
1868*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x6_UNORM_BLOCK;
1869*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x8_SRGB_BLOCK:
1870*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x8_UNORM_BLOCK;
1871*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_10x10_SRGB_BLOCK:
1872*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_10x10_UNORM_BLOCK;
1873*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_12x10_SRGB_BLOCK:
1874*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_12x10_UNORM_BLOCK;
1875*8975f5c5SAndroid Build Coastguard Worker         case angle::FormatID::ASTC_12x12_SRGB_BLOCK:
1876*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::ASTC_12x12_UNORM_BLOCK;
1877*8975f5c5SAndroid Build Coastguard Worker         default:
1878*8975f5c5SAndroid Build Coastguard Worker             return angle::FormatID::NONE;
1879*8975f5c5SAndroid Build Coastguard Worker     }
1880*8975f5c5SAndroid Build Coastguard Worker }
1881*8975f5c5SAndroid Build Coastguard Worker 
IsOverridableLinearFormat(angle::FormatID formatID)1882*8975f5c5SAndroid Build Coastguard Worker bool IsOverridableLinearFormat(angle::FormatID formatID)
1883*8975f5c5SAndroid Build Coastguard Worker {
1884*8975f5c5SAndroid Build Coastguard Worker     return ConvertToSRGB(formatID) != angle::FormatID::NONE;
1885*8975f5c5SAndroid Build Coastguard Worker }
1886*8975f5c5SAndroid Build Coastguard Worker 
1887*8975f5c5SAndroid Build Coastguard Worker template <bool swizzledLuma>
AdjustBorderColor(const angle::ColorGeneric & borderColorGeneric,const angle::Format & format,bool stencilMode)1888*8975f5c5SAndroid Build Coastguard Worker const gl::ColorGeneric AdjustBorderColor(const angle::ColorGeneric &borderColorGeneric,
1889*8975f5c5SAndroid Build Coastguard Worker                                          const angle::Format &format,
1890*8975f5c5SAndroid Build Coastguard Worker                                          bool stencilMode)
1891*8975f5c5SAndroid Build Coastguard Worker {
1892*8975f5c5SAndroid Build Coastguard Worker     gl::ColorGeneric adjustedBorderColor = borderColorGeneric;
1893*8975f5c5SAndroid Build Coastguard Worker 
1894*8975f5c5SAndroid Build Coastguard Worker     // Handle depth formats
1895*8975f5c5SAndroid Build Coastguard Worker     if (format.hasDepthOrStencilBits())
1896*8975f5c5SAndroid Build Coastguard Worker     {
1897*8975f5c5SAndroid Build Coastguard Worker         if (stencilMode)
1898*8975f5c5SAndroid Build Coastguard Worker         {
1899*8975f5c5SAndroid Build Coastguard Worker             // Stencil component
1900*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorUI.red = gl::clampForBitCount<unsigned int>(
1901*8975f5c5SAndroid Build Coastguard Worker                 adjustedBorderColor.colorUI.red, format.stencilBits);
1902*8975f5c5SAndroid Build Coastguard Worker             // Unused components need to be reset because some backends simulate integer samplers
1903*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorUI.green = 0u;
1904*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorUI.blue  = 0u;
1905*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorUI.alpha = 1u;
1906*8975f5c5SAndroid Build Coastguard Worker         }
1907*8975f5c5SAndroid Build Coastguard Worker         else
1908*8975f5c5SAndroid Build Coastguard Worker         {
1909*8975f5c5SAndroid Build Coastguard Worker             // Depth component
1910*8975f5c5SAndroid Build Coastguard Worker             if (format.isUnorm())
1911*8975f5c5SAndroid Build Coastguard Worker             {
1912*8975f5c5SAndroid Build Coastguard Worker                 adjustedBorderColor.colorF.red = gl::clamp01(adjustedBorderColor.colorF.red);
1913*8975f5c5SAndroid Build Coastguard Worker             }
1914*8975f5c5SAndroid Build Coastguard Worker         }
1915*8975f5c5SAndroid Build Coastguard Worker 
1916*8975f5c5SAndroid Build Coastguard Worker         return adjustedBorderColor;
1917*8975f5c5SAndroid Build Coastguard Worker     }
1918*8975f5c5SAndroid Build Coastguard Worker 
1919*8975f5c5SAndroid Build Coastguard Worker     // Handle LUMA formats
1920*8975f5c5SAndroid Build Coastguard Worker     if (format.isLUMA())
1921*8975f5c5SAndroid Build Coastguard Worker     {
1922*8975f5c5SAndroid Build Coastguard Worker         if (format.isUnorm())
1923*8975f5c5SAndroid Build Coastguard Worker         {
1924*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorF.red   = gl::clamp01(adjustedBorderColor.colorF.red);
1925*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorF.alpha = gl::clamp01(adjustedBorderColor.colorF.alpha);
1926*8975f5c5SAndroid Build Coastguard Worker         }
1927*8975f5c5SAndroid Build Coastguard Worker 
1928*8975f5c5SAndroid Build Coastguard Worker         // Luma formats are either unpacked to RGBA or emulated with component swizzling
1929*8975f5c5SAndroid Build Coastguard Worker         if (swizzledLuma)
1930*8975f5c5SAndroid Build Coastguard Worker         {
1931*8975f5c5SAndroid Build Coastguard Worker             // L is R (no-op); A is R; LA is RG
1932*8975f5c5SAndroid Build Coastguard Worker             if (format.alphaBits > 0)
1933*8975f5c5SAndroid Build Coastguard Worker             {
1934*8975f5c5SAndroid Build Coastguard Worker                 if (format.luminanceBits > 0)
1935*8975f5c5SAndroid Build Coastguard Worker                 {
1936*8975f5c5SAndroid Build Coastguard Worker                     adjustedBorderColor.colorF.green = adjustedBorderColor.colorF.alpha;
1937*8975f5c5SAndroid Build Coastguard Worker                 }
1938*8975f5c5SAndroid Build Coastguard Worker                 else
1939*8975f5c5SAndroid Build Coastguard Worker                 {
1940*8975f5c5SAndroid Build Coastguard Worker                     adjustedBorderColor.colorF.red = adjustedBorderColor.colorF.alpha;
1941*8975f5c5SAndroid Build Coastguard Worker                 }
1942*8975f5c5SAndroid Build Coastguard Worker             }
1943*8975f5c5SAndroid Build Coastguard Worker         }
1944*8975f5c5SAndroid Build Coastguard Worker         else
1945*8975f5c5SAndroid Build Coastguard Worker         {
1946*8975f5c5SAndroid Build Coastguard Worker             // L is RGBX; A is A or RGBA; LA is RGBA
1947*8975f5c5SAndroid Build Coastguard Worker             if (format.alphaBits == 0)
1948*8975f5c5SAndroid Build Coastguard Worker             {
1949*8975f5c5SAndroid Build Coastguard Worker                 adjustedBorderColor.colorF.alpha = 1.0f;
1950*8975f5c5SAndroid Build Coastguard Worker             }
1951*8975f5c5SAndroid Build Coastguard Worker             else if (format.luminanceBits == 0)
1952*8975f5c5SAndroid Build Coastguard Worker             {
1953*8975f5c5SAndroid Build Coastguard Worker                 adjustedBorderColor.colorF.red = 0.0f;
1954*8975f5c5SAndroid Build Coastguard Worker             }
1955*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorF.green = adjustedBorderColor.colorF.red;
1956*8975f5c5SAndroid Build Coastguard Worker             adjustedBorderColor.colorF.blue  = adjustedBorderColor.colorF.red;
1957*8975f5c5SAndroid Build Coastguard Worker         }
1958*8975f5c5SAndroid Build Coastguard Worker 
1959*8975f5c5SAndroid Build Coastguard Worker         return adjustedBorderColor;
1960*8975f5c5SAndroid Build Coastguard Worker     }
1961*8975f5c5SAndroid Build Coastguard Worker 
1962*8975f5c5SAndroid Build Coastguard Worker     // Handle all other formats. Clamp border color to the ranges of color components.
1963*8975f5c5SAndroid Build Coastguard Worker     // On some platforms, RGB formats may be emulated with RGBA, enforce opaque border color there.
1964*8975f5c5SAndroid Build Coastguard Worker     if (format.isSint())
1965*8975f5c5SAndroid Build Coastguard Worker     {
1966*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorI.red =
1967*8975f5c5SAndroid Build Coastguard Worker             gl::clampForBitCount<int>(adjustedBorderColor.colorI.red, format.redBits);
1968*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorI.green =
1969*8975f5c5SAndroid Build Coastguard Worker             gl::clampForBitCount<int>(adjustedBorderColor.colorI.green, format.greenBits);
1970*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorI.blue =
1971*8975f5c5SAndroid Build Coastguard Worker             gl::clampForBitCount<int>(adjustedBorderColor.colorI.blue, format.blueBits);
1972*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorI.alpha =
1973*8975f5c5SAndroid Build Coastguard Worker             format.alphaBits > 0
1974*8975f5c5SAndroid Build Coastguard Worker                 ? gl::clampForBitCount<int>(adjustedBorderColor.colorI.alpha, format.alphaBits)
1975*8975f5c5SAndroid Build Coastguard Worker                 : 1;
1976*8975f5c5SAndroid Build Coastguard Worker     }
1977*8975f5c5SAndroid Build Coastguard Worker     else if (format.isUint())
1978*8975f5c5SAndroid Build Coastguard Worker     {
1979*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorUI.red =
1980*8975f5c5SAndroid Build Coastguard Worker             gl::clampForBitCount<unsigned int>(adjustedBorderColor.colorUI.red, format.redBits);
1981*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorUI.green =
1982*8975f5c5SAndroid Build Coastguard Worker             gl::clampForBitCount<unsigned int>(adjustedBorderColor.colorUI.green, format.greenBits);
1983*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorUI.blue =
1984*8975f5c5SAndroid Build Coastguard Worker             gl::clampForBitCount<unsigned int>(adjustedBorderColor.colorUI.blue, format.blueBits);
1985*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorUI.alpha =
1986*8975f5c5SAndroid Build Coastguard Worker             format.alphaBits > 0 ? gl::clampForBitCount<unsigned int>(
1987*8975f5c5SAndroid Build Coastguard Worker                                        adjustedBorderColor.colorUI.alpha, format.alphaBits)
1988*8975f5c5SAndroid Build Coastguard Worker                                  : 1;
1989*8975f5c5SAndroid Build Coastguard Worker     }
1990*8975f5c5SAndroid Build Coastguard Worker     else if (format.isSnorm())
1991*8975f5c5SAndroid Build Coastguard Worker     {
1992*8975f5c5SAndroid Build Coastguard Worker         // clamp between -1.0f and 1.0f
1993*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.red   = gl::clamp(adjustedBorderColor.colorF.red, -1.0f, 1.0f);
1994*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.green = gl::clamp(adjustedBorderColor.colorF.green, -1.0f, 1.0f);
1995*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.blue  = gl::clamp(adjustedBorderColor.colorF.blue, -1.0f, 1.0f);
1996*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.alpha =
1997*8975f5c5SAndroid Build Coastguard Worker             format.alphaBits > 0 ? gl::clamp(adjustedBorderColor.colorF.alpha, -1.0f, 1.0f) : 1.0f;
1998*8975f5c5SAndroid Build Coastguard Worker     }
1999*8975f5c5SAndroid Build Coastguard Worker     else if (format.isUnorm())
2000*8975f5c5SAndroid Build Coastguard Worker     {
2001*8975f5c5SAndroid Build Coastguard Worker         // clamp between 0.0f and 1.0f
2002*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.red   = gl::clamp01(adjustedBorderColor.colorF.red);
2003*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.green = gl::clamp01(adjustedBorderColor.colorF.green);
2004*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.blue  = gl::clamp01(adjustedBorderColor.colorF.blue);
2005*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.alpha =
2006*8975f5c5SAndroid Build Coastguard Worker             format.alphaBits > 0 ? gl::clamp01(adjustedBorderColor.colorF.alpha) : 1.0f;
2007*8975f5c5SAndroid Build Coastguard Worker     }
2008*8975f5c5SAndroid Build Coastguard Worker     else if (format.isFloat() && format.alphaBits == 0)
2009*8975f5c5SAndroid Build Coastguard Worker     {
2010*8975f5c5SAndroid Build Coastguard Worker         adjustedBorderColor.colorF.alpha = 1.0;
2011*8975f5c5SAndroid Build Coastguard Worker     }
2012*8975f5c5SAndroid Build Coastguard Worker 
2013*8975f5c5SAndroid Build Coastguard Worker     return adjustedBorderColor;
2014*8975f5c5SAndroid Build Coastguard Worker }
2015*8975f5c5SAndroid Build Coastguard Worker 
2016*8975f5c5SAndroid Build Coastguard Worker template const gl::ColorGeneric AdjustBorderColor<true>(
2017*8975f5c5SAndroid Build Coastguard Worker     const angle::ColorGeneric &borderColorGeneric,
2018*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &format,
2019*8975f5c5SAndroid Build Coastguard Worker     bool stencilMode);
2020*8975f5c5SAndroid Build Coastguard Worker template const gl::ColorGeneric AdjustBorderColor<false>(
2021*8975f5c5SAndroid Build Coastguard Worker     const angle::ColorGeneric &borderColorGeneric,
2022*8975f5c5SAndroid Build Coastguard Worker     const angle::Format &format,
2023*8975f5c5SAndroid Build Coastguard Worker     bool stencilMode);
2024*8975f5c5SAndroid Build Coastguard Worker 
TextureHasAnyRedefinedLevels(const gl::CubeFaceArray<gl::TexLevelMask> & redefinedLevels)2025*8975f5c5SAndroid Build Coastguard Worker bool TextureHasAnyRedefinedLevels(const gl::CubeFaceArray<gl::TexLevelMask> &redefinedLevels)
2026*8975f5c5SAndroid Build Coastguard Worker {
2027*8975f5c5SAndroid Build Coastguard Worker     for (gl::TexLevelMask faceRedefinedLevels : redefinedLevels)
2028*8975f5c5SAndroid Build Coastguard Worker     {
2029*8975f5c5SAndroid Build Coastguard Worker         if (faceRedefinedLevels.any())
2030*8975f5c5SAndroid Build Coastguard Worker         {
2031*8975f5c5SAndroid Build Coastguard Worker             return true;
2032*8975f5c5SAndroid Build Coastguard Worker         }
2033*8975f5c5SAndroid Build Coastguard Worker     }
2034*8975f5c5SAndroid Build Coastguard Worker 
2035*8975f5c5SAndroid Build Coastguard Worker     return false;
2036*8975f5c5SAndroid Build Coastguard Worker }
2037*8975f5c5SAndroid Build Coastguard Worker 
IsTextureLevelRedefined(const gl::CubeFaceArray<gl::TexLevelMask> & redefinedLevels,gl::TextureType textureType,gl::LevelIndex level)2038*8975f5c5SAndroid Build Coastguard Worker bool IsTextureLevelRedefined(const gl::CubeFaceArray<gl::TexLevelMask> &redefinedLevels,
2039*8975f5c5SAndroid Build Coastguard Worker                              gl::TextureType textureType,
2040*8975f5c5SAndroid Build Coastguard Worker                              gl::LevelIndex level)
2041*8975f5c5SAndroid Build Coastguard Worker {
2042*8975f5c5SAndroid Build Coastguard Worker     gl::TexLevelMask redefined = redefinedLevels[0];
2043*8975f5c5SAndroid Build Coastguard Worker 
2044*8975f5c5SAndroid Build Coastguard Worker     if (textureType == gl::TextureType::CubeMap)
2045*8975f5c5SAndroid Build Coastguard Worker     {
2046*8975f5c5SAndroid Build Coastguard Worker         for (size_t face = 1; face < gl::kCubeFaceCount; ++face)
2047*8975f5c5SAndroid Build Coastguard Worker         {
2048*8975f5c5SAndroid Build Coastguard Worker             redefined |= redefinedLevels[face];
2049*8975f5c5SAndroid Build Coastguard Worker         }
2050*8975f5c5SAndroid Build Coastguard Worker     }
2051*8975f5c5SAndroid Build Coastguard Worker 
2052*8975f5c5SAndroid Build Coastguard Worker     return redefined.test(level.get());
2053*8975f5c5SAndroid Build Coastguard Worker }
2054*8975f5c5SAndroid Build Coastguard Worker 
TextureRedefineLevel(const TextureLevelAllocation levelAllocation,const TextureLevelDefinition levelDefinition,bool immutableFormat,uint32_t levelCount,const uint32_t layerIndex,const gl::ImageIndex & index,gl::LevelIndex imageFirstAllocatedLevel,gl::CubeFaceArray<gl::TexLevelMask> * redefinedLevels)2055*8975f5c5SAndroid Build Coastguard Worker bool TextureRedefineLevel(const TextureLevelAllocation levelAllocation,
2056*8975f5c5SAndroid Build Coastguard Worker                           const TextureLevelDefinition levelDefinition,
2057*8975f5c5SAndroid Build Coastguard Worker                           bool immutableFormat,
2058*8975f5c5SAndroid Build Coastguard Worker                           uint32_t levelCount,
2059*8975f5c5SAndroid Build Coastguard Worker                           const uint32_t layerIndex,
2060*8975f5c5SAndroid Build Coastguard Worker                           const gl::ImageIndex &index,
2061*8975f5c5SAndroid Build Coastguard Worker                           gl::LevelIndex imageFirstAllocatedLevel,
2062*8975f5c5SAndroid Build Coastguard Worker                           gl::CubeFaceArray<gl::TexLevelMask> *redefinedLevels)
2063*8975f5c5SAndroid Build Coastguard Worker {
2064*8975f5c5SAndroid Build Coastguard Worker     // If the level that's being redefined is outside the level range of the allocated
2065*8975f5c5SAndroid Build Coastguard Worker     // image, the application is free to use any size or format.  Any data uploaded to it
2066*8975f5c5SAndroid Build Coastguard Worker     // will live in staging area until the texture base/max level is adjusted to include
2067*8975f5c5SAndroid Build Coastguard Worker     // this level, at which point the image will be recreated.
2068*8975f5c5SAndroid Build Coastguard Worker     //
2069*8975f5c5SAndroid Build Coastguard Worker     // Otherwise, if the level that's being redefined has a different format or size,
2070*8975f5c5SAndroid Build Coastguard Worker     // only release the image if it's single-mip, and keep the uploaded data staged.
2071*8975f5c5SAndroid Build Coastguard Worker     // Otherwise the image is mip-incomplete anyway and will be eventually recreated when
2072*8975f5c5SAndroid Build Coastguard Worker     // needed.  Only exception to this latter is if all the levels of the texture are
2073*8975f5c5SAndroid Build Coastguard Worker     // redefined such that the image becomes mip-complete in the end.
2074*8975f5c5SAndroid Build Coastguard Worker     // redefinedLevels is used during syncState to support this use-case.
2075*8975f5c5SAndroid Build Coastguard Worker     //
2076*8975f5c5SAndroid Build Coastguard Worker     // Note that if the image has multiple mips, there could be a copy from one mip
2077*8975f5c5SAndroid Build Coastguard Worker     // happening to the other, which means the image cannot be released.
2078*8975f5c5SAndroid Build Coastguard Worker     //
2079*8975f5c5SAndroid Build Coastguard Worker     // In summary:
2080*8975f5c5SAndroid Build Coastguard Worker     //
2081*8975f5c5SAndroid Build Coastguard Worker     // - If the image has a single level, and that level is being redefined, release the
2082*8975f5c5SAndroid Build Coastguard Worker     //   image.
2083*8975f5c5SAndroid Build Coastguard Worker     // - Otherwise keep the image intact (another mip may be the source of a copy), and
2084*8975f5c5SAndroid Build Coastguard Worker     //   make sure any updates to this level are staged.
2085*8975f5c5SAndroid Build Coastguard Worker     gl::LevelIndex levelIndexGL(index.getLevelIndex());
2086*8975f5c5SAndroid Build Coastguard Worker     const bool isCompatibleRedefinition =
2087*8975f5c5SAndroid Build Coastguard Worker         levelAllocation == TextureLevelAllocation::WithinAllocatedImage &&
2088*8975f5c5SAndroid Build Coastguard Worker         levelDefinition == TextureLevelDefinition::Compatible;
2089*8975f5c5SAndroid Build Coastguard Worker     const bool isCubeMap = index.getType() == gl::TextureType::CubeMap;
2090*8975f5c5SAndroid Build Coastguard Worker 
2091*8975f5c5SAndroid Build Coastguard Worker     // Mark the level as incompatibly redefined if that's the case.  Note that if the level
2092*8975f5c5SAndroid Build Coastguard Worker     // was previously incompatibly defined, then later redefined to be compatible, the
2093*8975f5c5SAndroid Build Coastguard Worker     // corresponding bit should clear.
2094*8975f5c5SAndroid Build Coastguard Worker     if (levelAllocation == TextureLevelAllocation::WithinAllocatedImage)
2095*8975f5c5SAndroid Build Coastguard Worker     {
2096*8975f5c5SAndroid Build Coastguard Worker         // Immutable texture should never have levels redefined.
2097*8975f5c5SAndroid Build Coastguard Worker         ASSERT(isCompatibleRedefinition || !immutableFormat);
2098*8975f5c5SAndroid Build Coastguard Worker 
2099*8975f5c5SAndroid Build Coastguard Worker         const uint32_t redefinedFace = isCubeMap ? layerIndex : 0;
2100*8975f5c5SAndroid Build Coastguard Worker         (*redefinedLevels)[redefinedFace].set(levelIndexGL.get(), !isCompatibleRedefinition);
2101*8975f5c5SAndroid Build Coastguard Worker     }
2102*8975f5c5SAndroid Build Coastguard Worker 
2103*8975f5c5SAndroid Build Coastguard Worker     const bool isUpdateToSingleLevelImage =
2104*8975f5c5SAndroid Build Coastguard Worker         levelCount == 1 && imageFirstAllocatedLevel == levelIndexGL;
2105*8975f5c5SAndroid Build Coastguard Worker 
2106*8975f5c5SAndroid Build Coastguard Worker     // If incompatible, and redefining the single-level image, the caller will release the texture
2107*8975f5c5SAndroid Build Coastguard Worker     // so it can be recreated immediately.  This is needed so that the texture can be reallocated
2108*8975f5c5SAndroid Build Coastguard Worker     // with the correct format/size.
2109*8975f5c5SAndroid Build Coastguard Worker     //
2110*8975f5c5SAndroid Build Coastguard Worker     // This is not done for cubemaps because every face may be separately redefined.  Note
2111*8975f5c5SAndroid Build Coastguard Worker     // that this is not possible for texture arrays in general.
2112*8975f5c5SAndroid Build Coastguard Worker     bool shouldReleaseImage = !isCompatibleRedefinition && isUpdateToSingleLevelImage && !isCubeMap;
2113*8975f5c5SAndroid Build Coastguard Worker     return shouldReleaseImage;
2114*8975f5c5SAndroid Build Coastguard Worker }
2115*8975f5c5SAndroid Build Coastguard Worker 
TextureRedefineGenerateMipmapLevels(gl::LevelIndex baseLevel,gl::LevelIndex maxLevel,gl::LevelIndex firstGeneratedLevel,gl::CubeFaceArray<gl::TexLevelMask> * redefinedLevels)2116*8975f5c5SAndroid Build Coastguard Worker void TextureRedefineGenerateMipmapLevels(gl::LevelIndex baseLevel,
2117*8975f5c5SAndroid Build Coastguard Worker                                          gl::LevelIndex maxLevel,
2118*8975f5c5SAndroid Build Coastguard Worker                                          gl::LevelIndex firstGeneratedLevel,
2119*8975f5c5SAndroid Build Coastguard Worker                                          gl::CubeFaceArray<gl::TexLevelMask> *redefinedLevels)
2120*8975f5c5SAndroid Build Coastguard Worker {
2121*8975f5c5SAndroid Build Coastguard Worker     static_assert(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS < 32,
2122*8975f5c5SAndroid Build Coastguard Worker                   "levels mask assumes 32-bits is enough");
2123*8975f5c5SAndroid Build Coastguard Worker     // Generate bitmask for (baseLevel, maxLevel]. `+1` because bitMask takes `the number of bits`
2124*8975f5c5SAndroid Build Coastguard Worker     // but levels start counting from 0
2125*8975f5c5SAndroid Build Coastguard Worker     gl::TexLevelMask levelsMask(angle::BitMask<uint32_t>(maxLevel.get() + 1));
2126*8975f5c5SAndroid Build Coastguard Worker     levelsMask &= static_cast<uint32_t>(~angle::BitMask<uint32_t>(firstGeneratedLevel.get()));
2127*8975f5c5SAndroid Build Coastguard Worker     // Remove (baseLevel, maxLevel] from redefinedLevels. These levels are no longer incompatibly
2128*8975f5c5SAndroid Build Coastguard Worker     // defined if they previously were.  The corresponding bits in redefinedLevels should be
2129*8975f5c5SAndroid Build Coastguard Worker     // cleared.
2130*8975f5c5SAndroid Build Coastguard Worker     for (size_t face = 0; face < gl::kCubeFaceCount; ++face)
2131*8975f5c5SAndroid Build Coastguard Worker     {
2132*8975f5c5SAndroid Build Coastguard Worker         (*redefinedLevels)[face] &= ~levelsMask;
2133*8975f5c5SAndroid Build Coastguard Worker     }
2134*8975f5c5SAndroid Build Coastguard Worker }
2135*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
2136