Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / canvas / WebGLContextVertices.cpp
blob582433538c4229a5251b4df108ff2171d41dec19
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)
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);
43 void
44 WebGLContext::VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1)
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);
63 void
64 WebGLContext::VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2)
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);
83 void
84 WebGLContext::VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
85 GLfloat x2, GLfloat x3)
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);
105 void
106 WebGLContext::VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength,
107 const GLfloat* ptr)
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);
125 void
126 WebGLContext::VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength,
127 const GLfloat* ptr)
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);
145 void
146 WebGLContext::VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength,
147 const GLfloat* ptr)
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);
165 void
166 WebGLContext::VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength,
167 const GLfloat* ptr)
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);
185 void
186 WebGLContext::EnableVertexAttribArray(GLuint index)
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;
202 void
203 WebGLContext::DisableVertexAttribArray(GLuint index)
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;
222 JS::Value
223 WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
224 ErrorResult& rv)
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:
237 return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].buf.get(), rv);
240 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
242 return JS::Int32Value(mBoundVertexArray->mAttribs[index].stride);
245 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
247 if (!mBoundVertexArray->mAttribs[index].enabled)
248 return JS::Int32Value(4);
250 return JS::Int32Value(mBoundVertexArray->mAttribs[index].size);
253 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
255 if (!mBoundVertexArray->mAttribs[index].enabled)
256 return JS::NumberValue(uint32_t(LOCAL_GL_FLOAT));
258 return JS::NumberValue(uint32_t(mBoundVertexArray->mAttribs[index].type));
261 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
263 if (IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
265 return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
267 break;
270 case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
272 GLfloat vec[4] = {0, 0, 0, 1};
273 if (index) {
274 gl->fGetVertexAttribfv(index, LOCAL_GL_CURRENT_VERTEX_ATTRIB, &vec[0]);
275 } else {
276 vec[0] = mVertexAttrib0Vector[0];
277 vec[1] = mVertexAttrib0Vector[1];
278 vec[2] = mVertexAttrib0Vector[2];
279 vec[3] = mVertexAttrib0Vector[3];
281 JSObject* obj = Float32Array::Create(cx, this, 4, vec);
282 if (!obj) {
283 rv.Throw(NS_ERROR_OUT_OF_MEMORY);
285 return JS::ObjectOrNullValue(obj);
288 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
290 return JS::BooleanValue(mBoundVertexArray->mAttribs[index].enabled);
293 case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
295 return JS::BooleanValue(mBoundVertexArray->mAttribs[index].normalized);
298 default:
299 break;
302 ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);
304 return JS::NullValue();
307 WebGLsizeiptr
308 WebGLContext::GetVertexAttribOffset(GLuint index, GLenum pname)
310 if (IsContextLost())
311 return 0;
313 if (!ValidateAttribIndex(index, "getVertexAttribOffset"))
314 return 0;
316 if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER) {
317 ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
318 return 0;
321 return mBoundVertexArray->mAttribs[index].byteOffset;
324 void
325 WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
326 WebGLboolean normalized, GLsizei stride,
327 WebGLintptr byteOffset)
329 if (IsContextLost())
330 return;
332 if (mBoundArrayBuffer == nullptr)
333 return ErrorInvalidOperation("vertexAttribPointer: must have valid GL_ARRAY_BUFFER binding");
335 GLsizei requiredAlignment = 1;
336 switch (type) {
337 case LOCAL_GL_BYTE:
338 case LOCAL_GL_UNSIGNED_BYTE:
339 requiredAlignment = 1;
340 break;
341 case LOCAL_GL_SHORT:
342 case LOCAL_GL_UNSIGNED_SHORT:
343 requiredAlignment = 2;
344 break;
345 // XXX case LOCAL_GL_FIXED:
346 case LOCAL_GL_FLOAT:
347 requiredAlignment = 4;
348 break;
349 default:
350 return ErrorInvalidEnumInfo("vertexAttribPointer: type", type);
353 // requiredAlignment should always be a power of two.
354 GLsizei requiredAlignmentMask = requiredAlignment - 1;
356 if (!ValidateAttribIndex(index, "vertexAttribPointer")) {
357 return;
360 if (size < 1 || size > 4)
361 return ErrorInvalidValue("vertexAttribPointer: invalid element size");
363 if (stride < 0 || stride > 255) // see WebGL spec section 6.6 "Vertex Attribute Data Stride"
364 return ErrorInvalidValue("vertexAttribPointer: negative or too large stride");
366 if (byteOffset < 0)
367 return ErrorInvalidValue("vertexAttribPointer: negative offset");
369 if (stride & requiredAlignmentMask) {
370 return ErrorInvalidOperation("vertexAttribPointer: stride doesn't satisfy the alignment "
371 "requirement of given type");
374 if (byteOffset & requiredAlignmentMask) {
375 return ErrorInvalidOperation("vertexAttribPointer: byteOffset doesn't satisfy the alignment "
376 "requirement of given type");
380 InvalidateBufferFetching();
382 /* XXX make work with bufferSubData & heterogeneous types
383 if (type != mBoundArrayBuffer->GLType())
384 return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
387 WebGLVertexAttribData &vd = mBoundVertexArray->mAttribs[index];
389 vd.buf = mBoundArrayBuffer;
390 vd.stride = stride;
391 vd.size = size;
392 vd.byteOffset = byteOffset;
393 vd.type = type;
394 vd.normalized = normalized;
396 MakeContextCurrent();
398 gl->fVertexAttribPointer(index, size, type, normalized,
399 stride,
400 reinterpret_cast<void*>(byteOffset));
403 void
404 WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor)
406 if (IsContextLost())
407 return;
409 if (!ValidateAttribIndex(index, "vertexAttribDivisor")) {
410 return;
413 WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
414 vd.divisor = divisor;
416 InvalidateBufferFetching();
418 MakeContextCurrent();
420 gl->fVertexAttribDivisor(index, divisor);