content/canvas/src/WebGLContextState.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     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/. */
     6 #include "WebGLContext.h"
     7 #include "WebGLContextUtils.h"
     8 #include "WebGLBuffer.h"
     9 #include "WebGLShader.h"
    10 #include "WebGLProgram.h"
    11 #include "WebGLFramebuffer.h"
    12 #include "WebGLRenderbuffer.h"
    13 #include "WebGLTexture.h"
    14 #include "WebGLVertexArray.h"
    15 #include "GLContext.h"
    16 #include "mozilla/dom/ToJSValue.h"
    18 using namespace mozilla;
    19 using namespace dom;
    21 void
    22 WebGLContext::Disable(GLenum cap)
    23 {
    24     if (IsContextLost())
    25         return;
    27     if (!ValidateCapabilityEnum(cap, "disable"))
    28         return;
    30     realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
    32     if (trackingSlot)
    33     {
    34         *trackingSlot = 0;
    35     }
    37     MakeContextCurrent();
    38     gl->fDisable(cap);
    39 }
    41 void
    42 WebGLContext::Enable(GLenum cap)
    43 {
    44     if (IsContextLost())
    45         return;
    47     if (!ValidateCapabilityEnum(cap, "enable"))
    48         return;
    50     realGLboolean* trackingSlot = GetStateTrackingSlot(cap);
    52     if (trackingSlot)
    53     {
    54         *trackingSlot = 1;
    55     }
    57     MakeContextCurrent();
    58     gl->fEnable(cap);
    59 }
    61 static JS::Value
    62 StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
    63 {
    64     JSString* str = JS_NewStringCopyZ(cx, chars);
    65     if (!str) {
    66         rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    67         return JS::NullValue();
    68     }
    70     return JS::StringValue(str);
    71 }
    73 JS::Value
    74 WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
    75 {
    76     if (IsContextLost())
    77         return JS::NullValue();
    79     MakeContextCurrent();
    81     if (MinCapabilityMode()) {
    82         switch(pname) {
    83             ////////////////////////////
    84             // Single-value params
    86             // int
    87             case LOCAL_GL_MAX_VERTEX_ATTRIBS:
    88                 return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_ATTRIBS);
    90             case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
    91                 return JS::Int32Value(MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
    93             case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
    94                 return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS);
    96             case LOCAL_GL_MAX_VARYING_VECTORS:
    97                 return JS::Int32Value(MINVALUE_GL_MAX_VARYING_VECTORS);
    99             case LOCAL_GL_MAX_TEXTURE_SIZE:
   100                 return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_SIZE);
   102             case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
   103                 return JS::Int32Value(MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE);
   105             case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
   106                 return JS::Int32Value(MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS);
   108             case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
   109                 return JS::Int32Value(MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
   111             case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
   112                 return JS::Int32Value(MINVALUE_GL_MAX_RENDERBUFFER_SIZE);
   114             default:
   115                 // Return the real value; we're not overriding this one
   116                 break;
   117         }
   118     }
   120     if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
   121         if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
   122             return JS::Int32Value(mGLMaxColorAttachments);
   124         } else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
   125             return JS::Int32Value(mGLMaxDrawBuffers);
   127         } else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
   128                    pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
   129         {
   130             if (mBoundFramebuffer) {
   131                 GLint iv = 0;
   132                 gl->fGetIntegerv(pname, &iv);
   133                 return JS::Int32Value(iv);
   134             }
   136             GLint iv = 0;
   137             gl->fGetIntegerv(pname, &iv);
   139             if (iv == GLint(LOCAL_GL_COLOR_ATTACHMENT0 + pname - LOCAL_GL_DRAW_BUFFER0)) {
   140                 return JS::Int32Value(LOCAL_GL_BACK);
   141             }
   143             return JS::Int32Value(LOCAL_GL_NONE);
   144         }
   145     }
   147     if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
   148         if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
   149             if (mBoundVertexArray == mDefaultVertexArray){
   150                 return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
   151             }
   153             return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
   154         }
   155     }
   157     switch (pname) {
   158         //
   159         // String params
   160         //
   161         case LOCAL_GL_VENDOR:
   162             return StringValue(cx, "Mozilla", rv);
   163         case LOCAL_GL_RENDERER:
   164             return StringValue(cx, "Mozilla", rv);
   165         case LOCAL_GL_VERSION: {
   166             const char* version = 0;
   168             if (IsWebGL2()) {
   169                 version = "WebGL 2.0";
   170             } else {
   171                 version = "WebGL 1.0";
   172             }
   174             MOZ_ASSERT(version != 0);
   175             return StringValue(cx, version, rv);
   176         }
   177         case LOCAL_GL_SHADING_LANGUAGE_VERSION:
   178             return StringValue(cx, "WebGL GLSL ES 1.0", rv);
   180             // Privileged string params exposed by WEBGL_debug_renderer_info:
   181         case UNMASKED_VENDOR_WEBGL:
   182         case UNMASKED_RENDERER_WEBGL: {
   183             // The privilege check is done in WebGLContext::IsExtensionSupported.
   184             // So here we just have to check that the extension is enabled.
   185             if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
   186                 break;
   187             }
   188             GLenum glstringname = LOCAL_GL_NONE;
   189             if (pname == UNMASKED_VENDOR_WEBGL) {
   190                 glstringname = LOCAL_GL_VENDOR;
   191             } else if (pname == UNMASKED_RENDERER_WEBGL) {
   192                 glstringname = LOCAL_GL_RENDERER;
   193             }
   194             const char* string = reinterpret_cast<const char*>(gl->fGetString(glstringname));
   195             return StringValue(cx, string, rv);
   196         }
   198         ////////////////////////////////
   199         // Single-value params
   201         // unsigned int
   202         case LOCAL_GL_CULL_FACE_MODE:
   203         case LOCAL_GL_FRONT_FACE:
   204         case LOCAL_GL_ACTIVE_TEXTURE:
   205         case LOCAL_GL_STENCIL_FUNC:
   206         case LOCAL_GL_STENCIL_FAIL:
   207         case LOCAL_GL_STENCIL_PASS_DEPTH_FAIL:
   208         case LOCAL_GL_STENCIL_PASS_DEPTH_PASS:
   209         case LOCAL_GL_STENCIL_BACK_FUNC:
   210         case LOCAL_GL_STENCIL_BACK_FAIL:
   211         case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL:
   212         case LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS:
   213         case LOCAL_GL_DEPTH_FUNC:
   214         case LOCAL_GL_BLEND_SRC_RGB:
   215         case LOCAL_GL_BLEND_SRC_ALPHA:
   216         case LOCAL_GL_BLEND_DST_RGB:
   217         case LOCAL_GL_BLEND_DST_ALPHA:
   218         case LOCAL_GL_BLEND_EQUATION_RGB:
   219         case LOCAL_GL_BLEND_EQUATION_ALPHA:
   220         case LOCAL_GL_GENERATE_MIPMAP_HINT: {
   221             GLint i = 0;
   222             gl->fGetIntegerv(pname, &i);
   223             return JS::NumberValue(uint32_t(i));
   224         }
   225         // int
   226         case LOCAL_GL_STENCIL_CLEAR_VALUE:
   227         case LOCAL_GL_STENCIL_REF:
   228         case LOCAL_GL_STENCIL_BACK_REF:
   229         case LOCAL_GL_UNPACK_ALIGNMENT:
   230         case LOCAL_GL_PACK_ALIGNMENT:
   231         case LOCAL_GL_SUBPIXEL_BITS:
   232         case LOCAL_GL_SAMPLE_BUFFERS:
   233         case LOCAL_GL_SAMPLES:
   234         case LOCAL_GL_MAX_VERTEX_ATTRIBS:
   235         case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
   236         case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
   237         case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
   238         case LOCAL_GL_RED_BITS:
   239         case LOCAL_GL_GREEN_BITS:
   240         case LOCAL_GL_BLUE_BITS:
   241         case LOCAL_GL_ALPHA_BITS:
   242         case LOCAL_GL_DEPTH_BITS:
   243         case LOCAL_GL_STENCIL_BITS: {
   244             GLint i = 0;
   245             gl->fGetIntegerv(pname, &i);
   246             return JS::Int32Value(i);
   247         }
   248         case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
   249             if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
   250                 GLint i = 0;
   251                 gl->fGetIntegerv(pname, &i);
   252                 return JS::Int32Value(i);
   253             } else {
   254                 break;
   255             }
   256         }
   257         case LOCAL_GL_MAX_TEXTURE_SIZE:
   258             return JS::Int32Value(mGLMaxTextureSize);
   260         case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
   261             return JS::Int32Value(mGLMaxCubeMapTextureSize);
   263         case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
   264             return JS::Int32Value(mGLMaxRenderbufferSize);
   266         case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
   267             return JS::Int32Value(mGLMaxVertexUniformVectors);
   269         case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
   270             return JS::Int32Value(mGLMaxFragmentUniformVectors);
   272         case LOCAL_GL_MAX_VARYING_VECTORS:
   273             return JS::Int32Value(mGLMaxVaryingVectors);
   275         case LOCAL_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
   276             return JS::Int32Value(0);
   277         case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS: {
   278             uint32_t length = mCompressedTextureFormats.Length();
   279             JSObject* obj = Uint32Array::Create(cx, this, length, mCompressedTextureFormats.Elements());
   280             if (!obj) {
   281                 rv = NS_ERROR_OUT_OF_MEMORY;
   282             }
   283             return JS::ObjectOrNullValue(obj);
   284         }
   285         case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: {
   286             if (!IsWebGL2()) {
   287                 break;
   288             }
   289             return JS::Int32Value(mGLMaxTransformFeedbackSeparateAttribs);
   290         }
   292         // unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
   293         // javascript integer values. We just return them as doubles and javascript doesn't care.
   294         case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
   295         case LOCAL_GL_STENCIL_BACK_WRITEMASK:
   296         case LOCAL_GL_STENCIL_VALUE_MASK:
   297         case LOCAL_GL_STENCIL_WRITEMASK: {
   298             GLint i = 0; // the GL api (glGetIntegerv) only does signed ints
   299             gl->fGetIntegerv(pname, &i);
   300             GLuint i_unsigned(i); // this is where -1 becomes 2^32-1
   301             double i_double(i_unsigned); // pass as FP value to allow large values such as 2^32-1.
   302             return JS::DoubleValue(i_double);
   303         }
   305         // float
   306         case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: {
   307             if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
   308                 GLfloat f = 0.f;
   309                 gl->fGetFloatv(pname, &f);
   310                 return JS::DoubleValue(f);
   311             } else {
   312                 break;
   313             }
   314         }
   315         case LOCAL_GL_DEPTH_CLEAR_VALUE:
   316         case LOCAL_GL_LINE_WIDTH:
   317         case LOCAL_GL_POLYGON_OFFSET_FACTOR:
   318         case LOCAL_GL_POLYGON_OFFSET_UNITS:
   319         case LOCAL_GL_SAMPLE_COVERAGE_VALUE: {
   320             GLfloat f = 0.f;
   321             gl->fGetFloatv(pname, &f);
   322             return JS::DoubleValue(f);
   323         }
   325         // bool
   326         case LOCAL_GL_BLEND:
   327         case LOCAL_GL_DEPTH_TEST:
   328         case LOCAL_GL_STENCIL_TEST:
   329         case LOCAL_GL_CULL_FACE:
   330         case LOCAL_GL_DITHER:
   331         case LOCAL_GL_POLYGON_OFFSET_FILL:
   332         case LOCAL_GL_SCISSOR_TEST:
   333         case LOCAL_GL_SAMPLE_COVERAGE_INVERT:
   334         case LOCAL_GL_DEPTH_WRITEMASK: {
   335             realGLboolean b = 0;
   336             gl->fGetBooleanv(pname, &b);
   337             return JS::BooleanValue(bool(b));
   338         }
   340         // bool, WebGL-specific
   341         case UNPACK_FLIP_Y_WEBGL:
   342             return JS::BooleanValue(mPixelStoreFlipY);
   343         case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
   344             return JS::BooleanValue(mPixelStorePremultiplyAlpha);
   346         // uint, WebGL-specific
   347         case UNPACK_COLORSPACE_CONVERSION_WEBGL:
   348             return JS::NumberValue(uint32_t(mPixelStoreColorspaceConversion));
   350         ////////////////////////////////
   351         // Complex values
   353         // 2 floats
   354         case LOCAL_GL_DEPTH_RANGE:
   355         case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
   356         case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE: {
   357             GLfloat fv[2] = { 0 };
   358             gl->fGetFloatv(pname, fv);
   359             JSObject* obj = Float32Array::Create(cx, this, 2, fv);
   360             if (!obj) {
   361                 rv = NS_ERROR_OUT_OF_MEMORY;
   362             }
   363             return JS::ObjectOrNullValue(obj);
   364         }
   366         // 4 floats
   367         case LOCAL_GL_COLOR_CLEAR_VALUE:
   368         case LOCAL_GL_BLEND_COLOR: {
   369             GLfloat fv[4] = { 0 };
   370             gl->fGetFloatv(pname, fv);
   371             JSObject* obj = Float32Array::Create(cx, this, 4, fv);
   372             if (!obj) {
   373                 rv = NS_ERROR_OUT_OF_MEMORY;
   374             }
   375             return JS::ObjectOrNullValue(obj);
   376         }
   378         // 2 ints
   379         case LOCAL_GL_MAX_VIEWPORT_DIMS: {
   380             GLint iv[2] = { 0 };
   381             gl->fGetIntegerv(pname, iv);
   382             JSObject* obj = Int32Array::Create(cx, this, 2, iv);
   383             if (!obj) {
   384                 rv = NS_ERROR_OUT_OF_MEMORY;
   385             }
   386             return JS::ObjectOrNullValue(obj);
   387         }
   389         // 4 ints
   390         case LOCAL_GL_SCISSOR_BOX:
   391         case LOCAL_GL_VIEWPORT: {
   392             GLint iv[4] = { 0 };
   393             gl->fGetIntegerv(pname, iv);
   394             JSObject* obj = Int32Array::Create(cx, this, 4, iv);
   395             if (!obj) {
   396                 rv = NS_ERROR_OUT_OF_MEMORY;
   397             }
   398             return JS::ObjectOrNullValue(obj);
   399         }
   401         // 4 bools
   402         case LOCAL_GL_COLOR_WRITEMASK: {
   403             realGLboolean gl_bv[4] = { 0 };
   404             gl->fGetBooleanv(pname, gl_bv);
   405             bool vals[4] = { bool(gl_bv[0]), bool(gl_bv[1]),
   406                              bool(gl_bv[2]), bool(gl_bv[3]) };
   407             JS::Rooted<JS::Value> arr(cx);
   408             if (!ToJSValue(cx, vals, &arr)) {
   409                 rv = NS_ERROR_OUT_OF_MEMORY;
   410             }
   411             return arr;
   412         }
   414         case LOCAL_GL_ARRAY_BUFFER_BINDING: {
   415             return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv);
   416         }
   418         case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: {
   419             if (!IsWebGL2()) {
   420                 break;
   421             }
   422             return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
   423         }
   425         case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING: {
   426             return WebGLObjectAsJSValue(cx, mBoundVertexArray->mBoundElementArrayBuffer.get(), rv);
   427         }
   429         case LOCAL_GL_RENDERBUFFER_BINDING: {
   430             return WebGLObjectAsJSValue(cx, mBoundRenderbuffer.get(), rv);
   431         }
   433         case LOCAL_GL_FRAMEBUFFER_BINDING: {
   434             return WebGLObjectAsJSValue(cx, mBoundFramebuffer.get(), rv);
   435         }
   437         case LOCAL_GL_CURRENT_PROGRAM: {
   438             return WebGLObjectAsJSValue(cx, mCurrentProgram.get(), rv);
   439         }
   441         case LOCAL_GL_TEXTURE_BINDING_2D: {
   442             return WebGLObjectAsJSValue(cx, mBound2DTextures[mActiveTexture].get(), rv);
   443         }
   445         case LOCAL_GL_TEXTURE_BINDING_CUBE_MAP: {
   446             return WebGLObjectAsJSValue(cx, mBoundCubeMapTextures[mActiveTexture].get(), rv);
   447         }
   449         default:
   450             break;
   451     }
   453     ErrorInvalidEnumInfo("getParameter: parameter", pname);
   454     return JS::NullValue();
   455 }
   457 void
   458 WebGLContext::GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
   459                                   JS::MutableHandle<JS::Value> retval)
   460 {
   461     if (IsContextLost()) {
   462         retval.setNull();
   463         return;
   464     }
   466     MakeContextCurrent();
   468     switch (pname) {
   469         case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
   470         {
   471             if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
   472                 ErrorInvalidValue("getParameterIndexed: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", index);
   473                 retval.setNull();
   474                 return;
   475             }
   476             retval.setNull(); // See bug 903594
   477             return;
   478         }
   480         default:
   481             break;
   482     }
   484     ErrorInvalidEnumInfo("getParameterIndexed: parameter", pname);
   485     retval.setNull();
   486 }
   488 bool
   489 WebGLContext::IsEnabled(GLenum cap)
   490 {
   491     if (IsContextLost())
   492         return false;
   494     if (!ValidateCapabilityEnum(cap, "isEnabled"))
   495         return false;
   497     MakeContextCurrent();
   498     return gl->fIsEnabled(cap);
   499 }
   501 bool
   502 WebGLContext::ValidateCapabilityEnum(GLenum cap, const char* info)
   503 {
   504     switch (cap) {
   505         case LOCAL_GL_BLEND:
   506         case LOCAL_GL_CULL_FACE:
   507         case LOCAL_GL_DEPTH_TEST:
   508         case LOCAL_GL_DITHER:
   509         case LOCAL_GL_POLYGON_OFFSET_FILL:
   510         case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
   511         case LOCAL_GL_SAMPLE_COVERAGE:
   512         case LOCAL_GL_SCISSOR_TEST:
   513         case LOCAL_GL_STENCIL_TEST:
   514             return true;
   515         case LOCAL_GL_RASTERIZER_DISCARD:
   516             return IsWebGL2();
   517         default:
   518             ErrorInvalidEnumInfo(info, cap);
   519             return false;
   520     }
   521 }
   523 realGLboolean*
   524 WebGLContext::GetStateTrackingSlot(GLenum cap)
   525 {
   526     switch (cap) {
   527         case LOCAL_GL_SCISSOR_TEST:
   528             return &mScissorTestEnabled;
   529         case LOCAL_GL_DITHER:
   530             return &mDitherEnabled;
   531         case LOCAL_GL_RASTERIZER_DISCARD:
   532             return &mRasterizerDiscardEnabled;
   533     }
   535     return nullptr;
   536 }

mercurial