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