/src/mozilla-central/dom/canvas/WebGL2ContextUniforms.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
5 | | |
6 | | #include "WebGL2Context.h" |
7 | | |
8 | | #include "GLContext.h" |
9 | | #include "mozilla/dom/WebGL2RenderingContextBinding.h" |
10 | | #include "mozilla/RefPtr.h" |
11 | | #include "WebGLBuffer.h" |
12 | | #include "WebGLContext.h" |
13 | | #include "WebGLProgram.h" |
14 | | #include "WebGLUniformLocation.h" |
15 | | #include "WebGLVertexArray.h" |
16 | | #include "WebGLVertexAttribData.h" |
17 | | |
18 | | namespace mozilla { |
19 | | |
20 | | // ------------------------------------------------------------------------- |
21 | | // Uniforms |
22 | | |
23 | | void |
24 | | WebGLContext::Uniform1ui(WebGLUniformLocation* loc, GLuint v0) |
25 | 0 | { |
26 | 0 | const FuncScope funcScope(*this, "uniform1ui"); |
27 | 0 | if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT)) |
28 | 0 | return; |
29 | 0 | |
30 | 0 | gl->fUniform1ui(loc->mLoc, v0); |
31 | 0 | } |
32 | | |
33 | | void |
34 | | WebGLContext::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1) |
35 | 0 | { |
36 | 0 | const FuncScope funcScope(*this, "uniform2ui"); |
37 | 0 | if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT)) |
38 | 0 | return; |
39 | 0 | |
40 | 0 | gl->fUniform2ui(loc->mLoc, v0, v1); |
41 | 0 | } |
42 | | |
43 | | void |
44 | | WebGLContext::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2) |
45 | 0 | { |
46 | 0 | const FuncScope funcScope(*this, "uniform3ui"); |
47 | 0 | if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT)) |
48 | 0 | return; |
49 | 0 | |
50 | 0 | gl->fUniform3ui(loc->mLoc, v0, v1, v2); |
51 | 0 | } |
52 | | |
53 | | void |
54 | | WebGLContext::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2, |
55 | | GLuint v3) |
56 | 0 | { |
57 | 0 | const FuncScope funcScope(*this, "uniform4ui"); |
58 | 0 | if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT)) |
59 | 0 | return; |
60 | 0 | |
61 | 0 | gl->fUniform4ui(loc->mLoc, v0, v1, v2, v3); |
62 | 0 | } |
63 | | |
64 | | // ------------------------------------------------------------------------- |
65 | | // Uniform Buffer Objects and Transform Feedback Buffers |
66 | | |
67 | | void |
68 | | WebGL2Context::GetIndexedParameter(JSContext* cx, GLenum target, GLuint index, |
69 | | JS::MutableHandleValue retval, ErrorResult& out_error) |
70 | 0 | { |
71 | 0 | const FuncScope funcScope(*this, "getIndexedParameter"); |
72 | 0 | retval.set(JS::NullValue()); |
73 | 0 | if (IsContextLost()) |
74 | 0 | return; |
75 | 0 | |
76 | 0 | const std::vector<IndexedBufferBinding>* bindings; |
77 | 0 | switch (target) { |
78 | 0 | case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: |
79 | 0 | case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START: |
80 | 0 | case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: |
81 | 0 | bindings = &(mBoundTransformFeedback->mIndexedBindings); |
82 | 0 | break; |
83 | 0 |
|
84 | 0 | case LOCAL_GL_UNIFORM_BUFFER_BINDING: |
85 | 0 | case LOCAL_GL_UNIFORM_BUFFER_START: |
86 | 0 | case LOCAL_GL_UNIFORM_BUFFER_SIZE: |
87 | 0 | bindings = &mIndexedUniformBufferBindings; |
88 | 0 | break; |
89 | 0 |
|
90 | 0 | default: |
91 | 0 | ErrorInvalidEnumInfo("target", target); |
92 | 0 | return; |
93 | 0 | } |
94 | 0 | |
95 | 0 | if (index >= bindings->size()) { |
96 | 0 | ErrorInvalidValue("`index` must be < %s.", |
97 | 0 | "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"); |
98 | 0 | return; |
99 | 0 | } |
100 | 0 | const auto& binding = (*bindings)[index]; |
101 | 0 |
|
102 | 0 | JS::Value ret = JS::NullValue(); |
103 | 0 |
|
104 | 0 | switch (target) { |
105 | 0 | case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: |
106 | 0 | case LOCAL_GL_UNIFORM_BUFFER_BINDING: |
107 | 0 | if (binding.mBufferBinding) { |
108 | 0 | ret = WebGLObjectAsJSValue(cx, binding.mBufferBinding.get(), out_error); |
109 | 0 | } |
110 | 0 | break; |
111 | 0 |
|
112 | 0 | case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START: |
113 | 0 | case LOCAL_GL_UNIFORM_BUFFER_START: |
114 | 0 | ret = JS::NumberValue(binding.mRangeStart); |
115 | 0 | break; |
116 | 0 |
|
117 | 0 | case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: |
118 | 0 | case LOCAL_GL_UNIFORM_BUFFER_SIZE: |
119 | 0 | ret = JS::NumberValue(binding.mRangeSize); |
120 | 0 | break; |
121 | 0 | } |
122 | 0 |
|
123 | 0 | retval.set(ret); |
124 | 0 | } |
125 | | |
126 | | void |
127 | | WebGL2Context::GetUniformIndices(const WebGLProgram& program, |
128 | | const dom::Sequence<nsString>& uniformNames, |
129 | | dom::Nullable< nsTArray<GLuint> >& retval) |
130 | 0 | { |
131 | 0 | const FuncScope funcScope(*this, "getUniformIndices"); |
132 | 0 | retval.SetNull(); |
133 | 0 | if (IsContextLost()) |
134 | 0 | return; |
135 | 0 | |
136 | 0 | if (!ValidateObject("program", program)) |
137 | 0 | return; |
138 | 0 | |
139 | 0 | if (!uniformNames.Length()) |
140 | 0 | return; |
141 | 0 | |
142 | 0 | program.GetUniformIndices(uniformNames, retval); |
143 | 0 | } |
144 | | |
145 | | void |
146 | | WebGL2Context::GetActiveUniforms(JSContext* cx, const WebGLProgram& program, |
147 | | const dom::Sequence<GLuint>& uniformIndices, |
148 | | GLenum pname, JS::MutableHandleValue retval) |
149 | 0 | { |
150 | 0 | const FuncScope funcScope(*this, "getActiveUniforms"); |
151 | 0 | retval.setNull(); |
152 | 0 | if (IsContextLost()) |
153 | 0 | return; |
154 | 0 | |
155 | 0 | switch (pname) { |
156 | 0 | case LOCAL_GL_UNIFORM_TYPE: |
157 | 0 | case LOCAL_GL_UNIFORM_SIZE: |
158 | 0 | case LOCAL_GL_UNIFORM_BLOCK_INDEX: |
159 | 0 | case LOCAL_GL_UNIFORM_OFFSET: |
160 | 0 | case LOCAL_GL_UNIFORM_ARRAY_STRIDE: |
161 | 0 | case LOCAL_GL_UNIFORM_MATRIX_STRIDE: |
162 | 0 | case LOCAL_GL_UNIFORM_IS_ROW_MAJOR: |
163 | 0 | break; |
164 | 0 |
|
165 | 0 | default: |
166 | 0 | ErrorInvalidEnumInfo("pname", pname); |
167 | 0 | return; |
168 | 0 | } |
169 | 0 | |
170 | 0 | if (!ValidateObject("program", program)) |
171 | 0 | return; |
172 | 0 | |
173 | 0 | if (!program.IsLinked()) { |
174 | 0 | ErrorInvalidOperation("`program` must be linked."); |
175 | 0 | return; |
176 | 0 | } |
177 | 0 | |
178 | 0 | const auto& numActiveUniforms = program.LinkInfo()->uniforms.size(); |
179 | 0 | for (const auto& curIndex : uniformIndices) { |
180 | 0 | if (curIndex >= numActiveUniforms) { |
181 | 0 | ErrorInvalidValue("Too-large active uniform index queried."); |
182 | 0 | return; |
183 | 0 | } |
184 | 0 | } |
185 | 0 |
|
186 | 0 | const auto& count = uniformIndices.Length(); |
187 | 0 |
|
188 | 0 | JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count)); |
189 | 0 | UniquePtr<GLint[]> samples(new GLint[count]); |
190 | 0 | if (!array || !samples) { |
191 | 0 | ErrorOutOfMemory("Failed to allocate buffers."); |
192 | 0 | return; |
193 | 0 | } |
194 | 0 | retval.setObject(*array); |
195 | 0 |
|
196 | 0 | gl->fGetActiveUniformsiv(program.mGLName, count, uniformIndices.Elements(), pname, |
197 | 0 | samples.get()); |
198 | 0 |
|
199 | 0 | switch (pname) { |
200 | 0 | case LOCAL_GL_UNIFORM_TYPE: |
201 | 0 | case LOCAL_GL_UNIFORM_SIZE: |
202 | 0 | case LOCAL_GL_UNIFORM_BLOCK_INDEX: |
203 | 0 | case LOCAL_GL_UNIFORM_OFFSET: |
204 | 0 | case LOCAL_GL_UNIFORM_ARRAY_STRIDE: |
205 | 0 | case LOCAL_GL_UNIFORM_MATRIX_STRIDE: |
206 | 0 | for (size_t i = 0; i < count; ++i) { |
207 | 0 | JS::RootedValue value(cx); |
208 | 0 | value = JS::Int32Value(samples[i]); |
209 | 0 | if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) |
210 | 0 | return; |
211 | 0 | } |
212 | 0 | break; |
213 | 0 | case LOCAL_GL_UNIFORM_IS_ROW_MAJOR: |
214 | 0 | for (size_t i = 0; i < count; ++i) { |
215 | 0 | JS::RootedValue value(cx); |
216 | 0 | value = JS::BooleanValue(samples[i]); |
217 | 0 | if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) |
218 | 0 | return; |
219 | 0 | } |
220 | 0 | break; |
221 | 0 |
|
222 | 0 | default: |
223 | 0 | MOZ_CRASH("Invalid pname"); |
224 | 0 | } |
225 | 0 | } |
226 | | |
227 | | GLuint |
228 | | WebGL2Context::GetUniformBlockIndex(const WebGLProgram& program, |
229 | | const nsAString& uniformBlockName) |
230 | 0 | { |
231 | 0 | const FuncScope funcScope(*this, "getUniformBlockIndex"); |
232 | 0 | if (IsContextLost()) |
233 | 0 | return 0; |
234 | 0 | |
235 | 0 | if (!ValidateObject("program", program)) |
236 | 0 | return 0; |
237 | 0 | |
238 | 0 | return program.GetUniformBlockIndex(uniformBlockName); |
239 | 0 | } |
240 | | |
241 | | void |
242 | | WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, const WebGLProgram& program, |
243 | | GLuint uniformBlockIndex, GLenum pname, |
244 | | JS::MutableHandleValue out_retval, |
245 | | ErrorResult& out_error) |
246 | 0 | { |
247 | 0 | const FuncScope funcScope(*this, "getActiveUniformBlockParameter"); |
248 | 0 | out_retval.setNull(); |
249 | 0 | if (IsContextLost()) |
250 | 0 | return; |
251 | 0 | |
252 | 0 | if (!ValidateObject("program", program)) |
253 | 0 | return; |
254 | 0 | |
255 | 0 | switch(pname) { |
256 | 0 | case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: |
257 | 0 | case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: |
258 | 0 | case LOCAL_GL_UNIFORM_BLOCK_BINDING: |
259 | 0 | case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE: |
260 | 0 | case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: |
261 | 0 | out_retval.set(program.GetActiveUniformBlockParam(uniformBlockIndex, pname)); |
262 | 0 | return; |
263 | 0 |
|
264 | 0 | case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: |
265 | 0 | out_retval.set(program.GetActiveUniformBlockActiveUniforms(cx, uniformBlockIndex, |
266 | 0 | &out_error)); |
267 | 0 | return; |
268 | 0 | } |
269 | 0 |
|
270 | 0 | ErrorInvalidEnumInfo("parameter", pname); |
271 | 0 | } |
272 | | |
273 | | void |
274 | | WebGL2Context::GetActiveUniformBlockName(const WebGLProgram& program, |
275 | | GLuint uniformBlockIndex, nsAString& retval) |
276 | 0 | { |
277 | 0 | const FuncScope funcScope(*this, "getActiveUniformBlockName"); |
278 | 0 | retval.SetIsVoid(true); |
279 | 0 | if (IsContextLost()) |
280 | 0 | return; |
281 | 0 | |
282 | 0 | if (!ValidateObject("program", program)) |
283 | 0 | return; |
284 | 0 | |
285 | 0 | program.GetActiveUniformBlockName(uniformBlockIndex, retval); |
286 | 0 | } |
287 | | |
288 | | void |
289 | | WebGL2Context::UniformBlockBinding(WebGLProgram& program, GLuint uniformBlockIndex, |
290 | | GLuint uniformBlockBinding) |
291 | 0 | { |
292 | 0 | const FuncScope funcScope(*this, "uniformBlockBinding"); |
293 | 0 | if (IsContextLost()) |
294 | 0 | return; |
295 | 0 | |
296 | 0 | if (!ValidateObject("program", program)) |
297 | 0 | return; |
298 | 0 | |
299 | 0 | program.UniformBlockBinding(uniformBlockIndex, uniformBlockBinding); |
300 | 0 | } |
301 | | |
302 | | } // namespace mozilla |