Bumping manifests a=b2g-bump
[gecko.git] / dom / canvas / WebGL2ContextUniforms.cpp
blob6f9e80b18f9e0eba15bba65d751fff108d51869a
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"
7 #include "GLContext.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;
19 static inline
20 GLfloat PuntToFloat(GLint i)
22 fi_t tmp;
23 tmp.i = i;
24 return tmp.f;
27 static inline
28 GLfloat PuntToFloat(GLuint u)
30 fi_t tmp;
31 tmp.u = u;
32 return tmp.f;
35 bool
36 WebGL2Context::ValidateAttribPointerType(bool integerMode, GLenum type,
37 GLsizei* out_alignment, const char* info)
39 MOZ_ASSERT(out_alignment);
41 switch (type) {
42 case LOCAL_GL_BYTE:
43 case LOCAL_GL_UNSIGNED_BYTE:
44 *out_alignment = 1;
45 return true;
47 case LOCAL_GL_SHORT:
48 case LOCAL_GL_UNSIGNED_SHORT:
49 *out_alignment = 2;
50 return true;
52 case LOCAL_GL_INT:
53 case LOCAL_GL_UNSIGNED_INT:
54 *out_alignment = 4;
55 return true;
58 if (!integerMode) {
59 switch (type) {
60 case LOCAL_GL_HALF_FLOAT:
61 *out_alignment = 2;
62 return true;
64 case LOCAL_GL_FLOAT:
65 case LOCAL_GL_FIXED:
66 case LOCAL_GL_INT_2_10_10_10_REV:
67 case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
68 *out_alignment = 4;
69 return true;
73 ErrorInvalidEnum("%s: invalid enum value 0x%x", info, type);
74 return false;
77 // -------------------------------------------------------------------------
78 // Uniforms and attributes
80 void
81 WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride,
82 GLintptr offset)
84 if (IsContextLost())
85 return;
87 if (!ValidateAttribIndex(index, "vertexAttribIPointer"))
88 return;
90 if (!ValidateAttribPointer(true, index, size, type, LOCAL_GL_FALSE, stride, offset,
91 "vertexAttribIPointer"))
93 return;
96 MOZ_ASSERT(mBoundVertexArray);
97 mBoundVertexArray->EnsureAttrib(index);
99 InvalidateBufferFetching();
101 WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
103 vd.buf = mBoundArrayBuffer;
104 vd.stride = stride;
105 vd.size = size;
106 vd.byteOffset = offset;
107 vd.type = type;
108 vd.normalized = false;
109 vd.integer = true;
111 MakeContextCurrent();
112 gl->fVertexAttribIPointer(index, size, type, stride, reinterpret_cast<void*>(offset));
115 void
116 WebGL2Context::Uniform1ui(WebGLUniformLocation* location, GLuint v0)
118 MOZ_CRASH("Not Implemented.");
121 void
122 WebGL2Context::Uniform2ui(WebGLUniformLocation* location, GLuint v0, GLuint v1)
124 MOZ_CRASH("Not Implemented.");
127 void
128 WebGL2Context::Uniform3ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2)
130 MOZ_CRASH("Not Implemented.");
133 void
134 WebGL2Context::Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1,
135 GLuint v2, GLuint v3)
137 MOZ_CRASH("Not Implemented.");
140 void
141 WebGL2Context::Uniform1uiv(WebGLUniformLocation* location,
142 const dom::Sequence<GLuint>& value)
144 MOZ_CRASH("Not Implemented.");
147 void
148 WebGL2Context::Uniform2uiv(WebGLUniformLocation* location,
149 const dom::Sequence<GLuint>& value)
151 MOZ_CRASH("Not Implemented.");
154 void
155 WebGL2Context::Uniform3uiv(WebGLUniformLocation* location,
156 const dom::Sequence<GLuint>& value)
158 MOZ_CRASH("Not Implemented.");
161 void
162 WebGL2Context::Uniform4uiv(WebGLUniformLocation* location,
163 const dom::Sequence<GLuint>& value)
165 MOZ_CRASH("Not Implemented.");
168 void
169 WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose,
170 const dom::Float32Array& value)
172 MOZ_CRASH("Not Implemented.");
175 void
176 WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose,
177 const dom::Sequence<GLfloat>& value)
179 MOZ_CRASH("Not Implemented.");
182 void
183 WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose,
184 const dom::Float32Array& value)
186 MOZ_CRASH("Not Implemented.");
189 void
190 WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose,
191 const dom::Sequence<GLfloat>& value)
193 MOZ_CRASH("Not Implemented.");
196 void
197 WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose,
198 const dom::Float32Array& value)
200 MOZ_CRASH("Not Implemented.");
203 void
204 WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose,
205 const dom::Sequence<GLfloat>& value)
207 MOZ_CRASH("Not Implemented.");
210 void
211 WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose,
212 const dom::Float32Array& value)
214 MOZ_CRASH("Not Implemented.");
217 void
218 WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose,
219 const dom::Sequence<GLfloat>& value)
221 MOZ_CRASH("Not Implemented.");
224 void
225 WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose,
226 const dom::Float32Array& value)
228 MOZ_CRASH("Not Implemented.");
231 void
232 WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose,
233 const dom::Sequence<GLfloat>& value)
235 MOZ_CRASH("Not Implemented.");
238 void
239 WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose,
240 const dom::Float32Array& value)
242 MOZ_CRASH("Not Implemented.");
245 void
246 WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose,
247 const dom::Sequence<GLfloat>& value)
249 MOZ_CRASH("Not Implemented.");
252 void
253 WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
255 if (IsContextLost())
256 return;
258 if (index || gl->IsGLES()) {
259 MakeContextCurrent();
260 gl->fVertexAttribI4i(index, x, y, z, w);
261 } else {
262 mVertexAttrib0Vector[0] = PuntToFloat(x);
263 mVertexAttrib0Vector[1] = PuntToFloat(y);
264 mVertexAttrib0Vector[2] = PuntToFloat(z);
265 mVertexAttrib0Vector[3] = PuntToFloat(w);
269 void
270 WebGL2Context::VertexAttribI4iv(GLuint index, size_t length, const GLint* v)
272 if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
273 return;
275 if (index || gl->IsGLES()) {
276 MakeContextCurrent();
277 gl->fVertexAttribI4iv(index, v);
278 } else {
279 mVertexAttrib0Vector[0] = PuntToFloat(v[0]);
280 mVertexAttrib0Vector[1] = PuntToFloat(v[1]);
281 mVertexAttrib0Vector[2] = PuntToFloat(v[2]);
282 mVertexAttrib0Vector[3] = PuntToFloat(v[3]);
286 void
287 WebGL2Context::VertexAttribI4iv(GLuint index, const dom::Sequence<GLint>& v)
289 VertexAttribI4iv(index, v.Length(), v.Elements());
292 void
293 WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
295 if (IsContextLost())
296 return;
298 if (index || gl->IsGLES()) {
299 MakeContextCurrent();
300 gl->fVertexAttribI4ui(index, x, y, z, w);
301 } else {
302 mVertexAttrib0Vector[0] = PuntToFloat(x);
303 mVertexAttrib0Vector[1] = PuntToFloat(y);
304 mVertexAttrib0Vector[2] = PuntToFloat(z);
305 mVertexAttrib0Vector[3] = PuntToFloat(w);
309 void
310 WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
312 if (IsContextLost())
313 return;
315 if (index || gl->IsGLES()) {
316 MakeContextCurrent();
317 gl->fVertexAttribI4uiv(index, v);
318 } else {
319 mVertexAttrib0Vector[0] = PuntToFloat(v[0]);
320 mVertexAttrib0Vector[1] = PuntToFloat(v[1]);
321 mVertexAttrib0Vector[2] = PuntToFloat(v[2]);
322 mVertexAttrib0Vector[3] = PuntToFloat(v[3]);
326 void
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 */
342 void
343 WebGL2Context::GetIndexedParameter(GLenum target, GLuint index,
344 dom::Nullable<dom::OwningWebGLBufferOrLongLong>& retval)
346 retval.SetNull();
347 if (IsContextLost())
348 return;
350 GLint64 data = 0;
352 MakeContextCurrent();
354 switch (target) {
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();
362 return;
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();
370 return;
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;
378 return;
381 ErrorInvalidEnumInfo("getIndexedParameter: target", target);
384 void
385 WebGL2Context::GetUniformIndices(WebGLProgram* program,
386 const dom::Sequence<nsString>& uniformNames,
387 dom::Nullable< nsTArray<GLuint> >& retval)
389 retval.SetNull();
390 if (IsContextLost())
391 return;
393 if (!ValidateObject("getUniformIndices: program", program))
394 return;
396 if (!uniformNames.Length())
397 return;
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);
411 GLuint index = 0;
412 gl->fGetUniformIndices(progname, 1, &glname, &index);
413 arr.AppendElement(index);
417 void
418 WebGL2Context::GetActiveUniforms(WebGLProgram* program,
419 const dom::Sequence<GLuint>& uniformIndices,
420 GLenum pname,
421 dom::Nullable< nsTArray<GLint> >& retval)
423 retval.SetNull();
424 if (IsContextLost())
425 return;
427 if (!ValidateObject("getActiveUniforms: program", program))
428 return;
430 size_t count = uniformIndices.Length();
431 if (!count)
432 return;
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,
440 arr.Elements());
443 GLuint
444 WebGL2Context::GetUniformBlockIndex(WebGLProgram* program,
445 const nsAString& uniformBlockName)
447 if (IsContextLost())
448 return 0;
450 if (!ValidateObject("getUniformBlockIndex: program", program))
451 return 0;
453 if (!ValidateGLSLVariableName(uniformBlockName, "getUniformBlockIndex"))
454 return 0;
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());
466 static bool
467 GetUniformBlockActiveUniforms(gl::GLContext* gl, JSContext* cx,
468 WebGL2Context* owner, GLuint progname,
469 GLuint uniformBlockIndex,
470 JS::MutableHandleObject out_array)
472 GLint length = 0;
473 gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex,
474 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &length);
475 JS::RootedObject obj(cx, Uint32Array::Create(cx, owner, length, nullptr));
476 if (!obj)
477 return false;
479 Uint32Array result;
480 DebugOnly<bool> inited = result.Init(obj);
481 MOZ_ASSERT(inited);
482 result.ComputeLengthAndData();
483 gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex,
484 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
485 (GLint*) result.Data());
487 out_array.set(obj);
488 return true;
491 void
492 WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, WebGLProgram* program,
493 GLuint uniformBlockIndex, GLenum pname,
494 Nullable<dom::OwningUnsignedLongOrUint32ArrayOrBoolean>& retval,
495 ErrorResult& rv)
497 retval.SetNull();
498 if (IsContextLost())
499 return;
501 if (!ValidateObject("getActiveUniformBlockParameter: program", program))
502 return;
504 GLuint progname = program->GLName();
505 GLint param = 0;
507 MakeContextCurrent();
509 switch(pname) {
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, &param);
513 retval.SetValue().SetAsBoolean() = (param != 0);
514 return;
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, &param);
521 retval.SetValue().SetAsUnsignedLong() = param;
522 return;
524 case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
525 JS::RootedObject array(cx);
526 if (!GetUniformBlockActiveUniforms(gl, cx, this, progname, uniformBlockIndex,
527 &array))
529 rv = NS_ERROR_OUT_OF_MEMORY;
530 return;
533 DebugOnly<bool> inited = retval.SetValue().SetAsUint32Array().Init(array);
534 MOZ_ASSERT(inited);
536 return;
539 ErrorInvalidEnumInfo("getActiveUniformBlockParameter: parameter", pname);
542 #define WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH 256
544 void
545 WebGL2Context::GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex,
546 nsAString& retval)
548 if (IsContextLost())
549 return;
551 if (!ValidateObject("getActiveUniformBlockName: program", program))
552 return;
554 GLuint progname = program->GLName();
555 GLchar nameBuffer[WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH];
556 GLsizei length = 0;
558 MakeContextCurrent();
559 gl->fGetActiveUniformBlockName(progname, uniformBlockIndex,
560 WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH, &length,
561 nameBuffer);
562 retval.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(nameBuffer)));
565 #undef WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH
567 void
568 WebGL2Context::UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex,
569 GLuint uniformBlockBinding)
571 if (IsContextLost())
572 return;
574 if (!ValidateObject("uniformBlockBinding: program", program))
575 return;
577 GLuint progname = program->GLName();
579 MakeContextCurrent();
580 gl->fUniformBlockBinding(progname, uniformBlockIndex, uniformBlockBinding);