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