Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/CheckedInt.h"
10 #include "WebGLBuffer.h"
11 #include "WebGLFramebuffer.h"
12 #include "WebGLProgram.h"
13 #include "WebGLRenderbuffer.h"
14 #include "WebGLShader.h"
15 #include "WebGLTexture.h"
16 #include "WebGLUniformInfo.h"
17 #include "WebGLVertexArray.h"
18 #include "WebGLVertexAttribData.h"
20 using namespace mozilla;
21 using namespace dom;
23 void
24 WebGLContext::VertexAttrib1f(GLuint index, GLfloat x0)
25 {
26 if (IsContextLost())
27 return;
29 MakeContextCurrent();
31 if (index) {
32 gl->fVertexAttrib1f(index, x0);
33 } else {
34 mVertexAttrib0Vector[0] = x0;
35 mVertexAttrib0Vector[1] = 0;
36 mVertexAttrib0Vector[2] = 0;
37 mVertexAttrib0Vector[3] = 1;
38 if (gl->IsGLES())
39 gl->fVertexAttrib1f(index, x0);
40 }
41 }
43 void
44 WebGLContext::VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1)
45 {
46 if (IsContextLost())
47 return;
49 MakeContextCurrent();
51 if (index) {
52 gl->fVertexAttrib2f(index, x0, x1);
53 } else {
54 mVertexAttrib0Vector[0] = x0;
55 mVertexAttrib0Vector[1] = x1;
56 mVertexAttrib0Vector[2] = 0;
57 mVertexAttrib0Vector[3] = 1;
58 if (gl->IsGLES())
59 gl->fVertexAttrib2f(index, x0, x1);
60 }
61 }
63 void
64 WebGLContext::VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2)
65 {
66 if (IsContextLost())
67 return;
69 MakeContextCurrent();
71 if (index) {
72 gl->fVertexAttrib3f(index, x0, x1, x2);
73 } else {
74 mVertexAttrib0Vector[0] = x0;
75 mVertexAttrib0Vector[1] = x1;
76 mVertexAttrib0Vector[2] = x2;
77 mVertexAttrib0Vector[3] = 1;
78 if (gl->IsGLES())
79 gl->fVertexAttrib3f(index, x0, x1, x2);
80 }
81 }
83 void
84 WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
85 GLfloat x2, GLfloat x3)
86 {
87 if (IsContextLost())
88 return;
90 MakeContextCurrent();
92 if (index) {
93 gl->fVertexAttrib4f(index, x0, x1, x2, x3);
94 } else {
95 mVertexAttrib0Vector[0] = x0;
96 mVertexAttrib0Vector[1] = x1;
97 mVertexAttrib0Vector[2] = x2;
98 mVertexAttrib0Vector[3] = x3;
99 if (gl->IsGLES())
100 gl->fVertexAttrib4f(index, x0, x1, x2, x3);
101 }
102 }
105 void
106 WebGLContext::VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength,
107 const GLfloat* ptr)
108 {
109 if (!ValidateAttribArraySetter("VertexAttrib1fv", 1, arrayLength))
110 return;
112 MakeContextCurrent();
113 if (idx) {
114 gl->fVertexAttrib1fv(idx, ptr);
115 } else {
116 mVertexAttrib0Vector[0] = ptr[0];
117 mVertexAttrib0Vector[1] = GLfloat(0);
118 mVertexAttrib0Vector[2] = GLfloat(0);
119 mVertexAttrib0Vector[3] = GLfloat(1);
120 if (gl->IsGLES())
121 gl->fVertexAttrib1fv(idx, ptr);
122 }
123 }
125 void
126 WebGLContext::VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength,
127 const GLfloat* ptr)
128 {
129 if (!ValidateAttribArraySetter("VertexAttrib2fv", 2, arrayLength))
130 return;
132 MakeContextCurrent();
133 if (idx) {
134 gl->fVertexAttrib2fv(idx, ptr);
135 } else {
136 mVertexAttrib0Vector[0] = ptr[0];
137 mVertexAttrib0Vector[1] = ptr[1];
138 mVertexAttrib0Vector[2] = GLfloat(0);
139 mVertexAttrib0Vector[3] = GLfloat(1);
140 if (gl->IsGLES())
141 gl->fVertexAttrib2fv(idx, ptr);
142 }
143 }
145 void
146 WebGLContext::VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength,
147 const GLfloat* ptr)
148 {
149 if (!ValidateAttribArraySetter("VertexAttrib3fv", 3, arrayLength))
150 return;
152 MakeContextCurrent();
153 if (idx) {
154 gl->fVertexAttrib3fv(idx, ptr);
155 } else {
156 mVertexAttrib0Vector[0] = ptr[0];
157 mVertexAttrib0Vector[1] = ptr[1];
158 mVertexAttrib0Vector[2] = ptr[2];
159 mVertexAttrib0Vector[3] = GLfloat(1);
160 if (gl->IsGLES())
161 gl->fVertexAttrib3fv(idx, ptr);
162 }
163 }
165 void
166 WebGLContext::VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength,
167 const GLfloat* ptr)
168 {
169 if (!ValidateAttribArraySetter("VertexAttrib4fv", 4, arrayLength))
170 return;
172 MakeContextCurrent();
173 if (idx) {
174 gl->fVertexAttrib4fv(idx, ptr);
175 } else {
176 mVertexAttrib0Vector[0] = ptr[0];
177 mVertexAttrib0Vector[1] = ptr[1];
178 mVertexAttrib0Vector[2] = ptr[2];
179 mVertexAttrib0Vector[3] = ptr[3];
180 if (gl->IsGLES())
181 gl->fVertexAttrib4fv(idx, ptr);
182 }
183 }
185 void
186 WebGLContext::EnableVertexAttribArray(GLuint index)
187 {
188 if (IsContextLost())
189 return;
191 if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
192 return;
194 MakeContextCurrent();
195 InvalidateBufferFetching();
197 gl->fEnableVertexAttribArray(index);
198 MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
199 mBoundVertexArray->mAttribs[index].enabled = true;
200 }
202 void
203 WebGLContext::DisableVertexAttribArray(GLuint index)
204 {
205 if (IsContextLost())
206 return;
208 if (!ValidateAttribIndex(index, "disableVertexAttribArray"))
209 return;
211 MakeContextCurrent();
212 InvalidateBufferFetching();
214 if (index || gl->IsGLES())
215 gl->fDisableVertexAttribArray(index);
217 MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
218 mBoundVertexArray->mAttribs[index].enabled = false;
219 }
222 JS::Value
223 WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
224 ErrorResult& rv)
225 {
226 if (IsContextLost())
227 return JS::NullValue();
229 if (!ValidateAttribIndex(index, "getVertexAttrib"))
230 return JS::NullValue();
232 MakeContextCurrent();
234 switch (pname) {
235 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
236 {
237 return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].buf.get(), rv);
238 }
240 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
241 {
242 return JS::Int32Value(mBoundVertexArray->mAttribs[index].stride);
243 }
245 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
246 {
247 if (!ValidateAttribIndex(index, "getVertexAttrib"))
248 return JS::NullValue();
250 if (!mBoundVertexArray->mAttribs[index].enabled)
251 return JS::Int32Value(4);
253 // Don't break; fall through.
254 }
255 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
256 {
257 GLint i = 0;
258 gl->fGetVertexAttribiv(index, pname, &i);
259 if (pname == LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE)
260 return JS::Int32Value(i);
261 MOZ_ASSERT(pname == LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE);
262 return JS::NumberValue(uint32_t(i));
263 }
265 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
266 {
267 if (IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
268 {
269 return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
270 }
271 break;
272 }
274 case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
275 {
276 GLfloat vec[4] = {0, 0, 0, 1};
277 if (index) {
278 gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, &vec[0]);
279 } else {
280 vec[0] = mVertexAttrib0Vector[0];
281 vec[1] = mVertexAttrib0Vector[1];
282 vec[2] = mVertexAttrib0Vector[2];
283 vec[3] = mVertexAttrib0Vector[3];
284 }
285 JSObject* obj = Float32Array::Create(cx, this, 4, vec);
286 if (!obj) {
287 rv.Throw(NS_ERROR_OUT_OF_MEMORY);
288 }
289 return JS::ObjectOrNullValue(obj);
290 }
292 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
293 {
294 return JS::BooleanValue(mBoundVertexArray->mAttribs[index].enabled);
295 }
297 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
298 {
299 return JS::BooleanValue(mBoundVertexArray->mAttribs[index].normalized);
300 }
302 default:
303 break;
304 }
306 ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);
308 return JS::NullValue();
309 }
311 WebGLsizeiptr
312 WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname)
313 {
314 if (IsContextLost())
315 return 0;
317 if (!ValidateAttribIndex(index, "getVertexAttribOffset"))
318 return 0;
320 if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER) {
321 ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
322 return 0;
323 }
325 return mBoundVertexArray->mAttribs[index].byteOffset;
326 }
328 void
329 WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
330 WebGLboolean normalized, GLsizei stride,
331 WebGLintptr byteOffset)
332 {
333 if (IsContextLost())
334 return;
336 if (mBoundArrayBuffer == nullptr)
337 return ErrorInvalidOperation("vertexAttribPointer: must have valid GL_ARRAY_BUFFER binding");
339 GLsizei requiredAlignment = 1;
340 switch (type) {
341 case LOCAL_GL_BYTE:
342 case LOCAL_GL_UNSIGNED_BYTE:
343 requiredAlignment = 1;
344 break;
345 case LOCAL_GL_SHORT:
346 case LOCAL_GL_UNSIGNED_SHORT:
347 requiredAlignment = 2;
348 break;
349 // XXX case LOCAL_GL_FIXED:
350 case LOCAL_GL_FLOAT:
351 requiredAlignment = 4;
352 break;
353 default:
354 return ErrorInvalidEnumInfo("vertexAttribPointer: type", type);
355 }
357 // requiredAlignment should always be a power of two.
358 GLsizei requiredAlignmentMask = requiredAlignment - 1;
360 if (!ValidateAttribIndex(index, "vertexAttribPointer")) {
361 return;
362 }
364 if (size < 1 || size > 4)
365 return ErrorInvalidValue("vertexAttribPointer: invalid element size");
367 if (stride < 0 || stride > 255) // see WebGL spec section 6.6 "Vertex Attribute Data Stride"
368 return ErrorInvalidValue("vertexAttribPointer: negative or too large stride");
370 if (byteOffset < 0)
371 return ErrorInvalidValue("vertexAttribPointer: negative offset");
373 if (stride & requiredAlignmentMask) {
374 return ErrorInvalidOperation("vertexAttribPointer: stride doesn't satisfy the alignment "
375 "requirement of given type");
376 }
378 if (byteOffset & requiredAlignmentMask) {
379 return ErrorInvalidOperation("vertexAttribPointer: byteOffset doesn't satisfy the alignment "
380 "requirement of given type");
382 }
384 InvalidateBufferFetching();
386 /* XXX make work with bufferSubData & heterogeneous types
387 if (type != mBoundArrayBuffer->GLType())
388 return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
389 */
391 WebGLVertexAttribData &vd = mBoundVertexArray->mAttribs[index];
393 vd.buf = mBoundArrayBuffer;
394 vd.stride = stride;
395 vd.size = size;
396 vd.byteOffset = byteOffset;
397 vd.type = type;
398 vd.normalized = normalized;
400 MakeContextCurrent();
402 gl->fVertexAttribPointer(index, size, type, normalized,
403 stride,
404 reinterpret_cast<void*>(byteOffset));
405 }
407 void
408 WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor)
409 {
410 if (IsContextLost())
411 return;
413 if (!ValidateAttribIndex(index, "vertexAttribDivisor")) {
414 return;
415 }
417 WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
418 vd.divisor = divisor;
420 InvalidateBufferFetching();
422 MakeContextCurrent();
424 gl->fVertexAttribDivisor(index, divisor);
425 }