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