xref: /aosp_15_r20/external/angle/src/libANGLE/angletypes.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
8 
9 #include "libANGLE/angletypes.h"
10 #include "libANGLE/Program.h"
11 #include "libANGLE/State.h"
12 #include "libANGLE/VertexArray.h"
13 #include "libANGLE/VertexAttribute.h"
14 
15 #include <limits>
16 
17 #define USE_SYSTEM_ZLIB
18 #include "compression_utils_portable.h"
19 
20 namespace gl
21 {
22 namespace
23 {
IsStencilWriteMaskedOut(GLuint stencilWritemask,GLuint framebufferStencilSize)24 bool IsStencilWriteMaskedOut(GLuint stencilWritemask, GLuint framebufferStencilSize)
25 {
26     const GLuint framebufferMask = angle::BitMask<GLuint>(framebufferStencilSize);
27     return (stencilWritemask & framebufferMask) == 0;
28 }
29 
IsStencilNoOp(GLenum stencilFunc,GLenum stencilFail,GLenum stencilPassDepthFail,GLenum stencilPassDepthPass)30 bool IsStencilNoOp(GLenum stencilFunc,
31                    GLenum stencilFail,
32                    GLenum stencilPassDepthFail,
33                    GLenum stencilPassDepthPass)
34 {
35     const bool isNeverAndKeep           = stencilFunc == GL_NEVER && stencilFail == GL_KEEP;
36     const bool isAlwaysAndKeepOrAllKeep = (stencilFunc == GL_ALWAYS || stencilFail == GL_KEEP) &&
37                                           stencilPassDepthFail == GL_KEEP &&
38                                           stencilPassDepthPass == GL_KEEP;
39 
40     return isNeverAndKeep || isAlwaysAndKeepOrAllKeep;
41 }
42 
43 // Calculate whether the range [outsideLow, outsideHigh] encloses the range [insideLow, insideHigh]
EnclosesRange(int outsideLow,int outsideHigh,int insideLow,int insideHigh)44 bool EnclosesRange(int outsideLow, int outsideHigh, int insideLow, int insideHigh)
45 {
46     return outsideLow <= insideLow && outsideHigh >= insideHigh;
47 }
48 
IsAdvancedBlendEquation(gl::BlendEquationType blendEquation)49 bool IsAdvancedBlendEquation(gl::BlendEquationType blendEquation)
50 {
51     return blendEquation >= gl::BlendEquationType::Multiply &&
52            blendEquation <= gl::BlendEquationType::HslLuminosity;
53 }
54 
IsExtendedBlendFactor(gl::BlendFactorType blendFactor)55 bool IsExtendedBlendFactor(gl::BlendFactorType blendFactor)
56 {
57     return blendFactor >= gl::BlendFactorType::Src1Alpha &&
58            blendFactor <= gl::BlendFactorType::OneMinusSrc1Alpha;
59 }
60 }  // anonymous namespace
61 
RasterizerState()62 RasterizerState::RasterizerState()
63 {
64     memset(this, 0, sizeof(RasterizerState));
65 
66     cullFace            = false;
67     cullMode            = CullFaceMode::Back;
68     frontFace           = GL_CCW;
69     polygonMode         = PolygonMode::Fill;
70     polygonOffsetPoint  = false;
71     polygonOffsetLine   = false;
72     polygonOffsetFill   = false;
73     polygonOffsetFactor = 0.0f;
74     polygonOffsetUnits  = 0.0f;
75     polygonOffsetClamp  = 0.0f;
76     depthClamp          = false;
77     pointDrawMode       = false;
78     multiSample         = false;
79     rasterizerDiscard   = false;
80     dither              = true;
81 }
82 
RasterizerState(const RasterizerState & other)83 RasterizerState::RasterizerState(const RasterizerState &other)
84 {
85     memcpy(this, &other, sizeof(RasterizerState));
86 }
87 
operator =(const RasterizerState & other)88 RasterizerState &RasterizerState::operator=(const RasterizerState &other)
89 {
90     memcpy(this, &other, sizeof(RasterizerState));
91     return *this;
92 }
93 
operator ==(const RasterizerState & a,const RasterizerState & b)94 bool operator==(const RasterizerState &a, const RasterizerState &b)
95 {
96     return memcmp(&a, &b, sizeof(RasterizerState)) == 0;
97 }
98 
operator !=(const RasterizerState & a,const RasterizerState & b)99 bool operator!=(const RasterizerState &a, const RasterizerState &b)
100 {
101     return !(a == b);
102 }
103 
BlendState()104 BlendState::BlendState()
105 {
106     memset(this, 0, sizeof(BlendState));
107 
108     blend              = false;
109     sourceBlendRGB     = GL_ONE;
110     sourceBlendAlpha   = GL_ONE;
111     destBlendRGB       = GL_ZERO;
112     destBlendAlpha     = GL_ZERO;
113     blendEquationRGB   = GL_FUNC_ADD;
114     blendEquationAlpha = GL_FUNC_ADD;
115     colorMaskRed       = true;
116     colorMaskGreen     = true;
117     colorMaskBlue      = true;
118     colorMaskAlpha     = true;
119 }
120 
BlendState(const BlendState & other)121 BlendState::BlendState(const BlendState &other)
122 {
123     memcpy(this, &other, sizeof(BlendState));
124 }
125 
operator ==(const BlendState & a,const BlendState & b)126 bool operator==(const BlendState &a, const BlendState &b)
127 {
128     return memcmp(&a, &b, sizeof(BlendState)) == 0;
129 }
130 
operator !=(const BlendState & a,const BlendState & b)131 bool operator!=(const BlendState &a, const BlendState &b)
132 {
133     return !(a == b);
134 }
135 
DepthStencilState()136 DepthStencilState::DepthStencilState()
137 {
138     memset(this, 0, sizeof(DepthStencilState));
139 
140     depthTest                = false;
141     depthFunc                = GL_LESS;
142     depthMask                = true;
143     stencilTest              = false;
144     stencilFunc              = GL_ALWAYS;
145     stencilMask              = static_cast<GLuint>(-1);
146     stencilWritemask         = static_cast<GLuint>(-1);
147     stencilBackFunc          = GL_ALWAYS;
148     stencilBackMask          = static_cast<GLuint>(-1);
149     stencilBackWritemask     = static_cast<GLuint>(-1);
150     stencilFail              = GL_KEEP;
151     stencilPassDepthFail     = GL_KEEP;
152     stencilPassDepthPass     = GL_KEEP;
153     stencilBackFail          = GL_KEEP;
154     stencilBackPassDepthFail = GL_KEEP;
155     stencilBackPassDepthPass = GL_KEEP;
156 }
157 
DepthStencilState(const DepthStencilState & other)158 DepthStencilState::DepthStencilState(const DepthStencilState &other)
159 {
160     memcpy(this, &other, sizeof(DepthStencilState));
161 }
162 
operator =(const DepthStencilState & other)163 DepthStencilState &DepthStencilState::operator=(const DepthStencilState &other)
164 {
165     memcpy(this, &other, sizeof(DepthStencilState));
166     return *this;
167 }
168 
isDepthMaskedOut() const169 bool DepthStencilState::isDepthMaskedOut() const
170 {
171     return !depthMask;
172 }
173 
isStencilMaskedOut(GLuint framebufferStencilSize) const174 bool DepthStencilState::isStencilMaskedOut(GLuint framebufferStencilSize) const
175 {
176     return IsStencilWriteMaskedOut(stencilWritemask, framebufferStencilSize);
177 }
178 
isStencilNoOp(GLuint framebufferStencilSize) const179 bool DepthStencilState::isStencilNoOp(GLuint framebufferStencilSize) const
180 {
181     return isStencilMaskedOut(framebufferStencilSize) ||
182            IsStencilNoOp(stencilFunc, stencilFail, stencilPassDepthFail, stencilPassDepthPass);
183 }
184 
isStencilBackNoOp(GLuint framebufferStencilSize) const185 bool DepthStencilState::isStencilBackNoOp(GLuint framebufferStencilSize) const
186 {
187     return IsStencilWriteMaskedOut(stencilBackWritemask, framebufferStencilSize) ||
188            IsStencilNoOp(stencilBackFunc, stencilBackFail, stencilBackPassDepthFail,
189                          stencilBackPassDepthPass);
190 }
191 
operator ==(const DepthStencilState & a,const DepthStencilState & b)192 bool operator==(const DepthStencilState &a, const DepthStencilState &b)
193 {
194     return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
195 }
196 
operator !=(const DepthStencilState & a,const DepthStencilState & b)197 bool operator!=(const DepthStencilState &a, const DepthStencilState &b)
198 {
199     return !(a == b);
200 }
201 
SamplerState()202 SamplerState::SamplerState()
203 {
204     memset(this, 0, sizeof(SamplerState));
205 
206     setMinFilter(GL_NEAREST_MIPMAP_LINEAR);
207     setMagFilter(GL_LINEAR);
208     setWrapS(GL_REPEAT);
209     setWrapT(GL_REPEAT);
210     setWrapR(GL_REPEAT);
211     setMaxAnisotropy(1.0f);
212     setMinLod(-1000.0f);
213     setMaxLod(1000.0f);
214     setCompareMode(GL_NONE);
215     setCompareFunc(GL_LEQUAL);
216     setSRGBDecode(GL_DECODE_EXT);
217 }
218 
219 SamplerState::SamplerState(const SamplerState &other) = default;
220 
221 SamplerState &SamplerState::operator=(const SamplerState &other) = default;
222 
223 // static
CreateDefaultForTarget(TextureType type)224 SamplerState SamplerState::CreateDefaultForTarget(TextureType type)
225 {
226     SamplerState state;
227 
228     // According to OES_EGL_image_external and ARB_texture_rectangle: For external textures, the
229     // default min filter is GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
230     if (type == TextureType::External || type == TextureType::Rectangle)
231     {
232         state.mMinFilter = GL_LINEAR;
233         state.mWrapS     = GL_CLAMP_TO_EDGE;
234         state.mWrapT     = GL_CLAMP_TO_EDGE;
235     }
236 
237     return state;
238 }
239 
setMinFilter(GLenum minFilter)240 bool SamplerState::setMinFilter(GLenum minFilter)
241 {
242     if (mMinFilter != minFilter)
243     {
244         mMinFilter                    = minFilter;
245         mCompleteness.typed.minFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(minFilter));
246         return true;
247     }
248     return false;
249 }
250 
setMagFilter(GLenum magFilter)251 bool SamplerState::setMagFilter(GLenum magFilter)
252 {
253     if (mMagFilter != magFilter)
254     {
255         mMagFilter                    = magFilter;
256         mCompleteness.typed.magFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(magFilter));
257         return true;
258     }
259     return false;
260 }
261 
setWrapS(GLenum wrapS)262 bool SamplerState::setWrapS(GLenum wrapS)
263 {
264     if (mWrapS != wrapS)
265     {
266         mWrapS                    = wrapS;
267         mCompleteness.typed.wrapS = static_cast<uint8_t>(FromGLenum<WrapMode>(wrapS));
268         return true;
269     }
270     return false;
271 }
272 
setWrapT(GLenum wrapT)273 bool SamplerState::setWrapT(GLenum wrapT)
274 {
275     if (mWrapT != wrapT)
276     {
277         mWrapT = wrapT;
278         updateWrapTCompareMode();
279         return true;
280     }
281     return false;
282 }
283 
setWrapR(GLenum wrapR)284 bool SamplerState::setWrapR(GLenum wrapR)
285 {
286     if (mWrapR != wrapR)
287     {
288         mWrapR = wrapR;
289         return true;
290     }
291     return false;
292 }
293 
setMaxAnisotropy(float maxAnisotropy)294 bool SamplerState::setMaxAnisotropy(float maxAnisotropy)
295 {
296     if (mMaxAnisotropy != maxAnisotropy)
297     {
298         mMaxAnisotropy = maxAnisotropy;
299         return true;
300     }
301     return false;
302 }
303 
setMinLod(GLfloat minLod)304 bool SamplerState::setMinLod(GLfloat minLod)
305 {
306     if (mMinLod != minLod)
307     {
308         mMinLod = minLod;
309         return true;
310     }
311     return false;
312 }
313 
setMaxLod(GLfloat maxLod)314 bool SamplerState::setMaxLod(GLfloat maxLod)
315 {
316     if (mMaxLod != maxLod)
317     {
318         mMaxLod = maxLod;
319         return true;
320     }
321     return false;
322 }
323 
setCompareMode(GLenum compareMode)324 bool SamplerState::setCompareMode(GLenum compareMode)
325 {
326     if (mCompareMode != compareMode)
327     {
328         mCompareMode = compareMode;
329         updateWrapTCompareMode();
330         return true;
331     }
332     return false;
333 }
334 
setCompareFunc(GLenum compareFunc)335 bool SamplerState::setCompareFunc(GLenum compareFunc)
336 {
337     if (mCompareFunc != compareFunc)
338     {
339         mCompareFunc = compareFunc;
340         return true;
341     }
342     return false;
343 }
344 
setSRGBDecode(GLenum sRGBDecode)345 bool SamplerState::setSRGBDecode(GLenum sRGBDecode)
346 {
347     if (mSRGBDecode != sRGBDecode)
348     {
349         mSRGBDecode = sRGBDecode;
350         return true;
351     }
352     return false;
353 }
354 
setBorderColor(const ColorGeneric & color)355 bool SamplerState::setBorderColor(const ColorGeneric &color)
356 {
357     if (mBorderColor != color)
358     {
359         mBorderColor = color;
360         return true;
361     }
362     return false;
363 }
364 
updateWrapTCompareMode()365 void SamplerState::updateWrapTCompareMode()
366 {
367     uint8_t wrap    = static_cast<uint8_t>(FromGLenum<WrapMode>(mWrapT));
368     uint8_t compare = static_cast<uint8_t>(mCompareMode == GL_NONE ? 0x10 : 0x00);
369     mCompleteness.typed.wrapTCompareMode = wrap | compare;
370 }
371 
ImageUnit()372 ImageUnit::ImageUnit()
373     : texture(), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
374 {}
375 
376 ImageUnit::ImageUnit(const ImageUnit &other) = default;
377 
378 ImageUnit::~ImageUnit() = default;
379 
BlendStateExt(const size_t drawBufferCount)380 BlendStateExt::BlendStateExt(const size_t drawBufferCount)
381     : mParameterMask(FactorStorage::GetMask(drawBufferCount)),
382       mSrcColor(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)),
383       mDstColor(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mParameterMask)),
384       mSrcAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)),
385       mDstAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mParameterMask)),
386       mEquationColor(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mParameterMask)),
387       mEquationAlpha(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mParameterMask)),
388       mAllColorMask(
389           ColorMaskStorage::GetReplicatedValue(PackColorMask(true, true, true, true),
390                                                ColorMaskStorage::GetMask(drawBufferCount))),
391       mColorMask(mAllColorMask),
392       mAllEnabledMask(0xFF >> (8 - drawBufferCount)),
393       mDrawBufferCount(drawBufferCount)
394 {}
395 
396 BlendStateExt::BlendStateExt(const BlendStateExt &other) = default;
397 
398 BlendStateExt &BlendStateExt::operator=(const BlendStateExt &other) = default;
399 
setEnabled(const bool enabled)400 void BlendStateExt::setEnabled(const bool enabled)
401 {
402     mEnabledMask = enabled ? mAllEnabledMask : DrawBufferMask::Zero();
403 }
404 
setEnabledIndexed(const size_t index,const bool enabled)405 void BlendStateExt::setEnabledIndexed(const size_t index, const bool enabled)
406 {
407     ASSERT(index < mDrawBufferCount);
408     mEnabledMask.set(index, enabled);
409 }
410 
expandColorMaskValue(const bool red,const bool green,const bool blue,const bool alpha) const411 BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskValue(const bool red,
412                                                                           const bool green,
413                                                                           const bool blue,
414                                                                           const bool alpha) const
415 {
416     return BlendStateExt::ColorMaskStorage::GetReplicatedValue(
417         PackColorMask(red, green, blue, alpha), mAllColorMask);
418 }
419 
expandColorMaskIndexed(const size_t index) const420 BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskIndexed(
421     const size_t index) const
422 {
423     return ColorMaskStorage::GetReplicatedValue(
424         ColorMaskStorage::GetValueIndexed(index, mColorMask), mAllColorMask);
425 }
426 
setColorMask(const bool red,const bool green,const bool blue,const bool alpha)427 void BlendStateExt::setColorMask(const bool red,
428                                  const bool green,
429                                  const bool blue,
430                                  const bool alpha)
431 {
432     mColorMask = expandColorMaskValue(red, green, blue, alpha);
433 }
434 
setColorMaskIndexed(const size_t index,const uint8_t value)435 void BlendStateExt::setColorMaskIndexed(const size_t index, const uint8_t value)
436 {
437     ASSERT(index < mDrawBufferCount);
438     ASSERT(value <= 0xF);
439     ColorMaskStorage::SetValueIndexed(index, value, &mColorMask);
440 }
441 
setColorMaskIndexed(const size_t index,const bool red,const bool green,const bool blue,const bool alpha)442 void BlendStateExt::setColorMaskIndexed(const size_t index,
443                                         const bool red,
444                                         const bool green,
445                                         const bool blue,
446                                         const bool alpha)
447 {
448     ASSERT(index < mDrawBufferCount);
449     ColorMaskStorage::SetValueIndexed(index, PackColorMask(red, green, blue, alpha), &mColorMask);
450 }
451 
getColorMaskIndexed(const size_t index) const452 uint8_t BlendStateExt::getColorMaskIndexed(const size_t index) const
453 {
454     ASSERT(index < mDrawBufferCount);
455     return ColorMaskStorage::GetValueIndexed(index, mColorMask);
456 }
457 
getColorMaskIndexed(const size_t index,bool * red,bool * green,bool * blue,bool * alpha) const458 void BlendStateExt::getColorMaskIndexed(const size_t index,
459                                         bool *red,
460                                         bool *green,
461                                         bool *blue,
462                                         bool *alpha) const
463 {
464     ASSERT(index < mDrawBufferCount);
465     UnpackColorMask(ColorMaskStorage::GetValueIndexed(index, mColorMask), red, green, blue, alpha);
466 }
467 
compareColorMask(ColorMaskStorage::Type other) const468 DrawBufferMask BlendStateExt::compareColorMask(ColorMaskStorage::Type other) const
469 {
470     return ColorMaskStorage::GetDiffMask(mColorMask, other);
471 }
472 
expandEquationValue(const GLenum mode) const473 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue(const GLenum mode) const
474 {
475     return EquationStorage::GetReplicatedValue(FromGLenum<BlendEquationType>(mode), mParameterMask);
476 }
477 
expandEquationValue(const gl::BlendEquationType equation) const478 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue(
479     const gl::BlendEquationType equation) const
480 {
481     return EquationStorage::GetReplicatedValue(equation, mParameterMask);
482 }
483 
expandEquationColorIndexed(const size_t index) const484 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationColorIndexed(
485     const size_t index) const
486 {
487     return EquationStorage::GetReplicatedValue(
488         EquationStorage::GetValueIndexed(index, mEquationColor), mParameterMask);
489 }
490 
expandEquationAlphaIndexed(const size_t index) const491 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationAlphaIndexed(
492     const size_t index) const
493 {
494     return EquationStorage::GetReplicatedValue(
495         EquationStorage::GetValueIndexed(index, mEquationAlpha), mParameterMask);
496 }
497 
setEquations(const GLenum modeColor,const GLenum modeAlpha)498 void BlendStateExt::setEquations(const GLenum modeColor, const GLenum modeAlpha)
499 {
500     const gl::BlendEquationType colorEquation = FromGLenum<BlendEquationType>(modeColor);
501     const gl::BlendEquationType alphaEquation = FromGLenum<BlendEquationType>(modeAlpha);
502 
503     mEquationColor = expandEquationValue(colorEquation);
504     mEquationAlpha = expandEquationValue(alphaEquation);
505 
506     // Note that advanced blend equations cannot be independently set for color and alpha, so only
507     // the color equation can be checked.
508     if (IsAdvancedBlendEquation(colorEquation))
509     {
510         mUsesAdvancedBlendEquationMask = mAllEnabledMask;
511     }
512     else
513     {
514         mUsesAdvancedBlendEquationMask.reset();
515     }
516 }
517 
setEquationsIndexed(const size_t index,const GLenum modeColor,const GLenum modeAlpha)518 void BlendStateExt::setEquationsIndexed(const size_t index,
519                                         const GLenum modeColor,
520                                         const GLenum modeAlpha)
521 {
522     ASSERT(index < mDrawBufferCount);
523 
524     const gl::BlendEquationType colorEquation = FromGLenum<BlendEquationType>(modeColor);
525     const gl::BlendEquationType alphaEquation = FromGLenum<BlendEquationType>(modeAlpha);
526 
527     EquationStorage::SetValueIndexed(index, colorEquation, &mEquationColor);
528     EquationStorage::SetValueIndexed(index, alphaEquation, &mEquationAlpha);
529 
530     mUsesAdvancedBlendEquationMask.set(index, IsAdvancedBlendEquation(colorEquation));
531 }
532 
setEquationsIndexed(const size_t index,const size_t sourceIndex,const BlendStateExt & source)533 void BlendStateExt::setEquationsIndexed(const size_t index,
534                                         const size_t sourceIndex,
535                                         const BlendStateExt &source)
536 {
537     ASSERT(index < mDrawBufferCount);
538     ASSERT(sourceIndex < source.mDrawBufferCount);
539 
540     const gl::BlendEquationType colorEquation =
541         EquationStorage::GetValueIndexed(sourceIndex, source.mEquationColor);
542     const gl::BlendEquationType alphaEquation =
543         EquationStorage::GetValueIndexed(sourceIndex, source.mEquationAlpha);
544 
545     EquationStorage::SetValueIndexed(index, colorEquation, &mEquationColor);
546     EquationStorage::SetValueIndexed(index, alphaEquation, &mEquationAlpha);
547 
548     mUsesAdvancedBlendEquationMask.set(index, IsAdvancedBlendEquation(colorEquation));
549 }
550 
compareEquations(const EquationStorage::Type color,const EquationStorage::Type alpha) const551 DrawBufferMask BlendStateExt::compareEquations(const EquationStorage::Type color,
552                                                const EquationStorage::Type alpha) const
553 {
554     return EquationStorage::GetDiffMask(mEquationColor, color) |
555            EquationStorage::GetDiffMask(mEquationAlpha, alpha);
556 }
557 
expandFactorValue(const GLenum func) const558 BlendStateExt::FactorStorage::Type BlendStateExt::expandFactorValue(const GLenum func) const
559 {
560     return FactorStorage::GetReplicatedValue(FromGLenum<BlendFactorType>(func), mParameterMask);
561 }
562 
expandFactorValue(const gl::BlendFactorType func) const563 BlendStateExt::FactorStorage::Type BlendStateExt::expandFactorValue(
564     const gl::BlendFactorType func) const
565 {
566     return FactorStorage::GetReplicatedValue(func, mParameterMask);
567 }
568 
expandSrcColorIndexed(const size_t index) const569 BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcColorIndexed(const size_t index) const
570 {
571     ASSERT(index < mDrawBufferCount);
572     return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcColor),
573                                              mParameterMask);
574 }
575 
expandDstColorIndexed(const size_t index) const576 BlendStateExt::FactorStorage::Type BlendStateExt::expandDstColorIndexed(const size_t index) const
577 {
578     ASSERT(index < mDrawBufferCount);
579     return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstColor),
580                                              mParameterMask);
581 }
582 
expandSrcAlphaIndexed(const size_t index) const583 BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcAlphaIndexed(const size_t index) const
584 {
585     ASSERT(index < mDrawBufferCount);
586     return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcAlpha),
587                                              mParameterMask);
588 }
589 
expandDstAlphaIndexed(const size_t index) const590 BlendStateExt::FactorStorage::Type BlendStateExt::expandDstAlphaIndexed(const size_t index) const
591 {
592     ASSERT(index < mDrawBufferCount);
593     return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstAlpha),
594                                              mParameterMask);
595 }
596 
setFactors(const GLenum srcColor,const GLenum dstColor,const GLenum srcAlpha,const GLenum dstAlpha)597 void BlendStateExt::setFactors(const GLenum srcColor,
598                                const GLenum dstColor,
599                                const GLenum srcAlpha,
600                                const GLenum dstAlpha)
601 {
602     const gl::BlendFactorType srcColorFactor = FromGLenum<BlendFactorType>(srcColor);
603     const gl::BlendFactorType dstColorFactor = FromGLenum<BlendFactorType>(dstColor);
604     const gl::BlendFactorType srcAlphaFactor = FromGLenum<BlendFactorType>(srcAlpha);
605     const gl::BlendFactorType dstAlphaFactor = FromGLenum<BlendFactorType>(dstAlpha);
606 
607     mSrcColor = expandFactorValue(srcColorFactor);
608     mDstColor = expandFactorValue(dstColorFactor);
609     mSrcAlpha = expandFactorValue(srcAlphaFactor);
610     mDstAlpha = expandFactorValue(dstAlphaFactor);
611 
612     if (IsExtendedBlendFactor(srcColorFactor) || IsExtendedBlendFactor(dstColorFactor) ||
613         IsExtendedBlendFactor(srcAlphaFactor) || IsExtendedBlendFactor(dstAlphaFactor))
614     {
615         mUsesExtendedBlendFactorMask = mAllEnabledMask;
616     }
617     else
618     {
619         mUsesExtendedBlendFactorMask.reset();
620     }
621 }
622 
setFactorsIndexed(const size_t index,const gl::BlendFactorType srcColorFactor,const gl::BlendFactorType dstColorFactor,const gl::BlendFactorType srcAlphaFactor,const gl::BlendFactorType dstAlphaFactor)623 void BlendStateExt::setFactorsIndexed(const size_t index,
624                                       const gl::BlendFactorType srcColorFactor,
625                                       const gl::BlendFactorType dstColorFactor,
626                                       const gl::BlendFactorType srcAlphaFactor,
627                                       const gl::BlendFactorType dstAlphaFactor)
628 {
629     ASSERT(index < mDrawBufferCount);
630 
631     FactorStorage::SetValueIndexed(index, srcColorFactor, &mSrcColor);
632     FactorStorage::SetValueIndexed(index, dstColorFactor, &mDstColor);
633     FactorStorage::SetValueIndexed(index, srcAlphaFactor, &mSrcAlpha);
634     FactorStorage::SetValueIndexed(index, dstAlphaFactor, &mDstAlpha);
635 
636     const bool isExtended =
637         IsExtendedBlendFactor(srcColorFactor) || IsExtendedBlendFactor(dstColorFactor) ||
638         IsExtendedBlendFactor(srcAlphaFactor) || IsExtendedBlendFactor(dstAlphaFactor);
639     mUsesExtendedBlendFactorMask.set(index, isExtended);
640 }
641 
setFactorsIndexed(const size_t index,const GLenum srcColor,const GLenum dstColor,const GLenum srcAlpha,const GLenum dstAlpha)642 void BlendStateExt::setFactorsIndexed(const size_t index,
643                                       const GLenum srcColor,
644                                       const GLenum dstColor,
645                                       const GLenum srcAlpha,
646                                       const GLenum dstAlpha)
647 {
648     const gl::BlendFactorType srcColorFactor = FromGLenum<BlendFactorType>(srcColor);
649     const gl::BlendFactorType dstColorFactor = FromGLenum<BlendFactorType>(dstColor);
650     const gl::BlendFactorType srcAlphaFactor = FromGLenum<BlendFactorType>(srcAlpha);
651     const gl::BlendFactorType dstAlphaFactor = FromGLenum<BlendFactorType>(dstAlpha);
652 
653     setFactorsIndexed(index, srcColorFactor, dstColorFactor, srcAlphaFactor, dstAlphaFactor);
654 }
655 
setFactorsIndexed(const size_t index,const size_t sourceIndex,const BlendStateExt & source)656 void BlendStateExt::setFactorsIndexed(const size_t index,
657                                       const size_t sourceIndex,
658                                       const BlendStateExt &source)
659 {
660     ASSERT(index < mDrawBufferCount);
661     ASSERT(sourceIndex < source.mDrawBufferCount);
662 
663     const gl::BlendFactorType srcColorFactor =
664         FactorStorage::GetValueIndexed(sourceIndex, source.mSrcColor);
665     const gl::BlendFactorType dstColorFactor =
666         FactorStorage::GetValueIndexed(sourceIndex, source.mDstColor);
667     const gl::BlendFactorType srcAlphaFactor =
668         FactorStorage::GetValueIndexed(sourceIndex, source.mSrcAlpha);
669     const gl::BlendFactorType dstAlphaFactor =
670         FactorStorage::GetValueIndexed(sourceIndex, source.mDstAlpha);
671 
672     FactorStorage::SetValueIndexed(index, srcColorFactor, &mSrcColor);
673     FactorStorage::SetValueIndexed(index, dstColorFactor, &mDstColor);
674     FactorStorage::SetValueIndexed(index, srcAlphaFactor, &mSrcAlpha);
675     FactorStorage::SetValueIndexed(index, dstAlphaFactor, &mDstAlpha);
676 
677     const bool isExtended =
678         IsExtendedBlendFactor(srcColorFactor) || IsExtendedBlendFactor(dstColorFactor) ||
679         IsExtendedBlendFactor(srcAlphaFactor) || IsExtendedBlendFactor(dstAlphaFactor);
680     mUsesExtendedBlendFactorMask.set(index, isExtended);
681 }
682 
compareFactors(const FactorStorage::Type srcColor,const FactorStorage::Type dstColor,const FactorStorage::Type srcAlpha,const FactorStorage::Type dstAlpha) const683 DrawBufferMask BlendStateExt::compareFactors(const FactorStorage::Type srcColor,
684                                              const FactorStorage::Type dstColor,
685                                              const FactorStorage::Type srcAlpha,
686                                              const FactorStorage::Type dstAlpha) const
687 {
688     return FactorStorage::GetDiffMask(mSrcColor, srcColor) |
689            FactorStorage::GetDiffMask(mDstColor, dstColor) |
690            FactorStorage::GetDiffMask(mSrcAlpha, srcAlpha) |
691            FactorStorage::GetDiffMask(mDstAlpha, dstAlpha);
692 }
693 
MinMax(int a,int b,int * minimum,int * maximum)694 static void MinMax(int a, int b, int *minimum, int *maximum)
695 {
696     if (a < b)
697     {
698         *minimum = a;
699         *maximum = b;
700     }
701     else
702     {
703         *minimum = b;
704         *maximum = a;
705     }
706 }
707 
708 template <>
empty() const709 bool RectangleImpl<int>::empty() const
710 {
711     return width == 0 && height == 0;
712 }
713 
714 template <>
empty() const715 bool RectangleImpl<float>::empty() const
716 {
717     return std::abs(width) < std::numeric_limits<float>::epsilon() &&
718            std::abs(height) < std::numeric_limits<float>::epsilon();
719 }
720 
ClipRectangle(const Rectangle & source,const Rectangle & clip,Rectangle * intersection)721 bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
722 {
723     angle::CheckedNumeric<int> sourceX2(source.x);
724     sourceX2 += source.width;
725     if (!sourceX2.IsValid())
726     {
727         return false;
728     }
729     angle::CheckedNumeric<int> sourceY2(source.y);
730     sourceY2 += source.height;
731     if (!sourceY2.IsValid())
732     {
733         return false;
734     }
735 
736     int minSourceX, maxSourceX, minSourceY, maxSourceY;
737     MinMax(source.x, sourceX2.ValueOrDie(), &minSourceX, &maxSourceX);
738     MinMax(source.y, sourceY2.ValueOrDie(), &minSourceY, &maxSourceY);
739 
740     angle::CheckedNumeric<int> clipX2(clip.x);
741     clipX2 += clip.width;
742     if (!clipX2.IsValid())
743     {
744         return false;
745     }
746     angle::CheckedNumeric<int> clipY2(clip.y);
747     clipY2 += clip.height;
748     if (!clipY2.IsValid())
749     {
750         return false;
751     }
752 
753     int minClipX, maxClipX, minClipY, maxClipY;
754     MinMax(clip.x, clipX2.ValueOrDie(), &minClipX, &maxClipX);
755     MinMax(clip.y, clipY2.ValueOrDie(), &minClipY, &maxClipY);
756 
757     if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY ||
758         maxSourceY <= minClipY)
759     {
760         return false;
761     }
762 
763     int x      = std::max(minSourceX, minClipX);
764     int y      = std::max(minSourceY, minClipY);
765     int width  = std::min(maxSourceX, maxClipX) - x;
766     int height = std::min(maxSourceY, maxClipY) - y;
767 
768     if (intersection)
769     {
770         intersection->x      = x;
771         intersection->y      = y;
772         intersection->width  = width;
773         intersection->height = height;
774     }
775     return width != 0 && height != 0;
776 }
777 
GetEnclosingRectangle(const Rectangle & rect1,const Rectangle & rect2,Rectangle * rectUnion)778 void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion)
779 {
780     // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow
781     // are impossible.
782     ASSERT(!rect1.isReversedX() && !rect1.isReversedY());
783     ASSERT(!rect2.isReversedX() && !rect2.isReversedY());
784     ASSERT((angle::CheckedNumeric<int>(rect1.x) + rect1.width).IsValid());
785     ASSERT((angle::CheckedNumeric<int>(rect1.y) + rect1.height).IsValid());
786     ASSERT((angle::CheckedNumeric<int>(rect2.x) + rect2.width).IsValid());
787     ASSERT((angle::CheckedNumeric<int>(rect2.y) + rect2.height).IsValid());
788 
789     // This function calculates a rectangle that covers both input rectangles:
790     //
791     //                     +---------+
792     //          rect1 -->  |         |
793     //                     |     +---+-----+
794     //                     |     |   |     | <-- rect2
795     //                     +-----+---+     |
796     //                           |         |
797     //                           +---------+
798     //
799     //   xy0 = min(rect1.xy0, rect2.xy0)
800     //                    \
801     //                     +---------+-----+
802     //          union -->  |         .     |
803     //                     |     + . + . . +
804     //                     |     .   .     |
805     //                     + . . + . +     |
806     //                     |     .         |
807     //                     +-----+---------+
808     //                                    /
809     //                         xy1 = max(rect1.xy1, rect2.xy1)
810 
811     int x0 = std::min(rect1.x0(), rect2.x0());
812     int y0 = std::min(rect1.y0(), rect2.y0());
813 
814     int x1 = std::max(rect1.x1(), rect2.x1());
815     int y1 = std::max(rect1.y1(), rect2.y1());
816 
817     rectUnion->x      = x0;
818     rectUnion->y      = y0;
819     rectUnion->width  = x1 - x0;
820     rectUnion->height = y1 - y0;
821 }
822 
ExtendRectangle(const Rectangle & source,const Rectangle & extend,Rectangle * extended)823 void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended)
824 {
825     // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow
826     // are impossible.
827     ASSERT(!source.isReversedX() && !source.isReversedY());
828     ASSERT(!extend.isReversedX() && !extend.isReversedY());
829     ASSERT((angle::CheckedNumeric<int>(source.x) + source.width).IsValid());
830     ASSERT((angle::CheckedNumeric<int>(source.y) + source.height).IsValid());
831     ASSERT((angle::CheckedNumeric<int>(extend.x) + extend.width).IsValid());
832     ASSERT((angle::CheckedNumeric<int>(extend.y) + extend.height).IsValid());
833 
834     int x0 = source.x0();
835     int x1 = source.x1();
836     int y0 = source.y0();
837     int y1 = source.y1();
838 
839     const int extendX0 = extend.x0();
840     const int extendX1 = extend.x1();
841     const int extendY0 = extend.y0();
842     const int extendY1 = extend.y1();
843 
844     // For each side of the rectangle, calculate whether it can be extended by the second rectangle.
845     // If so, extend it and continue for the next side with the new dimensions.
846 
847     // Left: Reduce x0 if the second rectangle's vertical edge covers the source's:
848     //
849     //     +--- - - -                +--- - - -
850     //     |                         |
851     //     |  +--------------+       +-----------------+
852     //     |  |    source    |  -->  |       source    |
853     //     |  +--------------+       +-----------------+
854     //     |                         |
855     //     +--- - - -                +--- - - -
856     //
857     const bool enclosesHeight = EnclosesRange(extendY0, extendY1, y0, y1);
858     if (extendX0 < x0 && extendX1 >= x0 && enclosesHeight)
859     {
860         x0 = extendX0;
861     }
862 
863     // Right: Increase x1 simiarly.
864     if (extendX0 <= x1 && extendX1 > x1 && enclosesHeight)
865     {
866         x1 = extendX1;
867     }
868 
869     // Top: Reduce y0 if the second rectangle's horizontal edge covers the source's potentially
870     // extended edge.
871     const bool enclosesWidth = EnclosesRange(extendX0, extendX1, x0, x1);
872     if (extendY0 < y0 && extendY1 >= y0 && enclosesWidth)
873     {
874         y0 = extendY0;
875     }
876 
877     // Right: Increase y1 simiarly.
878     if (extendY0 <= y1 && extendY1 > y1 && enclosesWidth)
879     {
880         y1 = extendY1;
881     }
882 
883     extended->x      = x0;
884     extended->y      = y0;
885     extended->width  = x1 - x0;
886     extended->height = y1 - y0;
887 }
888 
valid() const889 bool Box::valid() const
890 {
891     return width != 0 && height != 0 && depth != 0;
892 }
893 
operator ==(const Box & other) const894 bool Box::operator==(const Box &other) const
895 {
896     return (x == other.x && y == other.y && z == other.z && width == other.width &&
897             height == other.height && depth == other.depth);
898 }
899 
operator !=(const Box & other) const900 bool Box::operator!=(const Box &other) const
901 {
902     return !(*this == other);
903 }
904 
toRect() const905 Rectangle Box::toRect() const
906 {
907     ASSERT(z == 0 && depth == 1);
908     return Rectangle(x, y, width, height);
909 }
910 
coversSameExtent(const Extents & size) const911 bool Box::coversSameExtent(const Extents &size) const
912 {
913     return x == 0 && y == 0 && z == 0 && width == size.width && height == size.height &&
914            depth == size.depth;
915 }
916 
contains(const Box & other) const917 bool Box::contains(const Box &other) const
918 {
919     return x <= other.x && y <= other.y && z <= other.z && x + width >= other.x + other.width &&
920            y + height >= other.y + other.height && z + depth >= other.z + other.depth;
921 }
922 
volume() const923 size_t Box::volume() const
924 {
925     return width * height * depth;
926 }
927 
extend(const Box & other)928 void Box::extend(const Box &other)
929 {
930     // This extends the logic of "ExtendRectangle" to 3 dimensions
931 
932     int x0 = x;
933     int x1 = x + width;
934     int y0 = y;
935     int y1 = y + height;
936     int z0 = z;
937     int z1 = z + depth;
938 
939     const int otherx0 = other.x;
940     const int otherx1 = other.x + other.width;
941     const int othery0 = other.y;
942     const int othery1 = other.y + other.height;
943     const int otherz0 = other.z;
944     const int otherz1 = other.z + other.depth;
945 
946     // For each side of the box, calculate whether it can be extended by the other box.
947     // If so, extend it and continue to the next side with the new dimensions.
948 
949     const bool enclosesWidth  = EnclosesRange(otherx0, otherx1, x0, x1);
950     const bool enclosesHeight = EnclosesRange(othery0, othery1, y0, y1);
951     const bool enclosesDepth  = EnclosesRange(otherz0, otherz1, z0, z1);
952 
953     // Left: Reduce x0 if the other box's Y and Z plane encloses the source
954     if (otherx0 < x0 && otherx1 >= x0 && enclosesHeight && enclosesDepth)
955     {
956         x0 = otherx0;
957     }
958 
959     // Right: Increase x1 simiarly.
960     if (otherx0 <= x1 && otherx1 > x1 && enclosesHeight && enclosesDepth)
961     {
962         x1 = otherx1;
963     }
964 
965     // Bottom: Reduce y0 if the other box's X and Z plane encloses the source
966     if (othery0 < y0 && othery1 >= y0 && enclosesWidth && enclosesDepth)
967     {
968         y0 = othery0;
969     }
970 
971     // Top: Increase y1 simiarly.
972     if (othery0 <= y1 && othery1 > y1 && enclosesWidth && enclosesDepth)
973     {
974         y1 = othery1;
975     }
976 
977     // Front: Reduce z0 if the other box's X and Y plane encloses the source
978     if (otherz0 < z0 && otherz1 >= z0 && enclosesWidth && enclosesHeight)
979     {
980         z0 = otherz0;
981     }
982 
983     // Back: Increase z1 simiarly.
984     if (otherz0 <= z1 && otherz1 > z1 && enclosesWidth && enclosesHeight)
985     {
986         z1 = otherz1;
987     }
988 
989     // Update member var with new dimensions
990     x      = x0;
991     width  = x1 - x0;
992     y      = y0;
993     height = y1 - y0;
994     z      = z0;
995     depth  = z1 - z0;
996 }
997 
ValidateComponentTypeMasks(unsigned long outputTypes,unsigned long inputTypes,unsigned long outputMask,unsigned long inputMask)998 bool ValidateComponentTypeMasks(unsigned long outputTypes,
999                                 unsigned long inputTypes,
1000                                 unsigned long outputMask,
1001                                 unsigned long inputMask)
1002 {
1003     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS <= kMaxComponentTypeMaskIndex,
1004                   "Output/input masks should fit into 16 bits - 1 bit per draw buffer. The "
1005                   "corresponding type masks should fit into 32 bits - 2 bits per draw buffer.");
1006     static_assert(MAX_VERTEX_ATTRIBS <= kMaxComponentTypeMaskIndex,
1007                   "Output/input masks should fit into 16 bits - 1 bit per attrib. The "
1008                   "corresponding type masks should fit into 32 bits - 2 bits per attrib.");
1009 
1010     // For performance reasons, draw buffer and attribute type validation is done using bit masks.
1011     // We store two bits representing the type split, with the low bit in the lower 16 bits of the
1012     // variable, and the high bit in the upper 16 bits of the variable. This is done so we can AND
1013     // with the elswewhere used DrawBufferMask or AttributeMask.
1014 
1015     // OR the masks with themselves, shifted 16 bits. This is to match our split type bits.
1016     outputMask |= (outputMask << kMaxComponentTypeMaskIndex);
1017     inputMask |= (inputMask << kMaxComponentTypeMaskIndex);
1018 
1019     // To validate:
1020     // 1. Remove any indexes that are not enabled in the input (& inputMask)
1021     // 2. Remove any indexes that exist in output, but not in input (& outputMask)
1022     // 3. Use == to verify equality
1023     return (outputTypes & inputMask) == ((inputTypes & outputMask) & inputMask);
1024 }
1025 
GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> & binding)1026 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding)
1027 {
1028     Buffer *buffer = binding.get();
1029     if (buffer == nullptr)
1030     {
1031         return 0;
1032     }
1033 
1034     const GLsizeiptr bufferSize = static_cast<GLsizeiptr>(buffer->getSize());
1035 
1036     if (binding.getSize() == 0)
1037     {
1038         return bufferSize;
1039     }
1040 
1041     const GLintptr offset = binding.getOffset();
1042     const GLsizeiptr size = binding.getSize();
1043 
1044     ASSERT(offset >= 0 && bufferSize >= 0);
1045 
1046     if (bufferSize <= offset)
1047     {
1048         return 0;
1049     }
1050 
1051     return std::min(size, bufferSize - offset);
1052 }
1053 
1054 }  // namespace gl
1055    //
1056 namespace angle
1057 {
CompressBlob(const size_t cacheSize,const uint8_t * cacheData,MemoryBuffer * compressedData)1058 bool CompressBlob(const size_t cacheSize, const uint8_t *cacheData, MemoryBuffer *compressedData)
1059 {
1060     uLong uncompressedSize       = static_cast<uLong>(cacheSize);
1061     uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize);
1062     uLong actualCompressedSize   = expectedCompressedSize;
1063 
1064     // Allocate memory.
1065     if (!compressedData->resize(expectedCompressedSize))
1066     {
1067         ERR() << "Failed to allocate memory for compression";
1068         return false;
1069     }
1070 
1071     int zResult = zlib_internal::GzipCompressHelper(compressedData->data(), &actualCompressedSize,
1072                                                     cacheData, uncompressedSize, nullptr, nullptr);
1073 
1074     if (zResult != Z_OK)
1075     {
1076         ERR() << "Failed to compress cache data: " << zResult;
1077         return false;
1078     }
1079 
1080     // Trim to actual size.
1081     ASSERT(actualCompressedSize <= expectedCompressedSize);
1082     compressedData->setSize(actualCompressedSize);
1083 
1084     return true;
1085 }
1086 
DecompressBlob(const uint8_t * compressedData,const size_t compressedSize,size_t maxUncompressedDataSize,MemoryBuffer * uncompressedData)1087 bool DecompressBlob(const uint8_t *compressedData,
1088                     const size_t compressedSize,
1089                     size_t maxUncompressedDataSize,
1090                     MemoryBuffer *uncompressedData)
1091 {
1092     // Call zlib function to decompress.
1093     uint32_t uncompressedSize =
1094         zlib_internal::GetGzipUncompressedSize(compressedData, compressedSize);
1095 
1096     if (uncompressedSize == 0)
1097     {
1098         ERR() << "Decompressed data size is zero. Wrong or corrupted data? (compressed size is: "
1099               << compressedSize << ")";
1100         return false;
1101     }
1102 
1103     if (uncompressedSize > maxUncompressedDataSize)
1104     {
1105         ERR() << "Decompressed data size is larger than the maximum supported (" << uncompressedSize
1106               << " vs " << maxUncompressedDataSize << ")";
1107         return false;
1108     }
1109 
1110     // Allocate enough memory.
1111     if (!uncompressedData->resize(uncompressedSize))
1112     {
1113         ERR() << "Failed to allocate memory for decompression";
1114         return false;
1115     }
1116 
1117     uLong destLen = uncompressedSize;
1118     int zResult   = zlib_internal::GzipUncompressHelper(
1119         uncompressedData->data(), &destLen, compressedData, static_cast<uLong>(compressedSize));
1120 
1121     if (zResult != Z_OK)
1122     {
1123         WARN() << "Failed to decompress data: " << zResult << "\n";
1124         return false;
1125     }
1126 
1127     // Trim to actual size.
1128     ASSERT(destLen <= uncompressedSize);
1129     uncompressedData->setSize(destLen);
1130 
1131     return true;
1132 }
1133 
GenerateCRC32(const uint8_t * data,size_t size)1134 uint32_t GenerateCRC32(const uint8_t *data, size_t size)
1135 {
1136     return UpdateCRC32(InitCRC32(), data, size);
1137 }
1138 
InitCRC32()1139 uint32_t InitCRC32()
1140 {
1141     // To get required initial value for the crc, need to pass nullptr into buf.
1142     return static_cast<uint32_t>(crc32_z(0u, nullptr, 0u));
1143 }
1144 
UpdateCRC32(uint32_t prevCrc32,const uint8_t * data,size_t size)1145 uint32_t UpdateCRC32(uint32_t prevCrc32, const uint8_t *data, size_t size)
1146 {
1147     return static_cast<uint32_t>(crc32_z(static_cast<uLong>(prevCrc32), data, size));
1148 }
1149 
1150 UnlockedTailCall::UnlockedTailCall() = default;
1151 
~UnlockedTailCall()1152 UnlockedTailCall::~UnlockedTailCall()
1153 {
1154     ASSERT(mCalls.empty());
1155 }
1156 
add(CallType && call)1157 void UnlockedTailCall::add(CallType &&call)
1158 {
1159     mCalls.push_back(std::move(call));
1160 }
1161 
runImpl(void * resultOut)1162 void UnlockedTailCall::runImpl(void *resultOut)
1163 {
1164     if (mCalls.empty())
1165     {
1166         return;
1167     }
1168     // Clear `mCalls` before calling, because Android sometimes calls back into ANGLE through EGL
1169     // calls which don't expect there to be any pre-existing tail calls.
1170     auto calls(std::move(mCalls));
1171     ASSERT(mCalls.empty());
1172     for (CallType &call : calls)
1173     {
1174         call(resultOut);
1175     }
1176 }
1177 }  // namespace angle
1178