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 } // anonymous namespace
40
RasterizerState()41 RasterizerState::RasterizerState()
42 {
43 memset(this, 0, sizeof(RasterizerState));
44
45 rasterizerDiscard = false;
46 cullFace = false;
47 cullMode = CullFaceMode::Back;
48 frontFace = GL_CCW;
49 polygonOffsetFill = false;
50 polygonOffsetFactor = 0.0f;
51 polygonOffsetUnits = 0.0f;
52 pointDrawMode = false;
53 multiSample = false;
54 dither = true;
55 }
56
RasterizerState(const RasterizerState & other)57 RasterizerState::RasterizerState(const RasterizerState &other)
58 {
59 memcpy(this, &other, sizeof(RasterizerState));
60 }
61
operator ==(const RasterizerState & a,const RasterizerState & b)62 bool operator==(const RasterizerState &a, const RasterizerState &b)
63 {
64 return memcmp(&a, &b, sizeof(RasterizerState)) == 0;
65 }
66
operator !=(const RasterizerState & a,const RasterizerState & b)67 bool operator!=(const RasterizerState &a, const RasterizerState &b)
68 {
69 return !(a == b);
70 }
71
BlendState()72 BlendState::BlendState()
73 {
74 memset(this, 0, sizeof(BlendState));
75
76 blend = false;
77 sourceBlendRGB = GL_ONE;
78 sourceBlendAlpha = GL_ONE;
79 destBlendRGB = GL_ZERO;
80 destBlendAlpha = GL_ZERO;
81 blendEquationRGB = GL_FUNC_ADD;
82 blendEquationAlpha = GL_FUNC_ADD;
83 colorMaskRed = true;
84 colorMaskGreen = true;
85 colorMaskBlue = true;
86 colorMaskAlpha = true;
87 }
88
BlendState(const BlendState & other)89 BlendState::BlendState(const BlendState &other)
90 {
91 memcpy(this, &other, sizeof(BlendState));
92 }
93
operator ==(const BlendState & a,const BlendState & b)94 bool operator==(const BlendState &a, const BlendState &b)
95 {
96 return memcmp(&a, &b, sizeof(BlendState)) == 0;
97 }
98
operator !=(const BlendState & a,const BlendState & b)99 bool operator!=(const BlendState &a, const BlendState &b)
100 {
101 return !(a == b);
102 }
103
DepthStencilState()104 DepthStencilState::DepthStencilState()
105 {
106 memset(this, 0, sizeof(DepthStencilState));
107
108 depthTest = false;
109 depthFunc = GL_LESS;
110 depthMask = true;
111 stencilTest = false;
112 stencilFunc = GL_ALWAYS;
113 stencilMask = static_cast<GLuint>(-1);
114 stencilWritemask = static_cast<GLuint>(-1);
115 stencilBackFunc = GL_ALWAYS;
116 stencilBackMask = static_cast<GLuint>(-1);
117 stencilBackWritemask = static_cast<GLuint>(-1);
118 stencilFail = GL_KEEP;
119 stencilPassDepthFail = GL_KEEP;
120 stencilPassDepthPass = GL_KEEP;
121 stencilBackFail = GL_KEEP;
122 stencilBackPassDepthFail = GL_KEEP;
123 stencilBackPassDepthPass = GL_KEEP;
124 }
125
DepthStencilState(const DepthStencilState & other)126 DepthStencilState::DepthStencilState(const DepthStencilState &other)
127 {
128 memcpy(this, &other, sizeof(DepthStencilState));
129 }
130
isDepthMaskedOut() const131 bool DepthStencilState::isDepthMaskedOut() const
132 {
133 return !depthMask;
134 }
135
isStencilMaskedOut() const136 bool DepthStencilState::isStencilMaskedOut() const
137 {
138 return (stencilMask & stencilWritemask) == 0;
139 }
140
isStencilNoOp() const141 bool DepthStencilState::isStencilNoOp() const
142 {
143 return isStencilMaskedOut() ||
144 IsStencilNoOp(stencilFunc, stencilFail, stencilPassDepthFail, stencilPassDepthPass);
145 }
146
isStencilBackNoOp() const147 bool DepthStencilState::isStencilBackNoOp() const
148 {
149 const bool isStencilBackMaskedOut = (stencilBackMask & stencilBackWritemask) == 0;
150 return isStencilBackMaskedOut ||
151 IsStencilNoOp(stencilBackFunc, stencilBackFail, stencilBackPassDepthFail,
152 stencilBackPassDepthPass);
153 }
154
operator ==(const DepthStencilState & a,const DepthStencilState & b)155 bool operator==(const DepthStencilState &a, const DepthStencilState &b)
156 {
157 return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
158 }
159
operator !=(const DepthStencilState & a,const DepthStencilState & b)160 bool operator!=(const DepthStencilState &a, const DepthStencilState &b)
161 {
162 return !(a == b);
163 }
164
SamplerState()165 SamplerState::SamplerState()
166 {
167 memset(this, 0, sizeof(SamplerState));
168
169 setMinFilter(GL_NEAREST_MIPMAP_LINEAR);
170 setMagFilter(GL_LINEAR);
171 setWrapS(GL_REPEAT);
172 setWrapT(GL_REPEAT);
173 setWrapR(GL_REPEAT);
174 setMaxAnisotropy(1.0f);
175 setMinLod(-1000.0f);
176 setMaxLod(1000.0f);
177 setCompareMode(GL_NONE);
178 setCompareFunc(GL_LEQUAL);
179 setSRGBDecode(GL_DECODE_EXT);
180 }
181
182 SamplerState::SamplerState(const SamplerState &other) = default;
183
184 SamplerState &SamplerState::operator=(const SamplerState &other) = default;
185
186 // static
CreateDefaultForTarget(TextureType type)187 SamplerState SamplerState::CreateDefaultForTarget(TextureType type)
188 {
189 SamplerState state;
190
191 // According to OES_EGL_image_external and ARB_texture_rectangle: For external textures, the
192 // default min filter is GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
193 if (type == TextureType::External || type == TextureType::Rectangle)
194 {
195 state.mMinFilter = GL_LINEAR;
196 state.mWrapS = GL_CLAMP_TO_EDGE;
197 state.mWrapT = GL_CLAMP_TO_EDGE;
198 }
199
200 return state;
201 }
202
setMinFilter(GLenum minFilter)203 bool SamplerState::setMinFilter(GLenum minFilter)
204 {
205 if (mMinFilter != minFilter)
206 {
207 mMinFilter = minFilter;
208 mCompleteness.typed.minFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(minFilter));
209 return true;
210 }
211 return false;
212 }
213
setMagFilter(GLenum magFilter)214 bool SamplerState::setMagFilter(GLenum magFilter)
215 {
216 if (mMagFilter != magFilter)
217 {
218 mMagFilter = magFilter;
219 mCompleteness.typed.magFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(magFilter));
220 return true;
221 }
222 return false;
223 }
224
setWrapS(GLenum wrapS)225 bool SamplerState::setWrapS(GLenum wrapS)
226 {
227 if (mWrapS != wrapS)
228 {
229 mWrapS = wrapS;
230 mCompleteness.typed.wrapS = static_cast<uint8_t>(FromGLenum<WrapMode>(wrapS));
231 return true;
232 }
233 return false;
234 }
235
setWrapT(GLenum wrapT)236 bool SamplerState::setWrapT(GLenum wrapT)
237 {
238 if (mWrapT != wrapT)
239 {
240 mWrapT = wrapT;
241 updateWrapTCompareMode();
242 return true;
243 }
244 return false;
245 }
246
setWrapR(GLenum wrapR)247 bool SamplerState::setWrapR(GLenum wrapR)
248 {
249 if (mWrapR != wrapR)
250 {
251 mWrapR = wrapR;
252 return true;
253 }
254 return false;
255 }
256
setMaxAnisotropy(float maxAnisotropy)257 bool SamplerState::setMaxAnisotropy(float maxAnisotropy)
258 {
259 if (mMaxAnisotropy != maxAnisotropy)
260 {
261 mMaxAnisotropy = maxAnisotropy;
262 return true;
263 }
264 return false;
265 }
266
setMinLod(GLfloat minLod)267 bool SamplerState::setMinLod(GLfloat minLod)
268 {
269 if (mMinLod != minLod)
270 {
271 mMinLod = minLod;
272 return true;
273 }
274 return false;
275 }
276
setMaxLod(GLfloat maxLod)277 bool SamplerState::setMaxLod(GLfloat maxLod)
278 {
279 if (mMaxLod != maxLod)
280 {
281 mMaxLod = maxLod;
282 return true;
283 }
284 return false;
285 }
286
setCompareMode(GLenum compareMode)287 bool SamplerState::setCompareMode(GLenum compareMode)
288 {
289 if (mCompareMode != compareMode)
290 {
291 mCompareMode = compareMode;
292 updateWrapTCompareMode();
293 return true;
294 }
295 return false;
296 }
297
setCompareFunc(GLenum compareFunc)298 bool SamplerState::setCompareFunc(GLenum compareFunc)
299 {
300 if (mCompareFunc != compareFunc)
301 {
302 mCompareFunc = compareFunc;
303 return true;
304 }
305 return false;
306 }
307
setSRGBDecode(GLenum sRGBDecode)308 bool SamplerState::setSRGBDecode(GLenum sRGBDecode)
309 {
310 if (mSRGBDecode != sRGBDecode)
311 {
312 mSRGBDecode = sRGBDecode;
313 return true;
314 }
315 return false;
316 }
317
setBorderColor(const ColorGeneric & color)318 bool SamplerState::setBorderColor(const ColorGeneric &color)
319 {
320 if (mBorderColor != color)
321 {
322 mBorderColor = color;
323 return true;
324 }
325 return false;
326 }
327
updateWrapTCompareMode()328 void SamplerState::updateWrapTCompareMode()
329 {
330 uint8_t wrap = static_cast<uint8_t>(FromGLenum<WrapMode>(mWrapT));
331 uint8_t compare = static_cast<uint8_t>(mCompareMode == GL_NONE ? 0x10 : 0x00);
332 mCompleteness.typed.wrapTCompareMode = wrap | compare;
333 }
334
ImageUnit()335 ImageUnit::ImageUnit()
336 : texture(), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
337 {}
338
339 ImageUnit::ImageUnit(const ImageUnit &other) = default;
340
341 ImageUnit::~ImageUnit() = default;
342
BlendStateExt(const size_t drawBuffers)343 BlendStateExt::BlendStateExt(const size_t drawBuffers)
344 : mMaxFactorMask(FactorStorage::GetMask(drawBuffers)),
345 mSrcColor(FactorStorage::GetReplicatedValue(BlendFactorType::One, mMaxFactorMask)),
346 mDstColor(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mMaxFactorMask)),
347 mSrcAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::One, mMaxFactorMask)),
348 mDstAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mMaxFactorMask)),
349 mMaxEquationMask(EquationStorage::GetMask(drawBuffers)),
350 mEquationColor(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mMaxEquationMask)),
351 mEquationAlpha(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mMaxEquationMask)),
352 mMaxColorMask(ColorMaskStorage::GetMask(drawBuffers)),
353 mColorMask(ColorMaskStorage::GetReplicatedValue(PackColorMask(true, true, true, true),
354 mMaxColorMask)),
355 mMaxEnabledMask(0xFF >> (8 - drawBuffers)),
356 mEnabledMask(),
357 mMaxDrawBuffers(drawBuffers)
358 {}
359
360 BlendStateExt::BlendStateExt(const BlendStateExt &other) = default;
361
362 BlendStateExt &BlendStateExt::operator=(const BlendStateExt &other) = default;
363
setEnabled(const bool enabled)364 void BlendStateExt::setEnabled(const bool enabled)
365 {
366 mEnabledMask = enabled ? mMaxEnabledMask : DrawBufferMask::Zero();
367 }
368
setEnabledIndexed(const size_t index,const bool enabled)369 void BlendStateExt::setEnabledIndexed(const size_t index, const bool enabled)
370 {
371 ASSERT(index < mMaxDrawBuffers);
372 mEnabledMask.set(index, enabled);
373 }
374
expandColorMaskValue(const bool red,const bool green,const bool blue,const bool alpha) const375 BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskValue(const bool red,
376 const bool green,
377 const bool blue,
378 const bool alpha) const
379 {
380 return BlendStateExt::ColorMaskStorage::GetReplicatedValue(
381 PackColorMask(red, green, blue, alpha), mMaxColorMask);
382 }
383
expandColorMaskIndexed(const size_t index) const384 BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskIndexed(
385 const size_t index) const
386 {
387 return ColorMaskStorage::GetReplicatedValue(
388 ColorMaskStorage::GetValueIndexed(index, mColorMask), mMaxColorMask);
389 }
390
setColorMask(const bool red,const bool green,const bool blue,const bool alpha)391 void BlendStateExt::setColorMask(const bool red,
392 const bool green,
393 const bool blue,
394 const bool alpha)
395 {
396 mColorMask = expandColorMaskValue(red, green, blue, alpha);
397 }
398
setColorMaskIndexed(const size_t index,const uint8_t value)399 void BlendStateExt::setColorMaskIndexed(const size_t index, const uint8_t value)
400 {
401 ASSERT(index < mMaxDrawBuffers);
402 ASSERT(value <= 0xF);
403 ColorMaskStorage::SetValueIndexed(index, value, &mColorMask);
404 }
405
setColorMaskIndexed(const size_t index,const bool red,const bool green,const bool blue,const bool alpha)406 void BlendStateExt::setColorMaskIndexed(const size_t index,
407 const bool red,
408 const bool green,
409 const bool blue,
410 const bool alpha)
411 {
412 ASSERT(index < mMaxDrawBuffers);
413 ColorMaskStorage::SetValueIndexed(index, PackColorMask(red, green, blue, alpha), &mColorMask);
414 }
415
getColorMaskIndexed(const size_t index) const416 uint8_t BlendStateExt::getColorMaskIndexed(const size_t index) const
417 {
418 ASSERT(index < mMaxDrawBuffers);
419 return ColorMaskStorage::GetValueIndexed(index, mColorMask);
420 }
421
getColorMaskIndexed(const size_t index,bool * red,bool * green,bool * blue,bool * alpha) const422 void BlendStateExt::getColorMaskIndexed(const size_t index,
423 bool *red,
424 bool *green,
425 bool *blue,
426 bool *alpha) const
427 {
428 ASSERT(index < mMaxDrawBuffers);
429 UnpackColorMask(ColorMaskStorage::GetValueIndexed(index, mColorMask), red, green, blue, alpha);
430 }
431
compareColorMask(ColorMaskStorage::Type other) const432 DrawBufferMask BlendStateExt::compareColorMask(ColorMaskStorage::Type other) const
433 {
434 return ColorMaskStorage::GetDiffMask(mColorMask, other);
435 }
436
expandEquationValue(const GLenum mode) const437 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue(const GLenum mode) const
438 {
439 return EquationStorage::GetReplicatedValue(FromGLenum<BlendEquationType>(mode),
440 mMaxEquationMask);
441 }
442
expandEquationColorIndexed(const size_t index) const443 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationColorIndexed(
444 const size_t index) const
445 {
446 return EquationStorage::GetReplicatedValue(
447 EquationStorage::GetValueIndexed(index, mEquationColor), mMaxEquationMask);
448 }
449
expandEquationAlphaIndexed(const size_t index) const450 BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationAlphaIndexed(
451 const size_t index) const
452 {
453 return EquationStorage::GetReplicatedValue(
454 EquationStorage::GetValueIndexed(index, mEquationAlpha), mMaxEquationMask);
455 }
456
setEquations(const GLenum modeColor,const GLenum modeAlpha)457 void BlendStateExt::setEquations(const GLenum modeColor, const GLenum modeAlpha)
458 {
459 mEquationColor = expandEquationValue(modeColor);
460 mEquationAlpha = expandEquationValue(modeAlpha);
461 }
462
setEquationsIndexed(const size_t index,const GLenum modeColor,const GLenum modeAlpha)463 void BlendStateExt::setEquationsIndexed(const size_t index,
464 const GLenum modeColor,
465 const GLenum modeAlpha)
466 {
467 ASSERT(index < mMaxDrawBuffers);
468 EquationStorage::SetValueIndexed(index, FromGLenum<BlendEquationType>(modeColor),
469 &mEquationColor);
470 EquationStorage::SetValueIndexed(index, FromGLenum<BlendEquationType>(modeAlpha),
471 &mEquationAlpha);
472 }
473
setEquationsIndexed(const size_t index,const size_t sourceIndex,const BlendStateExt & source)474 void BlendStateExt::setEquationsIndexed(const size_t index,
475 const size_t sourceIndex,
476 const BlendStateExt &source)
477 {
478 ASSERT(index < mMaxDrawBuffers);
479 ASSERT(sourceIndex < source.mMaxDrawBuffers);
480 EquationStorage::SetValueIndexed(
481 index, EquationStorage::GetValueIndexed(sourceIndex, source.mEquationColor),
482 &mEquationColor);
483 EquationStorage::SetValueIndexed(
484 index, EquationStorage::GetValueIndexed(sourceIndex, source.mEquationAlpha),
485 &mEquationAlpha);
486 }
487
getEquationColorIndexed(size_t index) const488 GLenum BlendStateExt::getEquationColorIndexed(size_t index) const
489 {
490 ASSERT(index < mMaxDrawBuffers);
491 return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationColor));
492 }
493
getEquationAlphaIndexed(size_t index) const494 GLenum BlendStateExt::getEquationAlphaIndexed(size_t index) const
495 {
496 ASSERT(index < mMaxDrawBuffers);
497 return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationAlpha));
498 }
499
compareEquations(const EquationStorage::Type color,const EquationStorage::Type alpha) const500 DrawBufferMask BlendStateExt::compareEquations(const EquationStorage::Type color,
501 const EquationStorage::Type alpha) const
502 {
503 return EquationStorage::GetDiffMask(mEquationColor, color) |
504 EquationStorage::GetDiffMask(mEquationAlpha, alpha);
505 }
506
expandFactorValue(const GLenum func) const507 BlendStateExt::FactorStorage::Type BlendStateExt::expandFactorValue(const GLenum func) const
508 {
509 return FactorStorage::GetReplicatedValue(FromGLenum<BlendFactorType>(func), mMaxFactorMask);
510 }
511
expandSrcColorIndexed(const size_t index) const512 BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcColorIndexed(const size_t index) const
513 {
514 ASSERT(index < mMaxDrawBuffers);
515 return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcColor),
516 mMaxFactorMask);
517 }
518
expandDstColorIndexed(const size_t index) const519 BlendStateExt::FactorStorage::Type BlendStateExt::expandDstColorIndexed(const size_t index) const
520 {
521 ASSERT(index < mMaxDrawBuffers);
522 return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstColor),
523 mMaxFactorMask);
524 }
525
expandSrcAlphaIndexed(const size_t index) const526 BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcAlphaIndexed(const size_t index) const
527 {
528 ASSERT(index < mMaxDrawBuffers);
529 return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcAlpha),
530 mMaxFactorMask);
531 }
532
expandDstAlphaIndexed(const size_t index) const533 BlendStateExt::FactorStorage::Type BlendStateExt::expandDstAlphaIndexed(const size_t index) const
534 {
535 ASSERT(index < mMaxDrawBuffers);
536 return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstAlpha),
537 mMaxFactorMask);
538 }
539
setFactors(const GLenum srcColor,const GLenum dstColor,const GLenum srcAlpha,const GLenum dstAlpha)540 void BlendStateExt::setFactors(const GLenum srcColor,
541 const GLenum dstColor,
542 const GLenum srcAlpha,
543 const GLenum dstAlpha)
544 {
545 mSrcColor = expandFactorValue(srcColor);
546 mDstColor = expandFactorValue(dstColor);
547 mSrcAlpha = expandFactorValue(srcAlpha);
548 mDstAlpha = expandFactorValue(dstAlpha);
549 }
550
setFactorsIndexed(const size_t index,const GLenum srcColor,const GLenum dstColor,const GLenum srcAlpha,const GLenum dstAlpha)551 void BlendStateExt::setFactorsIndexed(const size_t index,
552 const GLenum srcColor,
553 const GLenum dstColor,
554 const GLenum srcAlpha,
555 const GLenum dstAlpha)
556 {
557 ASSERT(index < mMaxDrawBuffers);
558 FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(srcColor), &mSrcColor);
559 FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(dstColor), &mDstColor);
560 FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(srcAlpha), &mSrcAlpha);
561 FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(dstAlpha), &mDstAlpha);
562 }
563
setFactorsIndexed(const size_t index,const size_t sourceIndex,const BlendStateExt & source)564 void BlendStateExt::setFactorsIndexed(const size_t index,
565 const size_t sourceIndex,
566 const BlendStateExt &source)
567 {
568 ASSERT(index < mMaxDrawBuffers);
569 ASSERT(sourceIndex < source.mMaxDrawBuffers);
570 FactorStorage::SetValueIndexed(
571 index, FactorStorage::GetValueIndexed(sourceIndex, source.mSrcColor), &mSrcColor);
572 FactorStorage::SetValueIndexed(
573 index, FactorStorage::GetValueIndexed(sourceIndex, source.mDstColor), &mDstColor);
574 FactorStorage::SetValueIndexed(
575 index, FactorStorage::GetValueIndexed(sourceIndex, source.mSrcAlpha), &mSrcAlpha);
576 FactorStorage::SetValueIndexed(
577 index, FactorStorage::GetValueIndexed(sourceIndex, source.mDstAlpha), &mDstAlpha);
578 }
579
getSrcColorIndexed(size_t index) const580 GLenum BlendStateExt::getSrcColorIndexed(size_t index) const
581 {
582 ASSERT(index < mMaxDrawBuffers);
583 return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcColor));
584 }
585
getDstColorIndexed(size_t index) const586 GLenum BlendStateExt::getDstColorIndexed(size_t index) const
587 {
588 ASSERT(index < mMaxDrawBuffers);
589 return ToGLenum(FactorStorage::GetValueIndexed(index, mDstColor));
590 }
591
getSrcAlphaIndexed(size_t index) const592 GLenum BlendStateExt::getSrcAlphaIndexed(size_t index) const
593 {
594 ASSERT(index < mMaxDrawBuffers);
595 return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcAlpha));
596 }
597
getDstAlphaIndexed(size_t index) const598 GLenum BlendStateExt::getDstAlphaIndexed(size_t index) const
599 {
600 ASSERT(index < mMaxDrawBuffers);
601 return ToGLenum(FactorStorage::GetValueIndexed(index, mDstAlpha));
602 }
603
compareFactors(const FactorStorage::Type srcColor,const FactorStorage::Type dstColor,const FactorStorage::Type srcAlpha,const FactorStorage::Type dstAlpha) const604 DrawBufferMask BlendStateExt::compareFactors(const FactorStorage::Type srcColor,
605 const FactorStorage::Type dstColor,
606 const FactorStorage::Type srcAlpha,
607 const FactorStorage::Type dstAlpha) const
608 {
609 return FactorStorage::GetDiffMask(mSrcColor, srcColor) |
610 FactorStorage::GetDiffMask(mDstColor, dstColor) |
611 FactorStorage::GetDiffMask(mSrcAlpha, srcAlpha) |
612 FactorStorage::GetDiffMask(mDstAlpha, dstAlpha);
613 }
614
MinMax(int a,int b,int * minimum,int * maximum)615 static void MinMax(int a, int b, int *minimum, int *maximum)
616 {
617 if (a < b)
618 {
619 *minimum = a;
620 *maximum = b;
621 }
622 else
623 {
624 *minimum = b;
625 *maximum = a;
626 }
627 }
628
629 template <>
empty() const630 bool RectangleImpl<int>::empty() const
631 {
632 return width == 0 && height == 0;
633 }
634
635 template <>
empty() const636 bool RectangleImpl<float>::empty() const
637 {
638 return std::abs(width) < std::numeric_limits<float>::epsilon() &&
639 std::abs(height) < std::numeric_limits<float>::epsilon();
640 }
641
ClipRectangle(const Rectangle & source,const Rectangle & clip,Rectangle * intersection)642 bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
643 {
644 angle::CheckedNumeric<int> sourceX2(source.x);
645 sourceX2 += source.width;
646 if (!sourceX2.IsValid())
647 {
648 return false;
649 }
650 angle::CheckedNumeric<int> sourceY2(source.y);
651 sourceY2 += source.height;
652 if (!sourceY2.IsValid())
653 {
654 return false;
655 }
656
657 int minSourceX, maxSourceX, minSourceY, maxSourceY;
658 MinMax(source.x, sourceX2.ValueOrDie(), &minSourceX, &maxSourceX);
659 MinMax(source.y, sourceY2.ValueOrDie(), &minSourceY, &maxSourceY);
660
661 angle::CheckedNumeric<int> clipX2(clip.x);
662 clipX2 += clip.width;
663 if (!clipX2.IsValid())
664 {
665 return false;
666 }
667 angle::CheckedNumeric<int> clipY2(clip.y);
668 clipY2 += clip.height;
669 if (!clipY2.IsValid())
670 {
671 return false;
672 }
673
674 int minClipX, maxClipX, minClipY, maxClipY;
675 MinMax(clip.x, clipX2.ValueOrDie(), &minClipX, &maxClipX);
676 MinMax(clip.y, clipY2.ValueOrDie(), &minClipY, &maxClipY);
677
678 if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY ||
679 maxSourceY <= minClipY)
680 {
681 return false;
682 }
683
684 int x = std::max(minSourceX, minClipX);
685 int y = std::max(minSourceY, minClipY);
686 int width = std::min(maxSourceX, maxClipX) - x;
687 int height = std::min(maxSourceY, maxClipY) - y;
688
689 if (intersection)
690 {
691 intersection->x = x;
692 intersection->y = y;
693 intersection->width = width;
694 intersection->height = height;
695 }
696 return width != 0 && height != 0;
697 }
698
GetEnclosingRectangle(const Rectangle & rect1,const Rectangle & rect2,Rectangle * rectUnion)699 void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion)
700 {
701 // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow
702 // are impossible.
703 ASSERT(!rect1.isReversedX() && !rect1.isReversedY());
704 ASSERT(!rect2.isReversedX() && !rect2.isReversedY());
705 ASSERT((angle::CheckedNumeric<int>(rect1.x) + rect1.width).IsValid());
706 ASSERT((angle::CheckedNumeric<int>(rect1.y) + rect1.height).IsValid());
707 ASSERT((angle::CheckedNumeric<int>(rect2.x) + rect2.width).IsValid());
708 ASSERT((angle::CheckedNumeric<int>(rect2.y) + rect2.height).IsValid());
709
710 // This function calculates a rectangle that covers both input rectangles:
711 //
712 // +---------+
713 // rect1 --> | |
714 // | +---+-----+
715 // | | | | <-- rect2
716 // +-----+---+ |
717 // | |
718 // +---------+
719 //
720 // xy0 = min(rect1.xy0, rect2.xy0)
721 // \
722 // +---------+-----+
723 // union --> | . |
724 // | + . + . . +
725 // | . . |
726 // + . . + . + |
727 // | . |
728 // +-----+---------+
729 // /
730 // xy1 = max(rect1.xy1, rect2.xy1)
731
732 int x0 = std::min(rect1.x0(), rect2.x0());
733 int y0 = std::min(rect1.y0(), rect2.y0());
734
735 int x1 = std::max(rect1.x1(), rect2.x1());
736 int y1 = std::max(rect1.y1(), rect2.y1());
737
738 rectUnion->x = x0;
739 rectUnion->y = y0;
740 rectUnion->width = x1 - x0;
741 rectUnion->height = y1 - y0;
742 }
743
ExtendRectangle(const Rectangle & source,const Rectangle & extend,Rectangle * extended)744 void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended)
745 {
746 // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow
747 // are impossible.
748 ASSERT(!source.isReversedX() && !source.isReversedY());
749 ASSERT(!extend.isReversedX() && !extend.isReversedY());
750 ASSERT((angle::CheckedNumeric<int>(source.x) + source.width).IsValid());
751 ASSERT((angle::CheckedNumeric<int>(source.y) + source.height).IsValid());
752 ASSERT((angle::CheckedNumeric<int>(extend.x) + extend.width).IsValid());
753 ASSERT((angle::CheckedNumeric<int>(extend.y) + extend.height).IsValid());
754
755 int x0 = source.x0();
756 int x1 = source.x1();
757 int y0 = source.y0();
758 int y1 = source.y1();
759
760 const int extendX0 = extend.x0();
761 const int extendX1 = extend.x1();
762 const int extendY0 = extend.y0();
763 const int extendY1 = extend.y1();
764
765 // For each side of the rectangle, calculate whether it can be extended by the second rectangle.
766 // If so, extend it and continue for the next side with the new dimensions.
767
768 // Left: Reduce x0 if the second rectangle's vertical edge covers the source's:
769 //
770 // +--- - - - +--- - - -
771 // | |
772 // | +--------------+ +-----------------+
773 // | | source | --> | source |
774 // | +--------------+ +-----------------+
775 // | |
776 // +--- - - - +--- - - -
777 //
778 const bool enclosesHeight = EnclosesRange(extendY0, extendY1, y0, y1);
779 if (extendX0 < x0 && extendX1 >= x0 && enclosesHeight)
780 {
781 x0 = extendX0;
782 }
783
784 // Right: Increase x1 simiarly.
785 if (extendX0 <= x1 && extendX1 > x1 && enclosesHeight)
786 {
787 x1 = extendX1;
788 }
789
790 // Top: Reduce y0 if the second rectangle's horizontal edge covers the source's potentially
791 // extended edge.
792 const bool enclosesWidth = EnclosesRange(extendX0, extendX1, x0, x1);
793 if (extendY0 < y0 && extendY1 >= y0 && enclosesWidth)
794 {
795 y0 = extendY0;
796 }
797
798 // Right: Increase y1 simiarly.
799 if (extendY0 <= y1 && extendY1 > y1 && enclosesWidth)
800 {
801 y1 = extendY1;
802 }
803
804 extended->x = x0;
805 extended->y = y0;
806 extended->width = x1 - x0;
807 extended->height = y1 - y0;
808 }
809
operator ==(const Box & other) const810 bool Box::operator==(const Box &other) const
811 {
812 return (x == other.x && y == other.y && z == other.z && width == other.width &&
813 height == other.height && depth == other.depth);
814 }
815
operator !=(const Box & other) const816 bool Box::operator!=(const Box &other) const
817 {
818 return !(*this == other);
819 }
820
toRect() const821 Rectangle Box::toRect() const
822 {
823 ASSERT(z == 0 && depth == 1);
824 return Rectangle(x, y, width, height);
825 }
826
coversSameExtent(const Extents & size) const827 bool Box::coversSameExtent(const Extents &size) const
828 {
829 return x == 0 && y == 0 && z == 0 && width == size.width && height == size.height &&
830 depth == size.depth;
831 }
832
operator ==(const Offset & a,const Offset & b)833 bool operator==(const Offset &a, const Offset &b)
834 {
835 return a.x == b.x && a.y == b.y && a.z == b.z;
836 }
837
operator !=(const Offset & a,const Offset & b)838 bool operator!=(const Offset &a, const Offset &b)
839 {
840 return !(a == b);
841 }
842
operator ==(const Extents & lhs,const Extents & rhs)843 bool operator==(const Extents &lhs, const Extents &rhs)
844 {
845 return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
846 }
847
operator !=(const Extents & lhs,const Extents & rhs)848 bool operator!=(const Extents &lhs, const Extents &rhs)
849 {
850 return !(lhs == rhs);
851 }
852
ValidateComponentTypeMasks(unsigned long outputTypes,unsigned long inputTypes,unsigned long outputMask,unsigned long inputMask)853 bool ValidateComponentTypeMasks(unsigned long outputTypes,
854 unsigned long inputTypes,
855 unsigned long outputMask,
856 unsigned long inputMask)
857 {
858 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS <= kMaxComponentTypeMaskIndex,
859 "Output/input masks should fit into 16 bits - 1 bit per draw buffer. The "
860 "corresponding type masks should fit into 32 bits - 2 bits per draw buffer.");
861 static_assert(MAX_VERTEX_ATTRIBS <= kMaxComponentTypeMaskIndex,
862 "Output/input masks should fit into 16 bits - 1 bit per attrib. The "
863 "corresponding type masks should fit into 32 bits - 2 bits per attrib.");
864
865 // For performance reasons, draw buffer and attribute type validation is done using bit masks.
866 // We store two bits representing the type split, with the low bit in the lower 16 bits of the
867 // variable, and the high bit in the upper 16 bits of the variable. This is done so we can AND
868 // with the elswewhere used DrawBufferMask or AttributeMask.
869
870 // OR the masks with themselves, shifted 16 bits. This is to match our split type bits.
871 outputMask |= (outputMask << kMaxComponentTypeMaskIndex);
872 inputMask |= (inputMask << kMaxComponentTypeMaskIndex);
873
874 // To validate:
875 // 1. Remove any indexes that are not enabled in the input (& inputMask)
876 // 2. Remove any indexes that exist in output, but not in input (& outputMask)
877 // 3. Use == to verify equality
878 return (outputTypes & inputMask) == ((inputTypes & outputMask) & inputMask);
879 }
880
GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> & binding)881 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding)
882 {
883 Buffer *buffer = binding.get();
884 if (buffer == nullptr)
885 {
886 return 0;
887 }
888
889 const GLsizeiptr bufferSize = static_cast<GLsizeiptr>(buffer->getSize());
890
891 if (binding.getSize() == 0)
892 {
893 return bufferSize;
894 }
895
896 const GLintptr offset = binding.getOffset();
897 const GLsizeiptr size = binding.getSize();
898
899 ASSERT(offset >= 0 && bufferSize >= 0);
900
901 if (bufferSize <= offset)
902 {
903 return 0;
904 }
905
906 return std::min(size, bufferSize - offset);
907 }
908
909 } // namespace gl
910