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