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