Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / canvas / WebGLContextVertices.cpp
blob96a2efc27a414a542166d81bbadf23b9322efd64
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WebGLContext.h"
8 #include "GLContext.h"
9 #include "mozilla/Casting.h"
10 #include "mozilla/CheckedInt.h"
11 #include "WebGLBuffer.h"
12 #include "WebGLFramebuffer.h"
13 #include "WebGLProgram.h"
14 #include "WebGLRenderbuffer.h"
15 #include "WebGLShader.h"
16 #include "WebGLTexture.h"
17 #include "WebGLTypes.h"
18 #include "WebGLVertexArray.h"
20 #include "mozilla/Casting.h"
22 namespace mozilla {
24 static bool ValidateAttribIndex(WebGLContext& webgl, GLuint index) {
25 bool valid = (index < webgl.MaxVertexAttribs());
27 if (!valid) {
28 if (index == GLuint(-1)) {
29 webgl.ErrorInvalidValue(
30 "-1 is not a valid `index`. This value"
31 " probably comes from a getAttribLocation()"
32 " call, where this return value -1 means"
33 " that the passed name didn't correspond to"
34 " an active attribute in the specified"
35 " program.");
36 } else {
37 webgl.ErrorInvalidValue(
38 "`index` must be less than"
39 " MAX_VERTEX_ATTRIBS.");
43 return valid;
46 ////////////////////////////////////////
48 void WebGLContext::VertexAttrib4T(GLuint index, const webgl::TypedQuad& src) {
49 const FuncScope funcScope(*this, "vertexAttrib[1234]u?[fi]v?");
50 if (IsContextLost()) return;
52 if (!ValidateAttribIndex(*this, index)) return;
54 ////
56 if (index || !gl->IsCompatibilityProfile()) {
57 switch (src.type) {
58 case webgl::AttribBaseType::Boolean:
59 case webgl::AttribBaseType::Float:
60 gl->fVertexAttrib4fv(index, reinterpret_cast<const float*>(src.data));
61 break;
62 case webgl::AttribBaseType::Int:
63 gl->fVertexAttribI4iv(index,
64 reinterpret_cast<const int32_t*>(src.data));
65 break;
66 case webgl::AttribBaseType::Uint:
67 gl->fVertexAttribI4uiv(index,
68 reinterpret_cast<const uint32_t*>(src.data));
69 break;
73 ////
75 mGenericVertexAttribTypes[index] = src.type;
76 mGenericVertexAttribTypeInvalidator.InvalidateCaches();
78 if (!index) {
79 memcpy(mGenericVertexAttrib0Data, src.data,
80 sizeof(mGenericVertexAttrib0Data));
84 ////////////////////////////////////////
86 void WebGLContext::EnableVertexAttribArray(GLuint index) {
87 const FuncScope funcScope(*this, "enableVertexAttribArray");
88 if (IsContextLost()) return;
90 if (!ValidateAttribIndex(*this, index)) return;
92 gl->fEnableVertexAttribArray(index);
94 MOZ_ASSERT(mBoundVertexArray);
95 mBoundVertexArray->SetAttribIsArray(index, true);
98 void WebGLContext::DisableVertexAttribArray(GLuint index) {
99 const FuncScope funcScope(*this, "disableVertexAttribArray");
100 if (IsContextLost()) return;
102 if (!ValidateAttribIndex(*this, index)) return;
104 if (index || !gl->IsCompatibilityProfile()) {
105 gl->fDisableVertexAttribArray(index);
108 MOZ_ASSERT(mBoundVertexArray);
109 mBoundVertexArray->SetAttribIsArray(index, false);
112 Maybe<double> WebGLContext::GetVertexAttrib(GLuint index, GLenum pname) {
113 const FuncScope funcScope(*this, "getVertexAttrib");
114 if (IsContextLost()) return Nothing();
116 if (!ValidateAttribIndex(*this, index)) return Nothing();
118 MOZ_ASSERT(mBoundVertexArray);
119 auto ret = mBoundVertexArray->GetVertexAttrib(index, pname);
121 switch (pname) {
122 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_INTEGER:
123 if (!IsWebGL2()) {
124 ret = Nothing();
126 break;
128 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
129 if (!IsWebGL2() &&
130 !IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays)) {
131 ret = Nothing();
133 break;
136 if (!ret) {
137 ErrorInvalidEnumInfo("pname", pname);
139 return ret;
142 ////////////////////////////////////////
144 Result<webgl::VertAttribPointerCalculated, webgl::ErrorInfo>
145 CheckVertexAttribPointer(const bool isWebgl2,
146 const webgl::VertAttribPointerDesc& desc) {
147 if (desc.channels < 1 || desc.channels > 4) {
148 return Err(webgl::ErrorInfo{LOCAL_GL_INVALID_VALUE,
149 "Channel count `size` must be within [1,4]."});
152 ////
154 webgl::VertAttribPointerCalculated calc;
156 bool isTypeValid = true;
157 bool isPackedType = false;
158 uint8_t bytesPerType = 0;
159 switch (desc.type) {
160 // WebGL 1:
161 case LOCAL_GL_BYTE:
162 bytesPerType = 1;
163 calc.baseType = webgl::AttribBaseType::Int;
164 break;
165 case LOCAL_GL_UNSIGNED_BYTE:
166 bytesPerType = 1;
167 calc.baseType = webgl::AttribBaseType::Uint;
168 break;
170 case LOCAL_GL_SHORT:
171 bytesPerType = 2;
172 calc.baseType = webgl::AttribBaseType::Int;
173 break;
174 case LOCAL_GL_UNSIGNED_SHORT:
175 bytesPerType = 2;
176 calc.baseType = webgl::AttribBaseType::Uint;
177 break;
179 case LOCAL_GL_FLOAT:
180 bytesPerType = 4;
181 calc.baseType = webgl::AttribBaseType::Float;
182 break;
184 // WebGL 2:
185 case LOCAL_GL_INT:
186 isTypeValid = isWebgl2;
187 bytesPerType = 4;
188 calc.baseType = webgl::AttribBaseType::Int;
189 break;
190 case LOCAL_GL_UNSIGNED_INT:
191 isTypeValid = isWebgl2;
192 bytesPerType = 4;
193 calc.baseType = webgl::AttribBaseType::Uint;
194 break;
196 case LOCAL_GL_HALF_FLOAT:
197 isTypeValid = isWebgl2;
198 bytesPerType = 2;
199 calc.baseType = webgl::AttribBaseType::Float;
200 break;
202 case LOCAL_GL_FIXED:
203 isTypeValid = isWebgl2;
204 bytesPerType = 4;
205 calc.baseType = webgl::AttribBaseType::Float;
206 break;
208 case LOCAL_GL_INT_2_10_10_10_REV:
209 case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
210 if (desc.channels != 4) {
211 return Err(webgl::ErrorInfo{LOCAL_GL_INVALID_OPERATION,
212 "Size must be 4 for this type."});
214 isTypeValid = isWebgl2;
215 bytesPerType = 4;
216 calc.baseType =
217 webgl::AttribBaseType::Float; // Invalid for intFunc:true.
218 isPackedType = true;
219 break;
221 default:
222 isTypeValid = false;
223 break;
225 if (desc.intFunc) {
226 isTypeValid = (calc.baseType != webgl::AttribBaseType::Float);
227 } else {
228 calc.baseType = webgl::AttribBaseType::Float;
230 if (!isTypeValid) {
231 const auto info =
232 nsPrintfCString("Bad `type`: %s", EnumString(desc.type).c_str());
233 return Err(webgl::ErrorInfo{LOCAL_GL_INVALID_ENUM, info.BeginReading()});
236 ////
238 calc.byteSize = bytesPerType;
239 if (!isPackedType) {
240 calc.byteSize *= desc.channels;
243 calc.byteStride =
244 desc.byteStrideOrZero ? desc.byteStrideOrZero : calc.byteSize;
246 // `alignment` should always be a power of two.
247 MOZ_ASSERT(IsPowerOfTwo(bytesPerType));
248 const auto typeAlignmentMask = bytesPerType - 1;
250 if (calc.byteStride & typeAlignmentMask ||
251 desc.byteOffset & typeAlignmentMask) {
252 return Err(
253 webgl::ErrorInfo{LOCAL_GL_INVALID_OPERATION,
254 "`stride` and `byteOffset` must satisfy the alignment"
255 " requirement of `type`."});
258 return calc;
261 void DoVertexAttribPointer(gl::GLContext& gl, const uint32_t index,
262 const webgl::VertAttribPointerDesc& desc) {
263 if (desc.intFunc) {
264 gl.fVertexAttribIPointer(index, desc.channels, desc.type,
265 desc.byteStrideOrZero,
266 reinterpret_cast<const void*>(desc.byteOffset));
267 } else {
268 gl.fVertexAttribPointer(index, desc.channels, desc.type, desc.normalized,
269 desc.byteStrideOrZero,
270 reinterpret_cast<const void*>(desc.byteOffset));
274 void WebGLContext::VertexAttribPointer(
275 const uint32_t index, const webgl::VertAttribPointerDesc& desc) {
276 if (IsContextLost()) return;
277 if (!ValidateAttribIndex(*this, index)) return;
279 const auto res = CheckVertexAttribPointer(IsWebGL2(), desc);
280 if (res.isErr()) {
281 const auto& err = res.inspectErr();
282 GenerateError(err.type, "%s", err.info.c_str());
283 return;
285 const auto& calc = res.inspect();
287 ////
289 const auto& buffer = mBoundArrayBuffer;
291 mBoundVertexArray->AttribPointer(index, buffer, desc, calc);
293 const ScopedLazyBind lazyBind(gl, LOCAL_GL_ARRAY_BUFFER, buffer);
294 DoVertexAttribPointer(*gl, index, desc);
297 ////////////////////////////////////////
299 void WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor) {
300 const FuncScope funcScope(*this, "vertexAttribDivisor");
301 if (IsContextLost()) return;
303 if (!ValidateAttribIndex(*this, index)) return;
305 MOZ_ASSERT(mBoundVertexArray);
306 mBoundVertexArray->AttribDivisor(index, divisor);
307 gl->fVertexAttribDivisor(index, divisor);
310 } // namespace mozilla