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 "WebGL2Context.h"
8 #include "WebGLContext.h"
9 #include "WebGLProgram.h"
10 #include "WebGLVertexArray.h"
11 #include "WebGLVertexAttribData.h"
12 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
14 using namespace mozilla
;
15 using namespace mozilla::dom
;
17 typedef union { GLint i
; GLfloat f
; GLuint u
; } fi_t
;
20 GLfloat
PuntToFloat(GLint i
)
28 GLfloat
PuntToFloat(GLuint u
)
36 WebGL2Context::ValidateAttribPointerType(bool integerMode
, GLenum type
,
37 GLsizei
* out_alignment
, const char* info
)
39 MOZ_ASSERT(out_alignment
);
43 case LOCAL_GL_UNSIGNED_BYTE
:
48 case LOCAL_GL_UNSIGNED_SHORT
:
53 case LOCAL_GL_UNSIGNED_INT
:
60 case LOCAL_GL_HALF_FLOAT
:
66 case LOCAL_GL_INT_2_10_10_10_REV
:
67 case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV
:
73 ErrorInvalidEnum("%s: invalid enum value 0x%x", info
, type
);
77 // -------------------------------------------------------------------------
78 // Uniforms and attributes
81 WebGL2Context::VertexAttribIPointer(GLuint index
, GLint size
, GLenum type
, GLsizei stride
,
87 if (!ValidateAttribIndex(index
, "vertexAttribIPointer"))
90 if (!ValidateAttribPointer(true, index
, size
, type
, LOCAL_GL_FALSE
, stride
, offset
,
91 "vertexAttribIPointer"))
96 MOZ_ASSERT(mBoundVertexArray
);
97 mBoundVertexArray
->EnsureAttrib(index
);
99 InvalidateBufferFetching();
101 WebGLVertexAttribData
& vd
= mBoundVertexArray
->mAttribs
[index
];
103 vd
.buf
= mBoundArrayBuffer
;
106 vd
.byteOffset
= offset
;
108 vd
.normalized
= false;
111 MakeContextCurrent();
112 gl
->fVertexAttribIPointer(index
, size
, type
, stride
, reinterpret_cast<void*>(offset
));
116 WebGL2Context::Uniform1ui(WebGLUniformLocation
* location
, GLuint v0
)
118 MOZ_CRASH("Not Implemented.");
122 WebGL2Context::Uniform2ui(WebGLUniformLocation
* location
, GLuint v0
, GLuint v1
)
124 MOZ_CRASH("Not Implemented.");
128 WebGL2Context::Uniform3ui(WebGLUniformLocation
* location
, GLuint v0
, GLuint v1
, GLuint v2
)
130 MOZ_CRASH("Not Implemented.");
134 WebGL2Context::Uniform4ui(WebGLUniformLocation
* location
, GLuint v0
, GLuint v1
,
135 GLuint v2
, GLuint v3
)
137 MOZ_CRASH("Not Implemented.");
141 WebGL2Context::Uniform1uiv(WebGLUniformLocation
* location
,
142 const dom::Sequence
<GLuint
>& value
)
144 MOZ_CRASH("Not Implemented.");
148 WebGL2Context::Uniform2uiv(WebGLUniformLocation
* location
,
149 const dom::Sequence
<GLuint
>& value
)
151 MOZ_CRASH("Not Implemented.");
155 WebGL2Context::Uniform3uiv(WebGLUniformLocation
* location
,
156 const dom::Sequence
<GLuint
>& value
)
158 MOZ_CRASH("Not Implemented.");
162 WebGL2Context::Uniform4uiv(WebGLUniformLocation
* location
,
163 const dom::Sequence
<GLuint
>& value
)
165 MOZ_CRASH("Not Implemented.");
169 WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation
* location
, bool transpose
,
170 const dom::Float32Array
& value
)
172 MOZ_CRASH("Not Implemented.");
176 WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation
* location
, bool transpose
,
177 const dom::Sequence
<GLfloat
>& value
)
179 MOZ_CRASH("Not Implemented.");
183 WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation
* location
, bool transpose
,
184 const dom::Float32Array
& value
)
186 MOZ_CRASH("Not Implemented.");
190 WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation
* location
, bool transpose
,
191 const dom::Sequence
<GLfloat
>& value
)
193 MOZ_CRASH("Not Implemented.");
197 WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation
* location
, bool transpose
,
198 const dom::Float32Array
& value
)
200 MOZ_CRASH("Not Implemented.");
204 WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation
* location
, bool transpose
,
205 const dom::Sequence
<GLfloat
>& value
)
207 MOZ_CRASH("Not Implemented.");
211 WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation
* location
, bool transpose
,
212 const dom::Float32Array
& value
)
214 MOZ_CRASH("Not Implemented.");
218 WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation
* location
, bool transpose
,
219 const dom::Sequence
<GLfloat
>& value
)
221 MOZ_CRASH("Not Implemented.");
225 WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation
* location
, bool transpose
,
226 const dom::Float32Array
& value
)
228 MOZ_CRASH("Not Implemented.");
232 WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation
* location
, bool transpose
,
233 const dom::Sequence
<GLfloat
>& value
)
235 MOZ_CRASH("Not Implemented.");
239 WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation
* location
, bool transpose
,
240 const dom::Float32Array
& value
)
242 MOZ_CRASH("Not Implemented.");
246 WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation
* location
, bool transpose
,
247 const dom::Sequence
<GLfloat
>& value
)
249 MOZ_CRASH("Not Implemented.");
253 WebGL2Context::VertexAttribI4i(GLuint index
, GLint x
, GLint y
, GLint z
, GLint w
)
258 if (index
|| gl
->IsGLES()) {
259 MakeContextCurrent();
260 gl
->fVertexAttribI4i(index
, x
, y
, z
, w
);
262 mVertexAttrib0Vector
[0] = PuntToFloat(x
);
263 mVertexAttrib0Vector
[1] = PuntToFloat(y
);
264 mVertexAttrib0Vector
[2] = PuntToFloat(z
);
265 mVertexAttrib0Vector
[3] = PuntToFloat(w
);
270 WebGL2Context::VertexAttribI4iv(GLuint index
, size_t length
, const GLint
* v
)
272 if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length
))
275 if (index
|| gl
->IsGLES()) {
276 MakeContextCurrent();
277 gl
->fVertexAttribI4iv(index
, v
);
279 mVertexAttrib0Vector
[0] = PuntToFloat(v
[0]);
280 mVertexAttrib0Vector
[1] = PuntToFloat(v
[1]);
281 mVertexAttrib0Vector
[2] = PuntToFloat(v
[2]);
282 mVertexAttrib0Vector
[3] = PuntToFloat(v
[3]);
287 WebGL2Context::VertexAttribI4iv(GLuint index
, const dom::Sequence
<GLint
>& v
)
289 VertexAttribI4iv(index
, v
.Length(), v
.Elements());
293 WebGL2Context::VertexAttribI4ui(GLuint index
, GLuint x
, GLuint y
, GLuint z
, GLuint w
)
298 if (index
|| gl
->IsGLES()) {
299 MakeContextCurrent();
300 gl
->fVertexAttribI4ui(index
, x
, y
, z
, w
);
302 mVertexAttrib0Vector
[0] = PuntToFloat(x
);
303 mVertexAttrib0Vector
[1] = PuntToFloat(y
);
304 mVertexAttrib0Vector
[2] = PuntToFloat(z
);
305 mVertexAttrib0Vector
[3] = PuntToFloat(w
);
310 WebGL2Context::VertexAttribI4uiv(GLuint index
, size_t length
, const GLuint
* v
)
315 if (index
|| gl
->IsGLES()) {
316 MakeContextCurrent();
317 gl
->fVertexAttribI4uiv(index
, v
);
319 mVertexAttrib0Vector
[0] = PuntToFloat(v
[0]);
320 mVertexAttrib0Vector
[1] = PuntToFloat(v
[1]);
321 mVertexAttrib0Vector
[2] = PuntToFloat(v
[2]);
322 mVertexAttrib0Vector
[3] = PuntToFloat(v
[3]);
327 WebGL2Context::VertexAttribI4uiv(GLuint index
, const dom::Sequence
<GLuint
>& v
)
329 VertexAttribI4uiv(index
, v
.Length(), v
.Elements());
332 // -------------------------------------------------------------------------
333 // Uniform Buffer Objects and Transform Feedback Buffers
334 // TODO(djg): Implemented in WebGLContext
336 void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
337 void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
338 GLintptr offset, GLsizeiptr size);
341 /* This doesn't belong here. It's part of state querying */
343 WebGL2Context::GetIndexedParameter(GLenum target
, GLuint index
,
344 dom::Nullable
<dom::OwningWebGLBufferOrLongLong
>& retval
)
352 MakeContextCurrent();
355 case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
356 if (index
>= mGLMaxTransformFeedbackSeparateAttribs
)
357 return ErrorInvalidValue("getIndexedParameter: index should be less than "
358 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
360 retval
.SetValue().SetAsWebGLBuffer() =
361 mBoundTransformFeedbackBuffers
[index
].get();
364 case LOCAL_GL_UNIFORM_BUFFER_BINDING
:
365 if (index
>= mGLMaxUniformBufferBindings
)
366 return ErrorInvalidValue("getIndexedParameter: index should be than "
367 "MAX_UNIFORM_BUFFER_BINDINGS");
369 retval
.SetValue().SetAsWebGLBuffer() = mBoundUniformBuffers
[index
].get();
372 case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START
:
373 case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
374 case LOCAL_GL_UNIFORM_BUFFER_START
:
375 case LOCAL_GL_UNIFORM_BUFFER_SIZE
:
376 gl
->fGetInteger64i_v(target
, index
, &data
);
377 retval
.SetValue().SetAsLongLong() = data
;
381 ErrorInvalidEnumInfo("getIndexedParameter: target", target
);
385 WebGL2Context::GetUniformIndices(WebGLProgram
* program
,
386 const dom::Sequence
<nsString
>& uniformNames
,
387 dom::Nullable
< nsTArray
<GLuint
> >& retval
)
393 if (!ValidateObject("getUniformIndices: program", program
))
396 if (!uniformNames
.Length())
399 GLuint progname
= program
->GLName();
400 size_t count
= uniformNames
.Length();
401 nsTArray
<GLuint
>& arr
= retval
.SetValue();
403 MakeContextCurrent();
405 for (size_t n
= 0; n
< count
; n
++) {
406 NS_LossyConvertUTF16toASCII
name(uniformNames
[n
]);
407 // const GLchar* glname = name.get();
408 const GLchar
* glname
= nullptr;
409 name
.BeginReading(glname
);
412 gl
->fGetUniformIndices(progname
, 1, &glname
, &index
);
413 arr
.AppendElement(index
);
418 WebGL2Context::GetActiveUniforms(WebGLProgram
* program
,
419 const dom::Sequence
<GLuint
>& uniformIndices
,
421 dom::Nullable
< nsTArray
<GLint
> >& retval
)
427 if (!ValidateObject("getActiveUniforms: program", program
))
430 size_t count
= uniformIndices
.Length();
434 GLuint progname
= program
->GLName();
435 nsTArray
<GLint
>& arr
= retval
.SetValue();
436 arr
.SetLength(count
);
438 MakeContextCurrent();
439 gl
->fGetActiveUniformsiv(progname
, count
, uniformIndices
.Elements(), pname
,
444 WebGL2Context::GetUniformBlockIndex(WebGLProgram
* program
,
445 const nsAString
& uniformBlockName
)
450 if (!ValidateObject("getUniformBlockIndex: program", program
))
453 if (!ValidateGLSLVariableName(uniformBlockName
, "getUniformBlockIndex"))
456 NS_LossyConvertUTF16toASCII
cname(uniformBlockName
);
457 nsCString mappedName
;
458 program
->MapIdentifier(cname
, &mappedName
);
460 GLuint progname
= program
->GLName();
462 MakeContextCurrent();
463 return gl
->fGetUniformBlockIndex(progname
, mappedName
.get());
467 GetUniformBlockActiveUniforms(gl::GLContext
* gl
, JSContext
* cx
,
468 WebGL2Context
* owner
, GLuint progname
,
469 GLuint uniformBlockIndex
,
470 JS::MutableHandleObject out_array
)
473 gl
->fGetActiveUniformBlockiv(progname
, uniformBlockIndex
,
474 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &length
);
475 JS::RootedObject
obj(cx
, Uint32Array::Create(cx
, owner
, length
, nullptr));
480 DebugOnly
<bool> inited
= result
.Init(obj
);
482 result
.ComputeLengthAndData();
483 gl
->fGetActiveUniformBlockiv(progname
, uniformBlockIndex
,
484 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
,
485 (GLint
*) result
.Data());
492 WebGL2Context::GetActiveUniformBlockParameter(JSContext
* cx
, WebGLProgram
* program
,
493 GLuint uniformBlockIndex
, GLenum pname
,
494 Nullable
<dom::OwningUnsignedLongOrUint32ArrayOrBoolean
>& retval
,
501 if (!ValidateObject("getActiveUniformBlockParameter: program", program
))
504 GLuint progname
= program
->GLName();
507 MakeContextCurrent();
510 case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER
:
511 case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
:
512 gl
->fGetActiveUniformBlockiv(progname
, uniformBlockIndex
, pname
, ¶m
);
513 retval
.SetValue().SetAsBoolean() = (param
!= 0);
516 case LOCAL_GL_UNIFORM_BLOCK_BINDING
:
517 case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE
:
518 case LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH
:
519 case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
:
520 gl
->fGetActiveUniformBlockiv(progname
, uniformBlockIndex
, pname
, ¶m
);
521 retval
.SetValue().SetAsUnsignedLong() = param
;
524 case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
:
525 JS::RootedObject
array(cx
);
526 if (!GetUniformBlockActiveUniforms(gl
, cx
, this, progname
, uniformBlockIndex
,
529 rv
= NS_ERROR_OUT_OF_MEMORY
;
533 DebugOnly
<bool> inited
= retval
.SetValue().SetAsUint32Array().Init(array
);
539 ErrorInvalidEnumInfo("getActiveUniformBlockParameter: parameter", pname
);
542 #define WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH 256
545 WebGL2Context::GetActiveUniformBlockName(WebGLProgram
* program
, GLuint uniformBlockIndex
,
551 if (!ValidateObject("getActiveUniformBlockName: program", program
))
554 GLuint progname
= program
->GLName();
555 GLchar nameBuffer
[WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH
];
558 MakeContextCurrent();
559 gl
->fGetActiveUniformBlockName(progname
, uniformBlockIndex
,
560 WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH
, &length
,
562 retval
.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(nameBuffer
)));
565 #undef WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH
568 WebGL2Context::UniformBlockBinding(WebGLProgram
* program
, GLuint uniformBlockIndex
,
569 GLuint uniformBlockBinding
)
574 if (!ValidateObject("uniformBlockBinding: program", program
))
577 GLuint progname
= program
->GLName();
579 MakeContextCurrent();
580 gl
->fUniformBlockBinding(progname
, uniformBlockIndex
, uniformBlockBinding
);