mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 15:15:23 +00:00
643 lines
20 KiB
C++
643 lines
20 KiB
C++
/* -*- 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 "WebGLContext.h"
|
|
#include "WebGLContextUtils.h"
|
|
#include "WebGLBuffer.h"
|
|
#include "WebGLShader.h"
|
|
#include "WebGLProgram.h"
|
|
#include "WebGLFramebuffer.h"
|
|
#include "WebGLRenderbuffer.h"
|
|
#include "WebGLTexture.h"
|
|
#include "WebGLVertexArray.h"
|
|
#include "GLContext.h"
|
|
#include "mozilla/dom/ToJSValue.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace dom;
|
|
|
|
void
|
|
WebGLContext::Disable(GLenum cap)
|
|
{
|
|
if (IsContextLost())
|
|
return;
|
|
|
|
if (!ValidateCapabilityEnum(cap, "disable"))
|
|
return;
|
|
|
|
realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
|
|
|
|
if (trackingSlot)
|
|
{
|
|
*trackingSlot = 0;
|
|
}
|
|
|
|
MakeContextCurrent();
|
|
gl->fDisable(cap);
|
|
}
|
|
|
|
void
|
|
WebGLContext::Enable(GLenum cap)
|
|
{
|
|
if (IsContextLost())
|
|
return;
|
|
|
|
if (!ValidateCapabilityEnum(cap, "enable"))
|
|
return;
|
|
|
|
realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
|
|
|
|
if (trackingSlot)
|
|
{
|
|
*trackingSlot = 1;
|
|
}
|
|
|
|
MakeContextCurrent();
|
|
gl->fEnable(cap);
|
|
}
|
|
|
|
static JS::Value
|
|
StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
|
|
{
|
|
JSString* str = JS_NewStringCopyZ(cx, chars);
|
|
if (!str) {
|
|
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
|
return JS::NullValue();
|
|
}
|
|
|
|
return JS::StringValue(str);
|
|
}
|
|
|
|
bool
|
|
WebGLContext::GetStencilBits(GLint* out_stencilBits)
|
|
{
|
|
*out_stencilBits = 0;
|
|
if (mBoundDrawFramebuffer) {
|
|
if (mBoundDrawFramebuffer->HasDepthStencilConflict()) {
|
|
// Error, we don't know which stencil buffer's bits to use
|
|
ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
|
|
return false;
|
|
}
|
|
|
|
if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() ||
|
|
mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
|
|
{
|
|
*out_stencilBits = 8;
|
|
}
|
|
} else if (mOptions.stencil) {
|
|
*out_stencilBits = 8;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
JS::Value
|
|
WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
|
{
|
|
if (IsContextLost())
|
|
return JS::NullValue();
|
|
|
|
MakeContextCurrent();
|
|
|
|
if (MinCapabilityMode()) {
|
|
switch(pname) {
|
|
////////////////////////////
|
|
// Single-value params
|
|
|
|
// int
|
|
case LOCAL_GL_MAX_VERTEX_ATTRIBS:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_ATTRIBS);
|
|
|
|
case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
|
|
|
|
case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);
|
|
|
|
case LOCAL_GL_MAX_VARYING_VECTORS:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_VARYING_VECTORS);
|
|
|
|
case LOCAL_GL_MAX_TEXTURE_SIZE:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_SIZE);
|
|
|
|
case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);
|
|
|
|
case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);
|
|
|
|
case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
|
|
|
|
case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
|
|
return JS::Int32Value(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);
|
|
|
|
default:
|
|
// Return the real value; we're not overriding this one
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
|
|
if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
|
|
return JS::Int32Value(mGLMaxColorAttachments);
|
|
|
|
} else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
|
|
return JS::Int32Value(mGLMaxDrawBuffers);
|
|
|
|
} else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
|
|
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
|
|
{
|
|
if (mBoundDrawFramebuffer) {
|
|
GLint iv = 0;
|
|
gl->fGetIntegerv(pname, &iv);
|
|
return JS::Int32Value(iv);
|
|
}
|
|
|
|
GLint iv = 0;
|
|
gl->fGetIntegerv(pname, &iv);
|
|
|
|
if (iv == GLint(LOCAL_GL_COLOR_ATTACHMENT0 + pname - LOCAL_GL_DRAW_BUFFER0)) {
|
|
return JS::Int32Value(LOCAL_GL_BACK);
|
|
}
|
|
|
|
return JS::Int32Value(LOCAL_GL_NONE);
|
|
}
|
|
}
|
|
|
|
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
|
|
if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
|
|
if (mBoundVertexArray == mDefaultVertexArray){
|
|
return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
|
|
}
|
|
|
|
return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
|
|
}
|
|
}
|
|
|
|
if (IsWebGL2()) {
|
|
switch (pname) {
|
|
case LOCAL_GL_MAX_SAMPLES:
|
|
case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE:
|
|
case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: {
|
|
GLint val;
|
|
gl->fGetIntegerv(pname, &val);
|
|
return JS::NumberValue(uint32_t(val));
|
|
}
|
|
|
|
case LOCAL_GL_TEXTURE_BINDING_3D: {
|
|
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
|
|
}
|
|
|
|
// DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
|
|
case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
|
|
return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv);
|
|
}
|
|
}
|
|
|
|
switch (pname) {
|
|
//
|
|
// String params
|
|
//
|
|
case LOCAL_GL_VENDOR:
|
|
return StringValue(cx, "Mozilla", rv);
|
|
case LOCAL_GL_RENDERER:
|
|
return StringValue(cx, "Mozilla", rv);
|
|
case LOCAL_GL_VERSION: {
|
|
const char* version = 0;
|
|
|
|
if (IsWebGL2()) {
|
|
version = "WebGL 2.0";
|
|
} else {
|
|
version = "WebGL 1.0";
|
|
}
|
|
|
|
MOZ_ASSERT(version != 0);
|
|
return StringValue(cx, version, rv);
|
|
}
|
|
case LOCAL_GL_SHADING_LANGUAGE_VERSION:
|
|
return StringValue(cx, "WebGL GLSL ES 1.0", rv);
|
|
|
|
// Privileged string params exposed by WEBGL_debug_renderer_info:
|
|
case UNMASKED_VENDOR_WEBGL:
|
|
case UNMASKED_RENDERER_WEBGL: {
|
|
// The privilege check is done in WebGLContext::IsExtensionSupported.
|
|
// So here we just have to check that the extension is enabled.
|
|
if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
|
|
break;
|
|
}
|
|
GLenum glstringname = LOCAL_GL_NONE;
|
|
if (pname == UNMASKED_VENDOR_WEBGL) {
|
|
glstringname = LOCAL_GL_VENDOR;
|
|
} else if (pname == UNMASKED_RENDERER_WEBGL) {
|
|
glstringname = LOCAL_GL_RENDERER;
|
|
}
|
|
const char* string = reinterpret_cast<const char*>(gl->fGetString(glstringname));
|
|
return StringValue(cx, string, rv);
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Single-value params
|
|
|
|
// unsigned int
|
|
case LOCAL_GL_CULL_FACE_MODE:
|
|
case LOCAL_GL_FRONT_FACE:
|
|
case LOCAL_GL_ACTIVE_TEXTURE:
|
|
case LOCAL_GL_STENCIL_FUNC:
|
|
case LOCAL_GL_STENCIL_FAIL:
|
|
case LOCAL_GL_STENCIL_PASS_DEPTH_FAIL:
|
|
case LOCAL_GL_STENCIL_PASS_DEPTH_PASS:
|
|
case LOCAL_GL_STENCIL_BACK_FUNC:
|
|
case LOCAL_GL_STENCIL_BACK_FAIL:
|
|
case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL:
|
|
case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS:
|
|
case LOCAL_GL_DEPTH_FUNC:
|
|
case LOCAL_GL_BLEND_SRC_RGB:
|
|
case LOCAL_GL_BLEND_SRC_ALPHA:
|
|
case LOCAL_GL_BLEND_DST_RGB:
|
|
case LOCAL_GL_BLEND_DST_ALPHA:
|
|
case LOCAL_GL_BLEND_EQUATION_RGB:
|
|
case LOCAL_GL_BLEND_EQUATION_ALPHA:
|
|
case LOCAL_GL_GENERATE_MIPMAP_HINT: {
|
|
GLint i = 0;
|
|
gl->fGetIntegerv(pname, &i);
|
|
return JS::NumberValue(uint32_t(i));
|
|
}
|
|
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
|
|
if (mBoundReadFramebuffer) {
|
|
FBStatus status = mBoundReadFramebuffer->CheckFramebufferStatus();
|
|
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
|
ErrorInvalidOperation("getParameter: Read framebuffer must be"
|
|
" complete before querying"
|
|
" IMPLEMENTATION_COLOR_READ_TYPE.");
|
|
return JS::NullValue();
|
|
}
|
|
}
|
|
|
|
GLint i = 0;
|
|
if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
|
|
gl->fGetIntegerv(pname, &i);
|
|
} else {
|
|
i = LOCAL_GL_UNSIGNED_BYTE;
|
|
}
|
|
return JS::NumberValue(uint32_t(i));
|
|
}
|
|
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
|
|
if (mBoundReadFramebuffer) {
|
|
FBStatus status = mBoundReadFramebuffer->CheckFramebufferStatus();
|
|
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
|
ErrorInvalidOperation("getParameter: Read framebuffer must be"
|
|
" complete before querying"
|
|
" IMPLEMENTATION_COLOR_READ_FORMAT.");
|
|
return JS::NullValue();
|
|
}
|
|
}
|
|
|
|
GLint i = 0;
|
|
if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) {
|
|
gl->fGetIntegerv(pname, &i);
|
|
} else {
|
|
i = LOCAL_GL_RGBA;
|
|
}
|
|
return JS::NumberValue(uint32_t(i));
|
|
}
|
|
// int
|
|
case LOCAL_GL_STENCIL_REF:
|
|
case LOCAL_GL_STENCIL_BACK_REF: {
|
|
GLint stencilBits = 0;
|
|
if (!GetStencilBits(&stencilBits))
|
|
return JS::NullValue();
|
|
|
|
// Assuming stencils have 8 bits
|
|
const GLint stencilMask = (1 << stencilBits) - 1;
|
|
|
|
GLint refValue = 0;
|
|
gl->fGetIntegerv(pname, &refValue);
|
|
|
|
return JS::Int32Value(refValue & stencilMask);
|
|
}
|
|
case LOCAL_GL_STENCIL_BITS: {
|
|
GLint stencilBits = 0;
|
|
GetStencilBits(&stencilBits);
|
|
return JS::Int32Value(stencilBits);
|
|
}
|
|
case LOCAL_GL_STENCIL_CLEAR_VALUE:
|
|
case LOCAL_GL_UNPACK_ALIGNMENT:
|
|
case LOCAL_GL_PACK_ALIGNMENT:
|
|
case LOCAL_GL_SUBPIXEL_BITS:
|
|
case LOCAL_GL_SAMPLE_BUFFERS:
|
|
case LOCAL_GL_SAMPLES:
|
|
case LOCAL_GL_MAX_VERTEX_ATTRIBS:
|
|
case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
|
|
case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
|
|
case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
|
|
case LOCAL_GL_RED_BITS:
|
|
case LOCAL_GL_GREEN_BITS:
|
|
case LOCAL_GL_BLUE_BITS:
|
|
case LOCAL_GL_DEPTH_BITS: {
|
|
GLint i = 0;
|
|
gl->fGetIntegerv(pname, &i);
|
|
return JS::Int32Value(i);
|
|
}
|
|
case LOCAL_GL_ALPHA_BITS: {
|
|
GLint i = 0;
|
|
if (!mNeedsFakeNoAlpha) {
|
|
gl->fGetIntegerv(pname, &i);
|
|
}
|
|
return JS::Int32Value(i);
|
|
}
|
|
case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
|
|
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
|
|
GLint i = 0;
|
|
gl->fGetIntegerv(pname, &i);
|
|
return JS::Int32Value(i);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
case LOCAL_GL_MAX_TEXTURE_SIZE:
|
|
return JS::Int32Value(mGLMaxTextureSize);
|
|
|
|
case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
|
|
return JS::Int32Value(mGLMaxCubeMapTextureSize);
|
|
|
|
case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
|
|
return JS::Int32Value(mGLMaxRenderbufferSize);
|
|
|
|
case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
|
|
return JS::Int32Value(mGLMaxVertexUniformVectors);
|
|
|
|
case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
|
|
return JS::Int32Value(mGLMaxFragmentUniformVectors);
|
|
|
|
case LOCAL_GL_MAX_VARYING_VECTORS:
|
|
return JS::Int32Value(mGLMaxVaryingVectors);
|
|
|
|
case LOCAL_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
|
|
return JS::Int32Value(0);
|
|
case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS: {
|
|
uint32_t length = mCompressedTextureFormats.Length();
|
|
JSObject* obj = Uint32Array::Create(cx, this, length, mCompressedTextureFormats.Elements());
|
|
if (!obj) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return JS::ObjectOrNullValue(obj);
|
|
}
|
|
case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: {
|
|
if (!IsWebGL2()) {
|
|
break;
|
|
}
|
|
return JS::Int32Value(mGLMaxTransformFeedbackSeparateAttribs);
|
|
}
|
|
|
|
// unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
|
|
// javascript integer values. We just return them as doubles and javascript doesn't care.
|
|
case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
|
|
case LOCAL_GL_STENCIL_BACK_WRITEMASK:
|
|
case LOCAL_GL_STENCIL_VALUE_MASK:
|
|
case LOCAL_GL_STENCIL_WRITEMASK: {
|
|
GLint i = 0; // the GL api (glGetIntegerv) only does signed ints
|
|
gl->fGetIntegerv(pname, &i);
|
|
GLuint i_unsigned(i); // this is where -1 becomes 2^32-1
|
|
double i_double(i_unsigned); // pass as FP value to allow large values such as 2^32-1.
|
|
return JS::DoubleValue(i_double);
|
|
}
|
|
|
|
// float
|
|
case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: {
|
|
if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
|
|
GLfloat f = 0.f;
|
|
gl->fGetFloatv(pname, &f);
|
|
return JS::DoubleValue(f);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
case LOCAL_GL_DEPTH_CLEAR_VALUE:
|
|
case LOCAL_GL_LINE_WIDTH:
|
|
case LOCAL_GL_POLYGON_OFFSET_FACTOR:
|
|
case LOCAL_GL_POLYGON_OFFSET_UNITS:
|
|
case LOCAL_GL_SAMPLE_COVERAGE_VALUE: {
|
|
GLfloat f = 0.f;
|
|
gl->fGetFloatv(pname, &f);
|
|
return JS::DoubleValue(f);
|
|
}
|
|
|
|
// bool
|
|
case LOCAL_GL_BLEND:
|
|
case LOCAL_GL_DEPTH_TEST:
|
|
case LOCAL_GL_STENCIL_TEST:
|
|
case LOCAL_GL_CULL_FACE:
|
|
case LOCAL_GL_DITHER:
|
|
case LOCAL_GL_POLYGON_OFFSET_FILL:
|
|
case LOCAL_GL_SCISSOR_TEST:
|
|
case LOCAL_GL_SAMPLE_COVERAGE_INVERT:
|
|
case LOCAL_GL_DEPTH_WRITEMASK: {
|
|
realGLboolean b = 0;
|
|
gl->fGetBooleanv(pname, &b);
|
|
return JS::BooleanValue(bool(b));
|
|
}
|
|
|
|
// bool, WebGL-specific
|
|
case UNPACK_FLIP_Y_WEBGL:
|
|
return JS::BooleanValue(mPixelStoreFlipY);
|
|
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
|
|
return JS::BooleanValue(mPixelStorePremultiplyAlpha);
|
|
|
|
// uint, WebGL-specific
|
|
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
|
|
return JS::NumberValue(uint32_t(mPixelStoreColorspaceConversion));
|
|
|
|
////////////////////////////////
|
|
// Complex values
|
|
|
|
// 2 floats
|
|
case LOCAL_GL_DEPTH_RANGE:
|
|
case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
|
|
case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE: {
|
|
GLfloat fv[2] = { 0 };
|
|
gl->fGetFloatv(pname, fv);
|
|
JSObject* obj = Float32Array::Create(cx, this, 2, fv);
|
|
if (!obj) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return JS::ObjectOrNullValue(obj);
|
|
}
|
|
|
|
// 4 floats
|
|
case LOCAL_GL_COLOR_CLEAR_VALUE:
|
|
case LOCAL_GL_BLEND_COLOR: {
|
|
GLfloat fv[4] = { 0 };
|
|
gl->fGetFloatv(pname, fv);
|
|
JSObject* obj = Float32Array::Create(cx, this, 4, fv);
|
|
if (!obj) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return JS::ObjectOrNullValue(obj);
|
|
}
|
|
|
|
// 2 ints
|
|
case LOCAL_GL_MAX_VIEWPORT_DIMS: {
|
|
GLint iv[2] = { 0 };
|
|
gl->fGetIntegerv(pname, iv);
|
|
JSObject* obj = Int32Array::Create(cx, this, 2, iv);
|
|
if (!obj) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return JS::ObjectOrNullValue(obj);
|
|
}
|
|
|
|
// 4 ints
|
|
case LOCAL_GL_SCISSOR_BOX:
|
|
case LOCAL_GL_VIEWPORT: {
|
|
GLint iv[4] = { 0 };
|
|
gl->fGetIntegerv(pname, iv);
|
|
JSObject* obj = Int32Array::Create(cx, this, 4, iv);
|
|
if (!obj) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return JS::ObjectOrNullValue(obj);
|
|
}
|
|
|
|
// 4 bools
|
|
case LOCAL_GL_COLOR_WRITEMASK: {
|
|
realGLboolean gl_bv[4] = { 0 };
|
|
gl->fGetBooleanv(pname, gl_bv);
|
|
bool vals[4] = { bool(gl_bv[0]), bool(gl_bv[1]),
|
|
bool(gl_bv[2]), bool(gl_bv[3]) };
|
|
JS::Rooted<JS::Value> arr(cx);
|
|
if (!ToJSValue(cx, vals, &arr)) {
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
case LOCAL_GL_ARRAY_BUFFER_BINDING: {
|
|
return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv);
|
|
}
|
|
|
|
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: {
|
|
if (!IsWebGL2()) {
|
|
break;
|
|
}
|
|
return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
|
|
}
|
|
|
|
case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING: {
|
|
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mElementArrayBuffer.get(), rv);
|
|
}
|
|
|
|
case LOCAL_GL_RENDERBUFFER_BINDING: {
|
|
return WebGLObjectAsJSValue(cx, mBoundRenderbuffer.get(), rv);
|
|
}
|
|
|
|
// DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
|
|
case LOCAL_GL_FRAMEBUFFER_BINDING: {
|
|
return WebGLObjectAsJSValue(cx, mBoundDrawFramebuffer.get(), rv);
|
|
}
|
|
|
|
case LOCAL_GL_CURRENT_PROGRAM: {
|
|
return WebGLObjectAsJSValue(cx, mCurrentProgram.get(), rv);
|
|
}
|
|
|
|
case LOCAL_GL_TEXTURE_BINDING_2D: {
|
|
return WebGLObjectAsJSValue(cx, mBound2DTextures[mActiveTexture].get(), rv);
|
|
}
|
|
|
|
case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP: {
|
|
return WebGLObjectAsJSValue(cx, mBoundCubeMapTextures[mActiveTexture].get(), rv);
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
ErrorInvalidEnumInfo("getParameter: parameter", pname);
|
|
return JS::NullValue();
|
|
}
|
|
|
|
void
|
|
WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
|
|
JS::MutableHandle<JS::Value> retval)
|
|
{
|
|
if (IsContextLost()) {
|
|
retval.setNull();
|
|
return;
|
|
}
|
|
|
|
MakeContextCurrent();
|
|
|
|
switch (pname) {
|
|
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
|
|
{
|
|
if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
|
|
ErrorInvalidValue("getParameterIndexed: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", index);
|
|
retval.setNull();
|
|
return;
|
|
}
|
|
retval.setNull(); // See bug 903594
|
|
return;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
ErrorInvalidEnumInfo("getParameterIndexed: parameter", pname);
|
|
retval.setNull();
|
|
}
|
|
|
|
bool
|
|
WebGLContext::IsEnabled(GLenum cap)
|
|
{
|
|
if (IsContextLost())
|
|
return false;
|
|
|
|
if (!ValidateCapabilityEnum(cap, "isEnabled"))
|
|
return false;
|
|
|
|
MakeContextCurrent();
|
|
return gl->fIsEnabled(cap);
|
|
}
|
|
|
|
bool
|
|
WebGLContext::ValidateCapabilityEnum(GLenum cap, const char* info)
|
|
{
|
|
switch (cap) {
|
|
case LOCAL_GL_BLEND:
|
|
case LOCAL_GL_CULL_FACE:
|
|
case LOCAL_GL_DEPTH_TEST:
|
|
case LOCAL_GL_DITHER:
|
|
case LOCAL_GL_POLYGON_OFFSET_FILL:
|
|
case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
|
|
case LOCAL_GL_SAMPLE_COVERAGE:
|
|
case LOCAL_GL_SCISSOR_TEST:
|
|
case LOCAL_GL_STENCIL_TEST:
|
|
return true;
|
|
case LOCAL_GL_RASTERIZER_DISCARD:
|
|
return IsWebGL2();
|
|
default:
|
|
ErrorInvalidEnumInfo(info, cap);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
realGLboolean*
|
|
WebGLContext::GetStateTrackingSlot(GLenum cap)
|
|
{
|
|
switch (cap) {
|
|
case LOCAL_GL_DITHER:
|
|
return &mDitherEnabled;
|
|
case LOCAL_GL_RASTERIZER_DISCARD:
|
|
return &mRasterizerDiscardEnabled;
|
|
case LOCAL_GL_SCISSOR_TEST:
|
|
return &mScissorTestEnabled;
|
|
case LOCAL_GL_STENCIL_TEST:
|
|
return &mStencilTestEnabled;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|