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"
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
;
24 WebGLContext::VertexAttrib1f(GLuint index
, GLfloat x0
)
32 gl
->fVertexAttrib1f(index
, x0
);
34 mVertexAttrib0Vector
[0] = x0
;
35 mVertexAttrib0Vector
[1] = 0;
36 mVertexAttrib0Vector
[2] = 0;
37 mVertexAttrib0Vector
[3] = 1;
39 gl
->fVertexAttrib1f(index
, x0
);
44 WebGLContext::VertexAttrib2f(GLuint index
, GLfloat x0
, GLfloat x1
)
52 gl
->fVertexAttrib2f(index
, x0
, x1
);
54 mVertexAttrib0Vector
[0] = x0
;
55 mVertexAttrib0Vector
[1] = x1
;
56 mVertexAttrib0Vector
[2] = 0;
57 mVertexAttrib0Vector
[3] = 1;
59 gl
->fVertexAttrib2f(index
, x0
, x1
);
64 WebGLContext::VertexAttrib3f(GLuint index
, GLfloat x0
, GLfloat x1
, GLfloat x2
)
72 gl
->fVertexAttrib3f(index
, x0
, x1
, x2
);
74 mVertexAttrib0Vector
[0] = x0
;
75 mVertexAttrib0Vector
[1] = x1
;
76 mVertexAttrib0Vector
[2] = x2
;
77 mVertexAttrib0Vector
[3] = 1;
79 gl
->fVertexAttrib3f(index
, x0
, x1
, x2
);
84 WebGLContext::VertexAttrib4f(GLuint index
, GLfloat x0
, GLfloat x1
,
85 GLfloat x2
, GLfloat x3
)
93 gl
->fVertexAttrib4f(index
, x0
, x1
, x2
, x3
);
95 mVertexAttrib0Vector
[0] = x0
;
96 mVertexAttrib0Vector
[1] = x1
;
97 mVertexAttrib0Vector
[2] = x2
;
98 mVertexAttrib0Vector
[3] = x3
;
100 gl
->fVertexAttrib4f(index
, x0
, x1
, x2
, x3
);
106 WebGLContext::VertexAttrib1fv_base(GLuint idx
, uint32_t arrayLength
,
109 if (!ValidateAttribArraySetter("VertexAttrib1fv", 1, arrayLength
))
112 MakeContextCurrent();
114 gl
->fVertexAttrib1fv(idx
, ptr
);
116 mVertexAttrib0Vector
[0] = ptr
[0];
117 mVertexAttrib0Vector
[1] = GLfloat(0);
118 mVertexAttrib0Vector
[2] = GLfloat(0);
119 mVertexAttrib0Vector
[3] = GLfloat(1);
121 gl
->fVertexAttrib1fv(idx
, ptr
);
126 WebGLContext::VertexAttrib2fv_base(GLuint idx
, uint32_t arrayLength
,
129 if (!ValidateAttribArraySetter("VertexAttrib2fv", 2, arrayLength
))
132 MakeContextCurrent();
134 gl
->fVertexAttrib2fv(idx
, ptr
);
136 mVertexAttrib0Vector
[0] = ptr
[0];
137 mVertexAttrib0Vector
[1] = ptr
[1];
138 mVertexAttrib0Vector
[2] = GLfloat(0);
139 mVertexAttrib0Vector
[3] = GLfloat(1);
141 gl
->fVertexAttrib2fv(idx
, ptr
);
146 WebGLContext::VertexAttrib3fv_base(GLuint idx
, uint32_t arrayLength
,
149 if (!ValidateAttribArraySetter("VertexAttrib3fv", 3, arrayLength
))
152 MakeContextCurrent();
154 gl
->fVertexAttrib3fv(idx
, ptr
);
156 mVertexAttrib0Vector
[0] = ptr
[0];
157 mVertexAttrib0Vector
[1] = ptr
[1];
158 mVertexAttrib0Vector
[2] = ptr
[2];
159 mVertexAttrib0Vector
[3] = GLfloat(1);
161 gl
->fVertexAttrib3fv(idx
, ptr
);
166 WebGLContext::VertexAttrib4fv_base(GLuint idx
, uint32_t arrayLength
,
169 if (!ValidateAttribArraySetter("VertexAttrib4fv", 4, arrayLength
))
172 MakeContextCurrent();
174 gl
->fVertexAttrib4fv(idx
, ptr
);
176 mVertexAttrib0Vector
[0] = ptr
[0];
177 mVertexAttrib0Vector
[1] = ptr
[1];
178 mVertexAttrib0Vector
[2] = ptr
[2];
179 mVertexAttrib0Vector
[3] = ptr
[3];
181 gl
->fVertexAttrib4fv(idx
, ptr
);
186 WebGLContext::EnableVertexAttribArray(GLuint index
)
191 if (!ValidateAttribIndex(index
, "enableVertexAttribArray"))
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;
203 WebGLContext::DisableVertexAttribArray(GLuint index
)
208 if (!ValidateAttribIndex(index
, "disableVertexAttribArray"))
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;
223 WebGLContext::GetVertexAttrib(JSContext
* cx
, GLuint index
, GLenum pname
,
227 return JS::NullValue();
229 if (!ValidateAttribIndex(index
, "getVertexAttrib"))
230 return JS::NullValue();
232 MakeContextCurrent();
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
);
270 case LOCAL_GL_CURRENT_VERTEX_ATTRIB
:
272 GLfloat vec
[4] = {0, 0, 0, 1};
274 gl
->fGetVertexAttribfv(index
, LOCAL_GL_CURRENT_VERTEX_ATTRIB
, &vec
[0]);
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
);
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
);
302 ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname
);
304 return JS::NullValue();
308 WebGLContext::GetVertexAttribOffset(GLuint index
, GLenum pname
)
313 if (!ValidateAttribIndex(index
, "getVertexAttribOffset"))
316 if (pname
!= LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER
) {
317 ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
321 return mBoundVertexArray
->mAttribs
[index
].byteOffset
;
325 WebGLContext::VertexAttribPointer(GLuint index
, GLint size
, GLenum type
,
326 WebGLboolean normalized
, GLsizei stride
,
327 WebGLintptr byteOffset
)
332 if (mBoundArrayBuffer
== nullptr)
333 return ErrorInvalidOperation("vertexAttribPointer: must have valid GL_ARRAY_BUFFER binding");
335 GLsizei requiredAlignment
= 1;
338 case LOCAL_GL_UNSIGNED_BYTE
:
339 requiredAlignment
= 1;
342 case LOCAL_GL_UNSIGNED_SHORT
:
343 requiredAlignment
= 2;
345 // XXX case LOCAL_GL_FIXED:
347 requiredAlignment
= 4;
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")) {
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");
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
;
392 vd
.byteOffset
= byteOffset
;
394 vd
.normalized
= normalized
;
396 MakeContextCurrent();
398 gl
->fVertexAttribPointer(index
, size
, type
, normalized
,
400 reinterpret_cast<void*>(byteOffset
));
404 WebGLContext::VertexAttribDivisor(GLuint index
, GLuint divisor
)
409 if (!ValidateAttribIndex(index
, "vertexAttribDivisor")) {
413 WebGLVertexAttribData
& vd
= mBoundVertexArray
->mAttribs
[index
];
414 vd
.divisor
= divisor
;
416 InvalidateBufferFetching();
418 MakeContextCurrent();
420 gl
->fVertexAttribDivisor(index
, divisor
);