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 {
RasterizerState()17 RasterizerState::RasterizerState()
18 {
19 memset(this, 0, sizeof(RasterizerState));
20
21 rasterizerDiscard = false;
22 cullFace = false;
23 cullMode = CullFaceMode::Back;
24 frontFace = GL_CCW;
25 polygonOffsetFill = false;
26 polygonOffsetFactor = 0.0f;
27 polygonOffsetUnits = 0.0f;
28 pointDrawMode = false;
29 multiSample = false;
30 }
31
operator ==(const RasterizerState & a,const RasterizerState & b)32 bool operator==(const RasterizerState &a, const RasterizerState &b)
33 {
34 return memcmp(&a, &b, sizeof(RasterizerState)) == 0;
35 }
36
operator !=(const RasterizerState & a,const RasterizerState & b)37 bool operator!=(const RasterizerState &a, const RasterizerState &b)
38 {
39 return !(a == b);
40 }
41
BlendState()42 BlendState::BlendState()
43 {
44 memset(this, 0, sizeof(BlendState));
45
46 blend = false;
47 sourceBlendRGB = GL_ONE;
48 sourceBlendAlpha = GL_ONE;
49 destBlendRGB = GL_ZERO;
50 destBlendAlpha = GL_ZERO;
51 blendEquationRGB = GL_FUNC_ADD;
52 blendEquationAlpha = GL_FUNC_ADD;
53 sampleAlphaToCoverage = false;
54 dither = true;
55 }
56
BlendState(const BlendState & other)57 BlendState::BlendState(const BlendState &other)
58 {
59 memcpy(this, &other, sizeof(BlendState));
60 }
61
allChannelsMasked() const62 bool BlendState::allChannelsMasked() const
63 {
64 return !colorMaskRed && !colorMaskGreen && !colorMaskBlue && !colorMaskAlpha;
65 }
66
operator ==(const BlendState & a,const BlendState & b)67 bool operator==(const BlendState &a, const BlendState &b)
68 {
69 return memcmp(&a, &b, sizeof(BlendState)) == 0;
70 }
71
operator !=(const BlendState & a,const BlendState & b)72 bool operator!=(const BlendState &a, const BlendState &b)
73 {
74 return !(a == b);
75 }
76
DepthStencilState()77 DepthStencilState::DepthStencilState()
78 {
79 memset(this, 0, sizeof(DepthStencilState));
80
81 depthTest = false;
82 depthFunc = GL_LESS;
83 depthMask = true;
84 stencilTest = false;
85 stencilFunc = GL_ALWAYS;
86 stencilMask = static_cast<GLuint>(-1);
87 stencilWritemask = static_cast<GLuint>(-1);
88 stencilBackFunc = GL_ALWAYS;
89 stencilBackMask = static_cast<GLuint>(-1);
90 stencilBackWritemask = static_cast<GLuint>(-1);
91 stencilFail = GL_KEEP;
92 stencilPassDepthFail = GL_KEEP;
93 stencilPassDepthPass = GL_KEEP;
94 stencilBackFail = GL_KEEP;
95 stencilBackPassDepthFail = GL_KEEP;
96 stencilBackPassDepthPass = GL_KEEP;
97 }
98
DepthStencilState(const DepthStencilState & other)99 DepthStencilState::DepthStencilState(const DepthStencilState &other)
100 {
101 memcpy(this, &other, sizeof(DepthStencilState));
102 }
103
operator ==(const DepthStencilState & a,const DepthStencilState & b)104 bool operator==(const DepthStencilState &a, const DepthStencilState &b)
105 {
106 return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
107 }
108
operator !=(const DepthStencilState & a,const DepthStencilState & b)109 bool operator!=(const DepthStencilState &a, const DepthStencilState &b)
110 {
111 return !(a == b);
112 }
113
SamplerState()114 SamplerState::SamplerState()
115 {
116 memset(this, 0, sizeof(SamplerState));
117
118 setMinFilter(GL_NEAREST_MIPMAP_LINEAR);
119 setMagFilter(GL_LINEAR);
120 setWrapS(GL_REPEAT);
121 setWrapT(GL_REPEAT);
122 setWrapR(GL_REPEAT);
123 setMaxAnisotropy(1.0f);
124 setMinLod(-1000.0f);
125 setMaxLod(1000.0f);
126 setCompareMode(GL_NONE);
127 setCompareFunc(GL_LEQUAL);
128 setSRGBDecode(GL_DECODE_EXT);
129 }
130
131 SamplerState::SamplerState(const SamplerState &other) = default;
132
133 // static
CreateDefaultForTarget(TextureType type)134 SamplerState SamplerState::CreateDefaultForTarget(TextureType type)
135 {
136 SamplerState state;
137
138 // According to OES_EGL_image_external and ARB_texture_rectangle: For external textures, the
139 // default min filter is GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
140 if (type == TextureType::External || type == TextureType::Rectangle)
141 {
142 state.mMinFilter = GL_LINEAR;
143 state.mWrapS = GL_CLAMP_TO_EDGE;
144 state.mWrapT = GL_CLAMP_TO_EDGE;
145 }
146
147 return state;
148 }
149
setMinFilter(GLenum minFilter)150 void SamplerState::setMinFilter(GLenum minFilter)
151 {
152 mMinFilter = minFilter;
153 mCompleteness.typed.minFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(minFilter));
154 }
155
setMagFilter(GLenum magFilter)156 void SamplerState::setMagFilter(GLenum magFilter)
157 {
158 mMagFilter = magFilter;
159 mCompleteness.typed.magFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(magFilter));
160 }
161
setWrapS(GLenum wrapS)162 void SamplerState::setWrapS(GLenum wrapS)
163 {
164 mWrapS = wrapS;
165 mCompleteness.typed.wrapS = static_cast<uint8_t>(FromGLenum<WrapMode>(wrapS));
166 }
167
setWrapT(GLenum wrapT)168 void SamplerState::setWrapT(GLenum wrapT)
169 {
170 mWrapT = wrapT;
171 updateWrapTCompareMode();
172 }
173
setWrapR(GLenum wrapR)174 void SamplerState::setWrapR(GLenum wrapR)
175 {
176 mWrapR = wrapR;
177 }
178
setMaxAnisotropy(float maxAnisotropy)179 void SamplerState::setMaxAnisotropy(float maxAnisotropy)
180 {
181 mMaxAnisotropy = maxAnisotropy;
182 }
183
setMinLod(GLfloat minLod)184 void SamplerState::setMinLod(GLfloat minLod)
185 {
186 mMinLod = minLod;
187 }
188
setMaxLod(GLfloat maxLod)189 void SamplerState::setMaxLod(GLfloat maxLod)
190 {
191 mMaxLod = maxLod;
192 }
193
setCompareMode(GLenum compareMode)194 void SamplerState::setCompareMode(GLenum compareMode)
195 {
196 mCompareMode = compareMode;
197 updateWrapTCompareMode();
198 }
199
setCompareFunc(GLenum compareFunc)200 void SamplerState::setCompareFunc(GLenum compareFunc)
201 {
202 mCompareFunc = compareFunc;
203 }
204
setSRGBDecode(GLenum sRGBDecode)205 void SamplerState::setSRGBDecode(GLenum sRGBDecode)
206 {
207 mSRGBDecode = sRGBDecode;
208 }
209
setBorderColor(const ColorGeneric & color)210 void SamplerState::setBorderColor(const ColorGeneric &color)
211 {
212 mBorderColor = color;
213 }
214
updateWrapTCompareMode()215 void SamplerState::updateWrapTCompareMode()
216 {
217 uint8_t wrap = static_cast<uint8_t>(FromGLenum<WrapMode>(mWrapT));
218 uint8_t compare = static_cast<uint8_t>(mCompareMode == GL_NONE ? 0x10 : 0x00);
219 mCompleteness.typed.wrapTCompareMode = wrap | compare;
220 }
221
ImageUnit()222 ImageUnit::ImageUnit()
223 : texture(), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
224 {}
225
226 ImageUnit::ImageUnit(const ImageUnit &other) = default;
227
228 ImageUnit::~ImageUnit() = default;
229
MinMax(int a,int b,int * minimum,int * maximum)230 static void MinMax(int a, int b, int *minimum, int *maximum)
231 {
232 if (a < b)
233 {
234 *minimum = a;
235 *maximum = b;
236 }
237 else
238 {
239 *minimum = b;
240 *maximum = a;
241 }
242 }
243
flip(bool flipX,bool flipY) const244 Rectangle Rectangle::flip(bool flipX, bool flipY) const
245 {
246 Rectangle flipped = *this;
247 if (flipX)
248 {
249 flipped.x = flipped.x + flipped.width;
250 flipped.width = -flipped.width;
251 }
252 if (flipY)
253 {
254 flipped.y = flipped.y + flipped.height;
255 flipped.height = -flipped.height;
256 }
257 return flipped;
258 }
259
removeReversal() const260 Rectangle Rectangle::removeReversal() const
261 {
262 return flip(isReversedX(), isReversedY());
263 }
264
encloses(const gl::Rectangle & inside) const265 bool Rectangle::encloses(const gl::Rectangle &inside) const
266 {
267 return x0() <= inside.x0() && y0() <= inside.y0() && x1() >= inside.x1() && y1() >= inside.y1();
268 }
269
ClipRectangle(const Rectangle & source,const Rectangle & clip,Rectangle * intersection)270 bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
271 {
272 int minSourceX, maxSourceX, minSourceY, maxSourceY;
273 MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX);
274 MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY);
275
276 int minClipX, maxClipX, minClipY, maxClipY;
277 MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX);
278 MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY);
279
280 if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY ||
281 maxSourceY <= minClipY)
282 {
283 return false;
284 }
285 if (intersection)
286 {
287 intersection->x = std::max(minSourceX, minClipX);
288 intersection->y = std::max(minSourceY, minClipY);
289 intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX);
290 intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY);
291 }
292 return true;
293 }
294
operator ==(const Box & other) const295 bool Box::operator==(const Box &other) const
296 {
297 return (x == other.x && y == other.y && z == other.z && width == other.width &&
298 height == other.height && depth == other.depth);
299 }
300
operator !=(const Box & other) const301 bool Box::operator!=(const Box &other) const
302 {
303 return !(*this == other);
304 }
305
toRect() const306 Rectangle Box::toRect() const
307 {
308 ASSERT(z == 0 && depth == 1);
309 return Rectangle(x, y, width, height);
310 }
311
operator ==(const Offset & a,const Offset & b)312 bool operator==(const Offset &a, const Offset &b)
313 {
314 return a.x == b.x && a.y == b.y && a.z == b.z;
315 }
316
operator !=(const Offset & a,const Offset & b)317 bool operator!=(const Offset &a, const Offset &b)
318 {
319 return !(a == b);
320 }
321
operator ==(const Extents & lhs,const Extents & rhs)322 bool operator==(const Extents &lhs, const Extents &rhs)
323 {
324 return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
325 }
326
operator !=(const Extents & lhs,const Extents & rhs)327 bool operator!=(const Extents &lhs, const Extents &rhs)
328 {
329 return !(lhs == rhs);
330 }
331
ValidateComponentTypeMasks(unsigned long outputTypes,unsigned long inputTypes,unsigned long outputMask,unsigned long inputMask)332 bool ValidateComponentTypeMasks(unsigned long outputTypes,
333 unsigned long inputTypes,
334 unsigned long outputMask,
335 unsigned long inputMask)
336 {
337 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS <= kMaxComponentTypeMaskIndex,
338 "Output/input masks should fit into 16 bits - 1 bit per draw buffer. The "
339 "corresponding type masks should fit into 32 bits - 2 bits per draw buffer.");
340 static_assert(MAX_VERTEX_ATTRIBS <= kMaxComponentTypeMaskIndex,
341 "Output/input masks should fit into 16 bits - 1 bit per attrib. The "
342 "corresponding type masks should fit into 32 bits - 2 bits per attrib.");
343
344 // For performance reasons, draw buffer and attribute type validation is done using bit masks.
345 // We store two bits representing the type split, with the low bit in the lower 16 bits of the
346 // variable, and the high bit in the upper 16 bits of the variable. This is done so we can AND
347 // with the elswewhere used DrawBufferMask or AttributeMask.
348
349 // OR the masks with themselves, shifted 16 bits. This is to match our split type bits.
350 outputMask |= (outputMask << kMaxComponentTypeMaskIndex);
351 inputMask |= (inputMask << kMaxComponentTypeMaskIndex);
352
353 // To validate:
354 // 1. Remove any indexes that are not enabled in the input (& inputMask)
355 // 2. Remove any indexes that exist in output, but not in input (& outputMask)
356 // 3. Use == to verify equality
357 return (outputTypes & inputMask) == ((inputTypes & outputMask) & inputMask);
358 }
359
GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> & binding)360 GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding)
361 {
362 Buffer *buffer = binding.get();
363 if (buffer)
364 {
365 if (binding.getSize() == 0)
366 return static_cast<GLsizeiptr>(buffer->getSize());
367 angle::CheckedNumeric<GLintptr> offset = binding.getOffset();
368 angle::CheckedNumeric<GLsizeiptr> size = binding.getSize();
369 angle::CheckedNumeric<GLsizeiptr> bufferSize = buffer->getSize();
370 auto end = offset + size;
371 auto clampedSize = size;
372 auto difference = end - bufferSize;
373 if (!difference.IsValid())
374 {
375 return 0;
376 }
377 if (difference.ValueOrDie() > 0)
378 {
379 clampedSize = size - difference;
380 }
381 return clampedSize.ValueOrDefault(0);
382 }
383 else
384 {
385 return 0;
386 }
387 }
388
389 } // namespace gl
390