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 "WebGLContext.h"
7 :
8 : #include "GLContext.h"
9 : #include "GLScreenBuffer.h"
10 : #include "mozilla/dom/ToJSValue.h"
11 : #include "mozilla/Preferences.h"
12 : #include "nsString.h"
13 : #include "WebGLBuffer.h"
14 : #include "WebGLContextUtils.h"
15 : #include "WebGLFramebuffer.h"
16 : #include "WebGLProgram.h"
17 : #include "WebGLRenderbuffer.h"
18 : #include "WebGLShader.h"
19 : #include "WebGLTexture.h"
20 : #include "WebGLVertexArray.h"
21 :
22 : namespace mozilla {
23 :
24 : void
25 0 : WebGLContext::Disable(GLenum cap)
26 : {
27 0 : if (IsContextLost())
28 0 : return;
29 :
30 0 : if (!ValidateCapabilityEnum(cap, "disable"))
31 0 : return;
32 :
33 0 : realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
34 :
35 0 : if (trackingSlot)
36 : {
37 0 : *trackingSlot = 0;
38 : }
39 :
40 0 : MakeContextCurrent();
41 0 : gl->fDisable(cap);
42 : }
43 :
44 : void
45 0 : WebGLContext::Enable(GLenum cap)
46 : {
47 0 : if (IsContextLost())
48 0 : return;
49 :
50 0 : if (!ValidateCapabilityEnum(cap, "enable"))
51 0 : return;
52 :
53 0 : realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
54 :
55 0 : if (trackingSlot)
56 : {
57 0 : *trackingSlot = 1;
58 : }
59 :
60 0 : MakeContextCurrent();
61 0 : gl->fEnable(cap);
62 : }
63 :
64 : bool
65 0 : WebGLContext::GetStencilBits(GLint* const out_stencilBits)
66 : {
67 0 : *out_stencilBits = 0;
68 0 : if (mBoundDrawFramebuffer) {
69 0 : if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() &&
70 0 : mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
71 : {
72 : // Error, we don't know which stencil buffer's bits to use
73 0 : ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
74 0 : return false;
75 : }
76 :
77 0 : if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() ||
78 0 : mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
79 : {
80 0 : *out_stencilBits = 8;
81 : }
82 0 : } else if (mOptions.stencil) {
83 0 : *out_stencilBits = 8;
84 : }
85 :
86 0 : return true;
87 : }
88 :
89 : bool
90 0 : WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val)
91 : {
92 0 : if (mBoundDrawFramebuffer) {
93 0 : if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
94 0 : return false;
95 : }
96 :
97 0 : if (!mBoundDrawFramebuffer) {
98 0 : switch (pname) {
99 : case LOCAL_GL_RED_BITS:
100 : case LOCAL_GL_GREEN_BITS:
101 : case LOCAL_GL_BLUE_BITS:
102 0 : *out_val = 8;
103 0 : break;
104 :
105 : case LOCAL_GL_ALPHA_BITS:
106 0 : *out_val = (mOptions.alpha ? 8 : 0);
107 0 : break;
108 :
109 : case LOCAL_GL_DEPTH_BITS:
110 0 : if (mOptions.depth) {
111 0 : *out_val = gl->Screen()->DepthBits();
112 : } else {
113 0 : *out_val = 0;
114 : }
115 0 : break;
116 :
117 : case LOCAL_GL_STENCIL_BITS:
118 0 : *out_val = (mOptions.stencil ? 8 : 0);
119 0 : break;
120 :
121 : default:
122 0 : MOZ_CRASH("GFX: bad pname");
123 : }
124 0 : return true;
125 : }
126 :
127 0 : if (!gl->IsCoreProfile()) {
128 0 : gl->fGetIntegerv(pname, out_val);
129 0 : return true;
130 : }
131 :
132 0 : GLenum fbAttachment = 0;
133 0 : GLenum fbPName = 0;
134 0 : switch (pname) {
135 : case LOCAL_GL_RED_BITS:
136 0 : fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
137 0 : fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
138 0 : break;
139 :
140 : case LOCAL_GL_GREEN_BITS:
141 0 : fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
142 0 : fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
143 0 : break;
144 :
145 : case LOCAL_GL_BLUE_BITS:
146 0 : fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
147 0 : fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
148 0 : break;
149 :
150 : case LOCAL_GL_ALPHA_BITS:
151 0 : fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0;
152 0 : fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
153 0 : break;
154 :
155 : case LOCAL_GL_DEPTH_BITS:
156 0 : fbAttachment = LOCAL_GL_DEPTH_ATTACHMENT;
157 0 : fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
158 0 : break;
159 :
160 : case LOCAL_GL_STENCIL_BITS:
161 0 : fbAttachment = LOCAL_GL_STENCIL_ATTACHMENT;
162 0 : fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE;
163 0 : break;
164 :
165 : default:
166 0 : MOZ_CRASH("GFX: bad pname");
167 : }
168 :
169 0 : gl->fGetFramebufferAttachmentParameteriv(LOCAL_GL_DRAW_FRAMEBUFFER, fbAttachment,
170 0 : fbPName, out_val);
171 0 : return true;
172 : }
173 :
174 : JS::Value
175 0 : WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
176 : {
177 0 : const char funcName[] = "getParameter";
178 :
179 0 : if (IsContextLost())
180 0 : return JS::NullValue();
181 :
182 0 : MakeContextCurrent();
183 :
184 0 : if (MinCapabilityMode()) {
185 0 : switch(pname) {
186 : ////////////////////////////
187 : // Single-value params
188 :
189 : // int
190 : case LOCAL_GL_MAX_VERTEX_ATTRIBS:
191 0 : return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_ATTRIBS);
192 :
193 : case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
194 0 : return JS::Int32Value(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
195 :
196 : case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
197 0 : return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);
198 :
199 : case LOCAL_GL_MAX_VARYING_VECTORS:
200 0 : return JS::Int32Value(MINVALUE_GL_MAX_VARYING_VECTORS);
201 :
202 : case LOCAL_GL_MAX_TEXTURE_SIZE:
203 0 : return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_SIZE);
204 :
205 : case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
206 0 : return JS::Int32Value(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);
207 :
208 : case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
209 0 : return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);
210 :
211 : case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
212 0 : return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
213 :
214 : case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
215 0 : return JS::Int32Value(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);
216 :
217 : default:
218 : // Return the real value; we're not overriding this one
219 0 : break;
220 : }
221 : }
222 :
223 0 : if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
224 0 : if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
225 0 : return JS::Int32Value(mImplMaxColorAttachments);
226 :
227 0 : } else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
228 0 : return JS::Int32Value(mImplMaxDrawBuffers);
229 :
230 0 : } else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
231 0 : pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mImplMaxDrawBuffers))
232 : {
233 0 : GLint ret = LOCAL_GL_NONE;
234 0 : if (!mBoundDrawFramebuffer) {
235 0 : if (pname == LOCAL_GL_DRAW_BUFFER0) {
236 0 : ret = gl->Screen()->GetDrawBufferMode();
237 : }
238 : } else {
239 0 : gl->fGetIntegerv(pname, &ret);
240 : }
241 0 : return JS::Int32Value(ret);
242 : }
243 : }
244 :
245 0 : if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
246 0 : if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
247 : WebGLVertexArray* vao =
248 0 : (mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
249 0 : return WebGLObjectAsJSValue(cx, vao, rv);
250 : }
251 : }
252 :
253 0 : if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
254 0 : switch (pname) {
255 : case LOCAL_GL_TIMESTAMP_EXT:
256 : {
257 0 : uint64_t val = 0;
258 0 : if (Has64BitTimestamps()) {
259 0 : gl->fGetInteger64v(pname, (GLint64*)&val);
260 : } else {
261 0 : gl->fGetIntegerv(pname, (GLint*)&val);
262 : }
263 : // TODO: JS doesn't support 64-bit integers. Be lossy and
264 : // cast to double (53 bits)
265 0 : return JS::NumberValue(val);
266 : }
267 :
268 : case LOCAL_GL_GPU_DISJOINT_EXT:
269 : {
270 0 : realGLboolean val = false; // Not disjoint by default.
271 0 : if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
272 0 : gl->fGetBooleanv(pname, &val);
273 : }
274 0 : return JS::BooleanValue(val);
275 : }
276 :
277 : default:
278 0 : break;
279 : }
280 : }
281 :
282 : // Privileged string params exposed by WEBGL_debug_renderer_info.
283 : // The privilege check is done in WebGLContext::IsExtensionSupported.
284 : // So here we just have to check that the extension is enabled.
285 0 : if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
286 0 : switch (pname) {
287 : case UNMASKED_VENDOR_WEBGL:
288 : case UNMASKED_RENDERER_WEBGL:
289 : {
290 0 : const char* overridePref = nullptr;
291 0 : GLenum driverEnum = LOCAL_GL_NONE;
292 :
293 0 : switch (pname) {
294 : case UNMASKED_RENDERER_WEBGL:
295 0 : overridePref = "webgl.renderer-string-override";
296 0 : driverEnum = LOCAL_GL_RENDERER;
297 0 : break;
298 : case UNMASKED_VENDOR_WEBGL:
299 0 : overridePref = "webgl.vendor-string-override";
300 0 : driverEnum = LOCAL_GL_VENDOR;
301 0 : break;
302 : default:
303 0 : MOZ_CRASH("GFX: bad `pname`");
304 : }
305 :
306 0 : bool hasRetVal = false;
307 :
308 0 : nsAutoString ret;
309 0 : if (overridePref) {
310 0 : nsresult res = Preferences::GetString(overridePref, &ret);
311 0 : if (NS_SUCCEEDED(res) && ret.Length() > 0)
312 0 : hasRetVal = true;
313 : }
314 :
315 0 : if (!hasRetVal) {
316 0 : const char* chars = reinterpret_cast<const char*>(gl->fGetString(driverEnum));
317 0 : ret = NS_ConvertASCIItoUTF16(chars);
318 0 : hasRetVal = true;
319 : }
320 :
321 0 : return StringValue(cx, ret, rv);
322 : }
323 : }
324 : }
325 :
326 0 : if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
327 0 : if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
328 0 : GLint i = 0;
329 0 : gl->fGetIntegerv(pname, &i);
330 0 : return JS::Int32Value(i);
331 : }
332 : }
333 :
334 0 : if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
335 0 : if (pname == LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) {
336 0 : GLfloat f = 0.f;
337 0 : gl->fGetFloatv(pname, &f);
338 0 : return JS::NumberValue(f);
339 : }
340 : }
341 :
342 0 : switch (pname) {
343 : //
344 : // String params
345 : //
346 : case LOCAL_GL_VENDOR:
347 : case LOCAL_GL_RENDERER:
348 0 : return StringValue(cx, "Mozilla", rv);
349 : case LOCAL_GL_VERSION:
350 0 : return StringValue(cx, "WebGL 1.0", rv);
351 : case LOCAL_GL_SHADING_LANGUAGE_VERSION:
352 0 : return StringValue(cx, "WebGL GLSL ES 1.0", rv);
353 :
354 : ////////////////////////////////
355 : // Single-value params
356 :
357 : // unsigned int
358 : case LOCAL_GL_CULL_FACE_MODE:
359 : case LOCAL_GL_FRONT_FACE:
360 : case LOCAL_GL_ACTIVE_TEXTURE:
361 : case LOCAL_GL_STENCIL_FUNC:
362 : case LOCAL_GL_STENCIL_FAIL:
363 : case LOCAL_GL_STENCIL_PASS_DEPTH_FAIL:
364 : case LOCAL_GL_STENCIL_PASS_DEPTH_PASS:
365 : case LOCAL_GL_STENCIL_BACK_FUNC:
366 : case LOCAL_GL_STENCIL_BACK_FAIL:
367 : case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL:
368 : case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS:
369 : case LOCAL_GL_DEPTH_FUNC:
370 : case LOCAL_GL_BLEND_SRC_RGB:
371 : case LOCAL_GL_BLEND_SRC_ALPHA:
372 : case LOCAL_GL_BLEND_DST_RGB:
373 : case LOCAL_GL_BLEND_DST_ALPHA:
374 : case LOCAL_GL_BLEND_EQUATION_RGB:
375 : case LOCAL_GL_BLEND_EQUATION_ALPHA: {
376 0 : GLint i = 0;
377 0 : gl->fGetIntegerv(pname, &i);
378 0 : return JS::NumberValue(uint32_t(i));
379 : }
380 :
381 : case LOCAL_GL_GENERATE_MIPMAP_HINT:
382 0 : return JS::NumberValue(mGenerateMipmapHint);
383 :
384 : case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT:
385 : case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
386 : const webgl::FormatUsageInfo* usage;
387 : uint32_t width, height;
388 0 : if (!ValidateCurFBForRead(funcName, &usage, &width, &height))
389 0 : return JS::NullValue();
390 :
391 0 : const auto implPI = ValidImplementationColorReadPI(usage);
392 :
393 : GLenum ret;
394 0 : if (pname == LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT) {
395 0 : ret = implPI.format;
396 : } else {
397 0 : ret = implPI.type;
398 : }
399 0 : return JS::NumberValue(uint32_t(ret));
400 : }
401 :
402 : // int
403 : case LOCAL_GL_STENCIL_REF:
404 : case LOCAL_GL_STENCIL_BACK_REF: {
405 0 : GLint stencilBits = 0;
406 0 : if (!GetStencilBits(&stencilBits))
407 0 : return JS::NullValue();
408 :
409 : // Assuming stencils have 8 bits
410 0 : const GLint stencilMask = (1 << stencilBits) - 1;
411 :
412 0 : GLint refValue = 0;
413 0 : gl->fGetIntegerv(pname, &refValue);
414 :
415 0 : return JS::Int32Value(refValue & stencilMask);
416 : }
417 :
418 : case LOCAL_GL_STENCIL_CLEAR_VALUE:
419 : case LOCAL_GL_UNPACK_ALIGNMENT:
420 : case LOCAL_GL_PACK_ALIGNMENT:
421 : case LOCAL_GL_SUBPIXEL_BITS:
422 : case LOCAL_GL_SAMPLE_BUFFERS:
423 : case LOCAL_GL_SAMPLES:
424 : case LOCAL_GL_MAX_VERTEX_ATTRIBS:
425 : case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
426 : case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
427 : case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: {
428 0 : GLint i = 0;
429 0 : gl->fGetIntegerv(pname, &i);
430 0 : return JS::Int32Value(i);
431 : }
432 :
433 : case LOCAL_GL_RED_BITS:
434 : case LOCAL_GL_GREEN_BITS:
435 : case LOCAL_GL_BLUE_BITS:
436 : case LOCAL_GL_ALPHA_BITS:
437 : case LOCAL_GL_DEPTH_BITS:
438 : case LOCAL_GL_STENCIL_BITS: {
439 : // Deprecated and removed in GL Core profiles, so special handling required.
440 : GLint val;
441 0 : if (!GetChannelBits(funcName, pname, &val))
442 0 : return JS::NullValue();
443 :
444 0 : return JS::Int32Value(val);
445 : }
446 :
447 : case LOCAL_GL_MAX_TEXTURE_SIZE:
448 0 : return JS::Int32Value(mImplMaxTextureSize);
449 :
450 : case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
451 0 : return JS::Int32Value(mImplMaxCubeMapTextureSize);
452 :
453 : case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
454 0 : return JS::Int32Value(mImplMaxRenderbufferSize);
455 :
456 : case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
457 0 : return JS::Int32Value(mGLMaxVertexUniformVectors);
458 :
459 : case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
460 0 : return JS::Int32Value(mGLMaxFragmentUniformVectors);
461 :
462 : case LOCAL_GL_MAX_VARYING_VECTORS:
463 0 : return JS::Int32Value(mGLMaxVaryingVectors);
464 :
465 : case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS: {
466 0 : uint32_t length = mCompressedTextureFormats.Length();
467 0 : JSObject* obj = dom::Uint32Array::Create(cx, this, length,
468 0 : mCompressedTextureFormats.Elements());
469 0 : if (!obj) {
470 0 : rv = NS_ERROR_OUT_OF_MEMORY;
471 : }
472 0 : return JS::ObjectOrNullValue(obj);
473 : }
474 :
475 : // unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
476 : // javascript integer values. We just return them as doubles and javascript doesn't care.
477 : case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
478 0 : return JS::DoubleValue(mStencilValueMaskBack); // pass as FP value to allow large values such as 2^32-1.
479 :
480 : case LOCAL_GL_STENCIL_BACK_WRITEMASK:
481 0 : return JS::DoubleValue(mStencilWriteMaskBack);
482 :
483 : case LOCAL_GL_STENCIL_VALUE_MASK:
484 0 : return JS::DoubleValue(mStencilValueMaskFront);
485 :
486 : case LOCAL_GL_STENCIL_WRITEMASK:
487 0 : return JS::DoubleValue(mStencilWriteMaskFront);
488 :
489 : // float
490 : case LOCAL_GL_LINE_WIDTH:
491 0 : return JS::DoubleValue(mLineWidth);
492 :
493 : case LOCAL_GL_DEPTH_CLEAR_VALUE:
494 : case LOCAL_GL_POLYGON_OFFSET_FACTOR:
495 : case LOCAL_GL_POLYGON_OFFSET_UNITS:
496 : case LOCAL_GL_SAMPLE_COVERAGE_VALUE: {
497 0 : GLfloat f = 0.f;
498 0 : gl->fGetFloatv(pname, &f);
499 0 : return JS::DoubleValue(f);
500 : }
501 :
502 : // bool
503 : case LOCAL_GL_BLEND:
504 : case LOCAL_GL_DEPTH_TEST:
505 : case LOCAL_GL_STENCIL_TEST:
506 : case LOCAL_GL_CULL_FACE:
507 : case LOCAL_GL_DITHER:
508 : case LOCAL_GL_POLYGON_OFFSET_FILL:
509 : case LOCAL_GL_SCISSOR_TEST:
510 : case LOCAL_GL_SAMPLE_COVERAGE_INVERT:
511 : case LOCAL_GL_DEPTH_WRITEMASK: {
512 0 : realGLboolean b = 0;
513 0 : gl->fGetBooleanv(pname, &b);
514 0 : return JS::BooleanValue(bool(b));
515 : }
516 :
517 : // bool, WebGL-specific
518 : case UNPACK_FLIP_Y_WEBGL:
519 0 : return JS::BooleanValue(mPixelStore_FlipY);
520 : case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
521 0 : return JS::BooleanValue(mPixelStore_PremultiplyAlpha);
522 :
523 : // uint, WebGL-specific
524 : case UNPACK_COLORSPACE_CONVERSION_WEBGL:
525 0 : return JS::NumberValue(uint32_t(mPixelStore_ColorspaceConversion));
526 :
527 : ////////////////////////////////
528 : // Complex values
529 :
530 : // 2 floats
531 : case LOCAL_GL_DEPTH_RANGE:
532 : case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
533 : case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE: {
534 0 : GLenum driverPName = pname;
535 0 : if (gl->IsCoreProfile() &&
536 : driverPName == LOCAL_GL_ALIASED_POINT_SIZE_RANGE)
537 : {
538 0 : driverPName = LOCAL_GL_POINT_SIZE_RANGE;
539 : }
540 :
541 0 : GLfloat fv[2] = { 0 };
542 0 : gl->fGetFloatv(driverPName, fv);
543 0 : JSObject* obj = dom::Float32Array::Create(cx, this, 2, fv);
544 0 : if (!obj) {
545 0 : rv = NS_ERROR_OUT_OF_MEMORY;
546 : }
547 0 : return JS::ObjectOrNullValue(obj);
548 : }
549 :
550 : // 4 floats
551 : case LOCAL_GL_COLOR_CLEAR_VALUE:
552 : case LOCAL_GL_BLEND_COLOR: {
553 0 : GLfloat fv[4] = { 0 };
554 0 : gl->fGetFloatv(pname, fv);
555 0 : JSObject* obj = dom::Float32Array::Create(cx, this, 4, fv);
556 0 : if (!obj) {
557 0 : rv = NS_ERROR_OUT_OF_MEMORY;
558 : }
559 0 : return JS::ObjectOrNullValue(obj);
560 : }
561 :
562 : // 2 ints
563 : case LOCAL_GL_MAX_VIEWPORT_DIMS: {
564 0 : GLint iv[2] = { 0 };
565 0 : gl->fGetIntegerv(pname, iv);
566 0 : JSObject* obj = dom::Int32Array::Create(cx, this, 2, iv);
567 0 : if (!obj) {
568 0 : rv = NS_ERROR_OUT_OF_MEMORY;
569 : }
570 0 : return JS::ObjectOrNullValue(obj);
571 : }
572 :
573 : // 4 ints
574 : case LOCAL_GL_SCISSOR_BOX:
575 : case LOCAL_GL_VIEWPORT: {
576 0 : GLint iv[4] = { 0 };
577 0 : gl->fGetIntegerv(pname, iv);
578 0 : JSObject* obj = dom::Int32Array::Create(cx, this, 4, iv);
579 0 : if (!obj) {
580 0 : rv = NS_ERROR_OUT_OF_MEMORY;
581 : }
582 0 : return JS::ObjectOrNullValue(obj);
583 : }
584 :
585 : // 4 bools
586 : case LOCAL_GL_COLOR_WRITEMASK: {
587 0 : realGLboolean gl_bv[4] = { 0 };
588 0 : gl->fGetBooleanv(pname, gl_bv);
589 0 : bool vals[4] = { bool(gl_bv[0]), bool(gl_bv[1]),
590 0 : bool(gl_bv[2]), bool(gl_bv[3]) };
591 0 : JS::Rooted<JS::Value> arr(cx);
592 0 : if (!dom::ToJSValue(cx, vals, &arr)) {
593 0 : rv = NS_ERROR_OUT_OF_MEMORY;
594 : }
595 0 : return arr;
596 : }
597 :
598 : case LOCAL_GL_ARRAY_BUFFER_BINDING: {
599 0 : return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv);
600 : }
601 :
602 : case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING: {
603 0 : return WebGLObjectAsJSValue(cx, mBoundVertexArray->mElementArrayBuffer.get(), rv);
604 : }
605 :
606 : case LOCAL_GL_RENDERBUFFER_BINDING: {
607 0 : return WebGLObjectAsJSValue(cx, mBoundRenderbuffer.get(), rv);
608 : }
609 :
610 : // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
611 : case LOCAL_GL_FRAMEBUFFER_BINDING: {
612 0 : return WebGLObjectAsJSValue(cx, mBoundDrawFramebuffer.get(), rv);
613 : }
614 :
615 : case LOCAL_GL_CURRENT_PROGRAM: {
616 0 : return WebGLObjectAsJSValue(cx, mCurrentProgram.get(), rv);
617 : }
618 :
619 : case LOCAL_GL_TEXTURE_BINDING_2D: {
620 0 : return WebGLObjectAsJSValue(cx, mBound2DTextures[mActiveTexture].get(), rv);
621 : }
622 :
623 : case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP: {
624 0 : return WebGLObjectAsJSValue(cx, mBoundCubeMapTextures[mActiveTexture].get(), rv);
625 : }
626 :
627 : default:
628 0 : break;
629 : }
630 :
631 0 : ErrorInvalidEnumInfo("getParameter: parameter", pname);
632 0 : return JS::NullValue();
633 : }
634 :
635 : void
636 0 : WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
637 : JS::MutableHandle<JS::Value> retval)
638 : {
639 0 : if (IsContextLost()) {
640 0 : retval.setNull();
641 0 : return;
642 : }
643 :
644 0 : MakeContextCurrent();
645 :
646 0 : switch (pname) {
647 : case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
648 : {
649 0 : if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
650 0 : ErrorInvalidValue("getParameterIndexed: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
651 0 : retval.setNull();
652 0 : return;
653 : }
654 0 : retval.setNull(); // See bug 903594
655 0 : return;
656 : }
657 :
658 : default:
659 0 : break;
660 : }
661 :
662 0 : ErrorInvalidEnumInfo("getParameterIndexed: parameter", pname);
663 0 : retval.setNull();
664 : }
665 :
666 : bool
667 0 : WebGLContext::IsEnabled(GLenum cap)
668 : {
669 0 : if (IsContextLost())
670 0 : return false;
671 :
672 0 : if (!ValidateCapabilityEnum(cap, "isEnabled"))
673 0 : return false;
674 :
675 0 : MakeContextCurrent();
676 0 : return gl->fIsEnabled(cap);
677 : }
678 :
679 : bool
680 0 : WebGLContext::ValidateCapabilityEnum(GLenum cap, const char* info)
681 : {
682 0 : switch (cap) {
683 : case LOCAL_GL_BLEND:
684 : case LOCAL_GL_CULL_FACE:
685 : case LOCAL_GL_DEPTH_TEST:
686 : case LOCAL_GL_DITHER:
687 : case LOCAL_GL_POLYGON_OFFSET_FILL:
688 : case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
689 : case LOCAL_GL_SAMPLE_COVERAGE:
690 : case LOCAL_GL_SCISSOR_TEST:
691 : case LOCAL_GL_STENCIL_TEST:
692 0 : return true;
693 : case LOCAL_GL_RASTERIZER_DISCARD:
694 0 : return IsWebGL2();
695 : default:
696 0 : ErrorInvalidEnumInfo(info, cap);
697 0 : return false;
698 : }
699 : }
700 :
701 : realGLboolean*
702 0 : WebGLContext::GetStateTrackingSlot(GLenum cap)
703 : {
704 0 : switch (cap) {
705 : case LOCAL_GL_DEPTH_TEST:
706 0 : return &mDepthTestEnabled;
707 : case LOCAL_GL_DITHER:
708 0 : return &mDitherEnabled;
709 : case LOCAL_GL_RASTERIZER_DISCARD:
710 0 : return &mRasterizerDiscardEnabled;
711 : case LOCAL_GL_SCISSOR_TEST:
712 0 : return &mScissorTestEnabled;
713 : case LOCAL_GL_STENCIL_TEST:
714 0 : return &mStencilTestEnabled;
715 : }
716 :
717 0 : return nullptr;
718 : }
719 :
720 : } // namespace mozilla
|