summaryrefslogtreecommitdiffstats
path: root/dom/canvas/WebGL2ContextUniforms.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/WebGL2ContextUniforms.cpp')
-rw-r--r--dom/canvas/WebGL2ContextUniforms.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/dom/canvas/WebGL2ContextUniforms.cpp b/dom/canvas/WebGL2ContextUniforms.cpp
new file mode 100644
index 000000000..7f8c07332
--- /dev/null
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebGL2Context.h"
+
+#include "GLContext.h"
+#include "mozilla/dom/WebGL2RenderingContextBinding.h"
+#include "mozilla/RefPtr.h"
+#include "WebGLBuffer.h"
+#include "WebGLContext.h"
+#include "WebGLProgram.h"
+#include "WebGLUniformLocation.h"
+#include "WebGLVertexArray.h"
+#include "WebGLVertexAttribData.h"
+
+namespace mozilla {
+
+bool
+WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*info*/)
+{
+ return true;
+}
+
+// -------------------------------------------------------------------------
+// Uniforms
+
+void
+WebGLContext::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
+{
+ if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui"))
+ return;
+
+ MakeContextCurrent();
+ gl->fUniform1ui(loc->mLoc, v0);
+}
+
+void
+WebGLContext::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
+{
+ if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui"))
+ return;
+
+ MakeContextCurrent();
+ gl->fUniform2ui(loc->mLoc, v0, v1);
+}
+
+void
+WebGLContext::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2)
+{
+ if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui"))
+ return;
+
+ MakeContextCurrent();
+ gl->fUniform3ui(loc->mLoc, v0, v1, v2);
+}
+
+void
+WebGLContext::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
+ GLuint v3)
+{
+ if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui"))
+ return;
+
+ MakeContextCurrent();
+ gl->fUniform4ui(loc->mLoc, v0, v1, v2, v3);
+}
+
+// -------------------------------------------------------------------------
+// Uniform Buffer Objects and Transform Feedback Buffers
+
+void
+WebGL2Context::GetIndexedParameter(JSContext* cx, GLenum target, GLuint index,
+ JS::MutableHandleValue retval, ErrorResult& out_error)
+{
+ const char funcName[] = "getIndexedParameter";
+ retval.set(JS::NullValue());
+ if (IsContextLost())
+ return;
+
+ const std::vector<IndexedBufferBinding>* bindings;
+ switch (target) {
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ bindings = &(mBoundTransformFeedback->mIndexedBindings);
+ break;
+
+ case LOCAL_GL_UNIFORM_BUFFER_BINDING:
+ case LOCAL_GL_UNIFORM_BUFFER_START:
+ case LOCAL_GL_UNIFORM_BUFFER_SIZE:
+ bindings = &mIndexedUniformBufferBindings;
+ break;
+
+ default:
+ ErrorInvalidEnumInfo("getIndexedParameter: target", target);
+ return;
+ }
+
+ if (index >= bindings->size()) {
+ ErrorInvalidValue("%s: `index` must be < %s.", funcName,
+ "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
+ return;
+ }
+ const auto& binding = (*bindings)[index];
+
+ JS::Value ret = JS::NullValue();
+
+ switch (target) {
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case LOCAL_GL_UNIFORM_BUFFER_BINDING:
+ if (binding.mBufferBinding) {
+ ret = WebGLObjectAsJSValue(cx, binding.mBufferBinding.get(), out_error);
+ }
+ break;
+
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case LOCAL_GL_UNIFORM_BUFFER_START:
+ ret = JS::NumberValue(binding.mRangeStart);
+ break;
+
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case LOCAL_GL_UNIFORM_BUFFER_SIZE:
+ ret = JS::NumberValue(binding.mRangeSize);
+ break;
+ }
+
+ retval.set(ret);
+}
+
+void
+WebGL2Context::GetUniformIndices(const WebGLProgram& program,
+ const dom::Sequence<nsString>& uniformNames,
+ dom::Nullable< nsTArray<GLuint> >& retval)
+{
+ retval.SetNull();
+ if (IsContextLost())
+ return;
+
+ if (!ValidateObject("getUniformIndices: program", program))
+ return;
+
+ if (!uniformNames.Length())
+ return;
+
+ program.GetUniformIndices(uniformNames, retval);
+}
+
+static bool
+ValidateUniformEnum(WebGLContext* webgl, GLenum pname, const char* info)
+{
+ switch (pname) {
+ case LOCAL_GL_UNIFORM_TYPE:
+ case LOCAL_GL_UNIFORM_SIZE:
+ case LOCAL_GL_UNIFORM_BLOCK_INDEX:
+ case LOCAL_GL_UNIFORM_OFFSET:
+ case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
+ case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
+ case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
+ return true;
+
+ default:
+ webgl->ErrorInvalidEnumArg(info, "pname", pname);
+ return false;
+ }
+}
+
+void
+WebGL2Context::GetActiveUniforms(JSContext* cx, const WebGLProgram& program,
+ const dom::Sequence<GLuint>& uniformIndices,
+ GLenum pname, JS::MutableHandleValue retval)
+{
+ const char funcName[] = "getActiveUniforms";
+ retval.setNull();
+ if (IsContextLost())
+ return;
+
+ if (!ValidateUniformEnum(this, pname, funcName))
+ return;
+
+ if (!ValidateObject("getActiveUniforms: program", program))
+ return;
+
+ const auto& numActiveUniforms = program.LinkInfo()->uniforms.size();
+ for (const auto& curIndex : uniformIndices) {
+ if (curIndex >= numActiveUniforms) {
+ ErrorInvalidValue("%s: Too-large active uniform index queried.", funcName);
+ return;
+ }
+ }
+
+ const auto& count = uniformIndices.Length();
+
+ JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
+ UniquePtr<GLint[]> samples(new GLint[count]);
+ if (!array || !samples) {
+ ErrorOutOfMemory("%s: Failed to allocate buffers.", funcName);
+ return;
+ }
+ retval.setObject(*array);
+
+ MakeContextCurrent();
+ gl->fGetActiveUniformsiv(program.mGLName, count, uniformIndices.Elements(), pname,
+ samples.get());
+
+ switch (pname) {
+ case LOCAL_GL_UNIFORM_TYPE:
+ case LOCAL_GL_UNIFORM_SIZE:
+ case LOCAL_GL_UNIFORM_BLOCK_INDEX:
+ case LOCAL_GL_UNIFORM_OFFSET:
+ case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
+ case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
+ for (size_t i = 0; i < count; ++i) {
+ JS::RootedValue value(cx);
+ value = JS::Int32Value(samples[i]);
+ if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE))
+ return;
+ }
+ break;
+ case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
+ for (size_t i = 0; i < count; ++i) {
+ JS::RootedValue value(cx);
+ value = JS::BooleanValue(samples[i]);
+ if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE))
+ return;
+ }
+ break;
+
+ default:
+ MOZ_CRASH("Invalid pname");
+ }
+}
+
+GLuint
+WebGL2Context::GetUniformBlockIndex(const WebGLProgram& program,
+ const nsAString& uniformBlockName)
+{
+ if (IsContextLost())
+ return 0;
+
+ if (!ValidateObject("getUniformBlockIndex: program", program))
+ return 0;
+
+ return program.GetUniformBlockIndex(uniformBlockName);
+}
+
+void
+WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, const WebGLProgram& program,
+ GLuint uniformBlockIndex, GLenum pname,
+ JS::MutableHandleValue out_retval,
+ ErrorResult& out_error)
+{
+ out_retval.setNull();
+ if (IsContextLost())
+ return;
+
+ if (!ValidateObject("getActiveUniformBlockParameter: program", program))
+ return;
+
+ MakeContextCurrent();
+
+ switch(pname) {
+ case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ case LOCAL_GL_UNIFORM_BLOCK_BINDING:
+ case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE:
+ case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ out_retval.set(program.GetActiveUniformBlockParam(uniformBlockIndex, pname));
+ return;
+
+ case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ out_retval.set(program.GetActiveUniformBlockActiveUniforms(cx, uniformBlockIndex,
+ &out_error));
+ return;
+ }
+
+ ErrorInvalidEnumInfo("getActiveUniformBlockParameter: parameter", pname);
+}
+
+void
+WebGL2Context::GetActiveUniformBlockName(const WebGLProgram& program,
+ GLuint uniformBlockIndex, nsAString& retval)
+{
+ retval.SetIsVoid(true);
+ if (IsContextLost())
+ return;
+
+ if (!ValidateObject("getActiveUniformBlockName: program", program))
+ return;
+
+ program.GetActiveUniformBlockName(uniformBlockIndex, retval);
+}
+
+void
+WebGL2Context::UniformBlockBinding(WebGLProgram& program, GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ if (IsContextLost())
+ return;
+
+ if (!ValidateObject("uniformBlockBinding: program", program))
+ return;
+
+ program.UniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
+}
+
+} // namespace mozilla