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