• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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