content/canvas/src/WebGLContextUtils.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: 20; 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 <stdarg.h>
     8 #include "WebGLContext.h"
     9 #include "GLContext.h"
    11 #include "prprf.h"
    13 #include "jsapi.h"
    14 #include "nsIScriptSecurityManager.h"
    15 #include "nsServiceManagerUtils.h"
    16 #include "nsIVariant.h"
    17 #include "nsCxPusher.h"
    19 #include "nsIDOMEvent.h"
    20 #include "nsIDOMDataContainerEvent.h"
    22 #include "mozilla/Preferences.h"
    24 using namespace mozilla;
    26 namespace mozilla {
    28 using namespace gl;
    30 bool
    31 IsGLDepthFormat(GLenum webGLFormat)
    32 {
    33     return (webGLFormat == LOCAL_GL_DEPTH_COMPONENT ||
    34             webGLFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
    35             webGLFormat == LOCAL_GL_DEPTH_COMPONENT32);
    36 }
    38 bool
    39 IsGLDepthStencilFormat(GLenum webGLFormat)
    40 {
    41     return (webGLFormat == LOCAL_GL_DEPTH_STENCIL ||
    42             webGLFormat == LOCAL_GL_DEPTH24_STENCIL8);
    43 }
    45 bool
    46 FormatHasAlpha(GLenum webGLFormat)
    47 {
    48     return webGLFormat == LOCAL_GL_RGBA ||
    49            webGLFormat == LOCAL_GL_LUMINANCE_ALPHA ||
    50            webGLFormat == LOCAL_GL_ALPHA ||
    51            webGLFormat == LOCAL_GL_RGBA4 ||
    52            webGLFormat == LOCAL_GL_RGB5_A1 ||
    53            webGLFormat == LOCAL_GL_SRGB_ALPHA;
    54 }
    56 /**
    57  * Convert WebGL/ES format and type into GL format and GL internal
    58  * format valid for underlying driver.
    59  */
    60 void
    61 DriverFormatsFromFormatAndType(GLContext* gl, GLenum webGLFormat, GLenum webGLType,
    62                                GLenum* out_driverInternalFormat, GLenum* out_driverFormat)
    63 {
    64     MOZ_ASSERT(out_driverInternalFormat, "out_driverInternalFormat can't be nullptr.");
    65     MOZ_ASSERT(out_driverFormat, "out_driverFormat can't be nullptr.");
    66     if (!out_driverInternalFormat || !out_driverFormat)
    67         return;
    69     // ES2 requires that format == internalformat; floating-point is
    70     // indicated purely by the type that's loaded.  For desktop GL, we
    71     // have to specify a floating point internal format.
    72     if (gl->IsGLES()) {
    73         *out_driverInternalFormat = webGLFormat;
    74         *out_driverFormat = webGLFormat;
    76         return;
    77     }
    79     GLenum format = webGLFormat;
    80     GLenum internalFormat = LOCAL_GL_NONE;
    82     if (format == LOCAL_GL_DEPTH_COMPONENT) {
    83         if (webGLType == LOCAL_GL_UNSIGNED_SHORT)
    84             internalFormat = LOCAL_GL_DEPTH_COMPONENT16;
    85         else if (webGLType == LOCAL_GL_UNSIGNED_INT)
    86             internalFormat = LOCAL_GL_DEPTH_COMPONENT32;
    87     } else if (format == LOCAL_GL_DEPTH_STENCIL) {
    88         if (webGLType == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
    89             internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
    90     } else {
    91         switch (webGLType) {
    92         case LOCAL_GL_UNSIGNED_BYTE:
    93         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
    94         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
    95         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
    96             internalFormat = format;
    97             break;
    99         case LOCAL_GL_FLOAT:
   100             switch (format) {
   101             case LOCAL_GL_RGBA:
   102                 internalFormat = LOCAL_GL_RGBA32F;
   103                 break;
   105             case LOCAL_GL_RGB:
   106                 internalFormat = LOCAL_GL_RGB32F;
   107                 break;
   109             case LOCAL_GL_ALPHA:
   110                 internalFormat = LOCAL_GL_ALPHA32F_ARB;
   111                 break;
   113             case LOCAL_GL_LUMINANCE:
   114                 internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
   115                 break;
   117             case LOCAL_GL_LUMINANCE_ALPHA:
   118                 internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
   119                 break;
   120             }
   121             break;
   123         case LOCAL_GL_HALF_FLOAT_OES:
   124             switch (format) {
   125             case LOCAL_GL_RGBA:
   126                 internalFormat = LOCAL_GL_RGBA16F;
   127                 break;
   129             case LOCAL_GL_RGB:
   130                 internalFormat = LOCAL_GL_RGB16F;
   131                 break;
   133             case LOCAL_GL_ALPHA:
   134                 internalFormat = LOCAL_GL_ALPHA16F_ARB;
   135                 break;
   137             case LOCAL_GL_LUMINANCE:
   138                 internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
   139                 break;
   141             case LOCAL_GL_LUMINANCE_ALPHA:
   142                 internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
   143                 break;
   144             }
   145             break;
   147         default:
   148             break;
   149         }
   151         // Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
   152         // requires that format == internalformat, but GL will fail in this case.
   153         // GL requires:
   154         //      format  ->  internalformat
   155         //      GL_RGB      GL_SRGB_EXT
   156         //      GL_RGBA     GL_SRGB_ALPHA_EXT
   157         switch (format) {
   158         case LOCAL_GL_SRGB:
   159             internalFormat = format;
   160             format = LOCAL_GL_RGB;
   161             break;
   163         case LOCAL_GL_SRGB_ALPHA:
   164             internalFormat = format;
   165             format = LOCAL_GL_RGBA;
   166             break;
   167         }
   168     }
   170     MOZ_ASSERT(format != LOCAL_GL_NONE && internalFormat != LOCAL_GL_NONE,
   171                "Coding mistake -- bad format/type passed?");
   173     *out_driverInternalFormat = internalFormat;
   174     *out_driverFormat = format;
   175 }
   177 GLenum
   178 DriverTypeFromType(GLContext* gl, GLenum webGLType)
   179 {
   180     if (gl->IsGLES())
   181         return webGLType;
   183     // convert type for half float if not on GLES2
   184     GLenum type = webGLType;
   185     if (type == LOCAL_GL_HALF_FLOAT_OES) {
   186         if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
   187             return LOCAL_GL_HALF_FLOAT;
   188         } else {
   189             MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
   190         }
   191     }
   193     return webGLType;
   194 }
   196 } // namespace mozilla
   198 void
   199 WebGLContext::GenerateWarning(const char *fmt, ...)
   200 {
   201     va_list ap;
   202     va_start(ap, fmt);
   204     GenerateWarning(fmt, ap);
   206     va_end(ap);
   207 }
   209 void
   210 WebGLContext::GenerateWarning(const char *fmt, va_list ap)
   211 {
   212     if (!ShouldGenerateWarnings())
   213         return;
   215     mAlreadyGeneratedWarnings++;
   217     char buf[1024];
   218     PR_vsnprintf(buf, 1024, fmt, ap);
   220     // no need to print to stderr, as JS_ReportWarning takes care of this for us.
   222     AutoJSContext cx;
   223     JS_ReportWarning(cx, "WebGL: %s", buf);
   224     if (!ShouldGenerateWarnings()) {
   225         JS_ReportWarning(cx,
   226             "WebGL: No further warnings will be reported for this WebGL context "
   227             "(already reported %d warnings)", mAlreadyGeneratedWarnings);
   228     }
   229 }
   231 bool
   232 WebGLContext::ShouldGenerateWarnings() const
   233 {
   234     if (mMaxWarnings == -1) {
   235         return true;
   236     }
   238     return mAlreadyGeneratedWarnings < mMaxWarnings;
   239 }
   241 CheckedUint32
   242 WebGLContext::GetImageSize(GLsizei height,
   243                            GLsizei width,
   244                            uint32_t pixelSize,
   245                            uint32_t packOrUnpackAlignment)
   246 {
   247     CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
   249     // alignedRowSize = row size rounded up to next multiple of packAlignment
   250     CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
   252     // if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
   253     CheckedUint32 checked_neededByteLength
   254         = height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
   256     return checked_neededByteLength;
   257 }
   259 void
   260 WebGLContext::SynthesizeGLError(GLenum err)
   261 {
   262     /* ES2 section 2.5 "GL Errors" states that implementations can have
   263      * multiple 'flags', as errors might be caught in different parts of
   264      * a distributed implementation.
   265      * We're signing up as a distributed implementation here, with
   266      * separate flags for WebGL and the underlying GLContext.
   267      */
   268     if (!mWebGLError)
   269         mWebGLError = err;
   270 }
   272 void
   273 WebGLContext::SynthesizeGLError(GLenum err, const char *fmt, ...)
   274 {
   275     va_list va;
   276     va_start(va, fmt);
   277     GenerateWarning(fmt, va);
   278     va_end(va);
   280     return SynthesizeGLError(err);
   281 }
   283 void
   284 WebGLContext::ErrorInvalidEnum(const char *fmt, ...)
   285 {
   286     va_list va;
   287     va_start(va, fmt);
   288     GenerateWarning(fmt, va);
   289     va_end(va);
   291     return SynthesizeGLError(LOCAL_GL_INVALID_ENUM);
   292 }
   294 void
   295 WebGLContext::ErrorInvalidEnumInfo(const char *info, GLenum enumvalue)
   296 {
   297     return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
   298 }
   300 void
   301 WebGLContext::ErrorInvalidOperation(const char *fmt, ...)
   302 {
   303     va_list va;
   304     va_start(va, fmt);
   305     GenerateWarning(fmt, va);
   306     va_end(va);
   308     return SynthesizeGLError(LOCAL_GL_INVALID_OPERATION);
   309 }
   311 void
   312 WebGLContext::ErrorInvalidValue(const char *fmt, ...)
   313 {
   314     va_list va;
   315     va_start(va, fmt);
   316     GenerateWarning(fmt, va);
   317     va_end(va);
   319     return SynthesizeGLError(LOCAL_GL_INVALID_VALUE);
   320 }
   322 void
   323 WebGLContext::ErrorInvalidFramebufferOperation(const char *fmt, ...)
   324 {
   325     va_list va;
   326     va_start(va, fmt);
   327     GenerateWarning(fmt, va);
   328     va_end(va);
   330     return SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
   331 }
   333 void
   334 WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
   335 {
   336     va_list va;
   337     va_start(va, fmt);
   338     GenerateWarning(fmt, va);
   339     va_end(va);
   341     return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
   342 }
   344 const char *
   345 WebGLContext::ErrorName(GLenum error)
   346 {
   347     switch(error) {
   348         case LOCAL_GL_INVALID_ENUM:
   349             return "INVALID_ENUM";
   350         case LOCAL_GL_INVALID_OPERATION:
   351             return "INVALID_OPERATION";
   352         case LOCAL_GL_INVALID_VALUE:
   353             return "INVALID_VALUE";
   354         case LOCAL_GL_OUT_OF_MEMORY:
   355             return "OUT_OF_MEMORY";
   356         case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
   357             return "INVALID_FRAMEBUFFER_OPERATION";
   358         case LOCAL_GL_NO_ERROR:
   359             return "NO_ERROR";
   360         default:
   361             MOZ_ASSERT(false);
   362             return "[unknown WebGL error!]";
   363     }
   364 }
   366 bool
   367 WebGLContext::IsTextureFormatCompressed(GLenum format)
   368 {
   369     switch (format) {
   370         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
   371         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
   372         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
   373         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
   374         case LOCAL_GL_ATC_RGB:
   375         case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
   376         case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
   377         case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
   378         case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
   379         case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
   380         case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
   381         case LOCAL_GL_ETC1_RGB8_OES:
   382             return true;
   383         default:
   384             return false;
   385     }
   386 }
   388 GLenum
   389 WebGLContext::GetAndFlushUnderlyingGLErrors()
   390 {
   391     // Get and clear GL error in ALL cases.
   392     GLenum error = gl->GetAndClearError();
   394     // Only store in mUnderlyingGLError if is hasn't already recorded an
   395     // error.
   396     if (!mUnderlyingGLError)
   397         mUnderlyingGLError = error;
   399     return error;
   400 }

mercurial