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