LCOV - code coverage report
Current view: directory - content/canvas/src - WebGLContext.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 691 2 0.3 %
Date: 2012-06-02 Functions: 101 2 2.0 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  *   Mozilla Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
      24                 :  *   Mark Steele <mwsteele@gmail.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "WebGLContext.h"
      41                 : #include "WebGLExtensions.h"
      42                 : 
      43                 : #include "nsIConsoleService.h"
      44                 : #include "nsServiceManagerUtils.h"
      45                 : #include "nsIClassInfoImpl.h"
      46                 : #include "nsContentUtils.h"
      47                 : #include "nsIXPConnect.h"
      48                 : #include "nsDOMError.h"
      49                 : #include "nsIGfxInfo.h"
      50                 : 
      51                 : #include "nsIPropertyBag.h"
      52                 : #include "nsIVariant.h"
      53                 : 
      54                 : #include "imgIEncoder.h"
      55                 : 
      56                 : #include "gfxContext.h"
      57                 : #include "gfxPattern.h"
      58                 : #include "gfxUtils.h"
      59                 : 
      60                 : #include "CanvasUtils.h"
      61                 : #include "nsDisplayList.h"
      62                 : 
      63                 : #include "GLContextProvider.h"
      64                 : 
      65                 : #include "gfxCrashReporterUtils.h"
      66                 : 
      67                 : #include "nsSVGEffects.h"
      68                 : 
      69                 : #include "prenv.h"
      70                 : 
      71                 : #include "mozilla/Preferences.h"
      72                 : #include "mozilla/Telemetry.h"
      73                 : 
      74                 : using namespace mozilla;
      75                 : using namespace mozilla::gl;
      76                 : using namespace mozilla::layers;
      77                 : 
      78                 : 
      79                 : nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
      80                 : 
      81                 : nsresult
      82               0 : NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
      83                 : {
      84               0 :     Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
      85               0 :     nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
      86               0 :     if (!ctx)
      87               0 :         return NS_ERROR_OUT_OF_MEMORY;
      88                 : 
      89               0 :     NS_ADDREF(*aResult = ctx);
      90               0 :     return NS_OK;
      91                 : }
      92                 : 
      93               0 : WebGLContext::WebGLContext()
      94                 :     : mCanvasElement(nsnull),
      95               0 :       gl(nsnull)
      96                 : {
      97               0 :     mGeneration = 0;
      98               0 :     mInvalidated = false;
      99               0 :     mResetLayer = true;
     100               0 :     mVerbose = false;
     101               0 :     mOptionsFrozen = false;
     102                 : 
     103               0 :     mActiveTexture = 0;
     104               0 :     mWebGLError = LOCAL_GL_NO_ERROR;
     105               0 :     mPixelStoreFlipY = false;
     106               0 :     mPixelStorePremultiplyAlpha = false;
     107               0 :     mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
     108                 : 
     109               0 :     mShaderValidation = true;
     110                 : 
     111               0 :     mBlackTexturesAreInitialized = false;
     112               0 :     mFakeBlackStatus = DoNotNeedFakeBlack;
     113                 : 
     114               0 :     mVertexAttrib0Vector[0] = 0;
     115               0 :     mVertexAttrib0Vector[1] = 0;
     116               0 :     mVertexAttrib0Vector[2] = 0;
     117               0 :     mVertexAttrib0Vector[3] = 1;
     118               0 :     mFakeVertexAttrib0BufferObjectVector[0] = 0;
     119               0 :     mFakeVertexAttrib0BufferObjectVector[1] = 0;
     120               0 :     mFakeVertexAttrib0BufferObjectVector[2] = 0;
     121               0 :     mFakeVertexAttrib0BufferObjectVector[3] = 1;
     122               0 :     mFakeVertexAttrib0BufferObjectSize = 0;
     123               0 :     mFakeVertexAttrib0BufferObject = 0;
     124               0 :     mFakeVertexAttrib0BufferStatus = VertexAttrib0Status::Default;
     125                 : 
     126                 :     // these are de default values, see 6.2 State tables in the OpenGL ES 2.0.25 spec
     127               0 :     mColorWriteMask[0] = 1;
     128               0 :     mColorWriteMask[1] = 1;
     129               0 :     mColorWriteMask[2] = 1;
     130               0 :     mColorWriteMask[3] = 1;
     131               0 :     mDepthWriteMask = 1;
     132               0 :     mColorClearValue[0] = 0.f;
     133               0 :     mColorClearValue[1] = 0.f;
     134               0 :     mColorClearValue[2] = 0.f;
     135               0 :     mColorClearValue[3] = 0.f;
     136               0 :     mDepthClearValue = 1.f;
     137               0 :     mStencilClearValue = 0;
     138               0 :     mStencilRefFront = 0;
     139               0 :     mStencilRefBack = 0;
     140               0 :     mStencilValueMaskFront = 0xffffffff;
     141               0 :     mStencilValueMaskBack  = 0xffffffff;
     142               0 :     mStencilWriteMaskFront = 0xffffffff;
     143               0 :     mStencilWriteMaskBack  = 0xffffffff;
     144                 : 
     145               0 :     mScissorTestEnabled = 0;
     146               0 :     mDitherEnabled = 1;
     147               0 :     mBackbufferClearingStatus = BackbufferClearingStatus::NotClearedSinceLastPresented;
     148                 :     
     149                 :     // initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
     150                 :     // so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
     151               0 :     mGLMaxVertexAttribs = 0;
     152               0 :     mGLMaxTextureUnits = 0;
     153               0 :     mGLMaxTextureSize = 0;
     154               0 :     mGLMaxCubeMapTextureSize = 0;
     155               0 :     mGLMaxTextureImageUnits = 0;
     156               0 :     mGLMaxVertexTextureImageUnits = 0;
     157               0 :     mGLMaxVaryingVectors = 0;
     158               0 :     mGLMaxFragmentUniformVectors = 0;
     159               0 :     mGLMaxVertexUniformVectors = 0;
     160                 :     
     161                 :     // See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
     162               0 :     mPixelStorePackAlignment = 4;
     163               0 :     mPixelStoreUnpackAlignment = 4;
     164                 : 
     165               0 :     WebGLMemoryMultiReporterWrapper::AddWebGLContext(this);
     166                 : 
     167               0 :     mAllowRestore = true;
     168               0 :     mRobustnessTimerRunning = false;
     169               0 :     mDrawSinceRobustnessTimerSet = false;
     170               0 :     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     171               0 :     mContextStatus = ContextStable;
     172               0 :     mContextLostErrorSet = false;
     173               0 :     mContextLostDueToTest = false;
     174               0 : }
     175                 : 
     176               0 : WebGLContext::~WebGLContext()
     177                 : {
     178               0 :     DestroyResourcesAndContext();
     179               0 :     WebGLMemoryMultiReporterWrapper::RemoveWebGLContext(this);
     180               0 :     TerminateRobustnessTimer();
     181               0 :     mContextRestorer = nsnull;
     182               0 : }
     183                 : 
     184                 : void
     185               0 : WebGLContext::DestroyResourcesAndContext()
     186                 : {
     187               0 :     if (!gl)
     188               0 :         return;
     189                 : 
     190               0 :     gl->MakeCurrent();
     191                 : 
     192               0 :     mBound2DTextures.Clear();
     193               0 :     mBoundCubeMapTextures.Clear();
     194               0 :     mBoundArrayBuffer = nsnull;
     195               0 :     mBoundElementArrayBuffer = nsnull;
     196               0 :     mCurrentProgram = nsnull;
     197               0 :     mBoundFramebuffer = nsnull;
     198               0 :     mBoundRenderbuffer = nsnull;
     199                 : 
     200               0 :     mAttribBuffers.Clear();
     201                 : 
     202               0 :     while (mTextures.Length())
     203               0 :         mTextures.Last()->DeleteOnce();
     204               0 :     while (mBuffers.Length())
     205               0 :         mBuffers.Last()->DeleteOnce();
     206               0 :     while (mRenderbuffers.Length())
     207               0 :         mRenderbuffers.Last()->DeleteOnce();
     208               0 :     while (mFramebuffers.Length())
     209               0 :         mFramebuffers.Last()->DeleteOnce();
     210               0 :     while (mShaders.Length())
     211               0 :         mShaders.Last()->DeleteOnce();
     212               0 :     while (mPrograms.Length())
     213               0 :         mPrograms.Last()->DeleteOnce();
     214               0 :     while (mUniformLocations.Length())
     215               0 :         mUniformLocations.Last()->DeleteOnce();
     216                 : 
     217               0 :     if (mBlackTexturesAreInitialized) {
     218               0 :         gl->fDeleteTextures(1, &mBlackTexture2D);
     219               0 :         gl->fDeleteTextures(1, &mBlackTextureCubeMap);
     220               0 :         mBlackTexturesAreInitialized = false;
     221                 :     }
     222                 : 
     223               0 :     if (mFakeVertexAttrib0BufferObject) {
     224               0 :         gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
     225                 :     }
     226                 : 
     227                 :     // We just got rid of everything, so the context had better
     228                 :     // have been going away.
     229                 : #ifdef DEBUG
     230               0 :     printf_stderr("--- WebGL context destroyed: %p\n", gl.get());
     231                 : #endif
     232                 : 
     233               0 :     gl = nsnull;
     234                 : }
     235                 : 
     236                 : void
     237               0 : WebGLContext::Invalidate()
     238                 : {
     239               0 :     if (mInvalidated)
     240               0 :         return;
     241                 : 
     242               0 :     if (!mCanvasElement)
     243               0 :         return;
     244                 : 
     245               0 :     nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
     246                 : 
     247               0 :     mInvalidated = true;
     248               0 :     HTMLCanvasElement()->InvalidateCanvasContent(nsnull);
     249                 : }
     250                 : 
     251                 : /* readonly attribute nsIDOMHTMLCanvasElement canvas; */
     252                 : NS_IMETHODIMP
     253               0 : WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
     254                 : {
     255               0 :     NS_IF_ADDREF(*canvas = mCanvasElement);
     256                 : 
     257               0 :     return NS_OK;
     258                 : }
     259                 : 
     260                 : //
     261                 : // nsICanvasRenderingContextInternal
     262                 : //
     263                 : 
     264                 : NS_IMETHODIMP
     265               0 : WebGLContext::SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
     266                 : {
     267               0 :     mCanvasElement = aParentCanvas;
     268                 : 
     269               0 :     return NS_OK;
     270                 : }
     271                 : 
     272                 : static bool
     273               0 : GetBoolFromPropertyBag(nsIPropertyBag *bag, const char *propName, bool *boolResult)
     274                 : {
     275               0 :     nsCOMPtr<nsIVariant> vv;
     276                 :     bool bv;
     277                 : 
     278               0 :     nsresult rv = bag->GetProperty(NS_ConvertASCIItoUTF16(propName), getter_AddRefs(vv));
     279               0 :     if (NS_FAILED(rv) || !vv)
     280               0 :         return false;
     281                 : 
     282               0 :     rv = vv->GetAsBool(&bv);
     283               0 :     if (NS_FAILED(rv))
     284               0 :         return false;
     285                 : 
     286               0 :     *boolResult = bv ? true : false;
     287               0 :     return true;
     288                 : }
     289                 : 
     290                 : NS_IMETHODIMP
     291               0 : WebGLContext::SetContextOptions(nsIPropertyBag *aOptions)
     292                 : {
     293               0 :     if (!aOptions)
     294               0 :         return NS_OK;
     295                 : 
     296               0 :     WebGLContextOptions newOpts;
     297                 : 
     298               0 :     GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil);
     299               0 :     GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth);
     300               0 :     GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha);
     301               0 :     GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha);
     302               0 :     GetBoolFromPropertyBag(aOptions, "antialias", &newOpts.antialias);
     303               0 :     GetBoolFromPropertyBag(aOptions, "preserveDrawingBuffer", &newOpts.preserveDrawingBuffer);
     304                 : 
     305                 :     // enforce that if stencil is specified, we also give back depth
     306               0 :     newOpts.depth |= newOpts.stencil;
     307                 : 
     308                 : #if 0
     309                 :     LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d preserve: %d\n",
     310                 :                newOpts.antialias ? 1 : 0,
     311                 :                newOpts.stencil ? 1 : 0,
     312                 :                newOpts.depth ? 1 : 0,
     313                 :                newOpts.alpha ? 1 : 0,
     314                 :                newOpts.premultipliedAlpha ? 1 : 0,
     315                 :                newOpts.preserveDrawingBuffer ? 1 : 0);
     316                 : #endif
     317                 : 
     318               0 :     if (mOptionsFrozen && newOpts != mOptions) {
     319                 :         // Error if the options are already frozen, and the ones that were asked for
     320                 :         // aren't the same as what they were originally.
     321               0 :         return NS_ERROR_FAILURE;
     322                 :     }
     323                 : 
     324               0 :     mOptions = newOpts;
     325               0 :     return NS_OK;
     326                 : }
     327                 : 
     328                 : NS_IMETHODIMP
     329               0 : WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
     330                 : {
     331                 :     /*** early success return cases ***/
     332                 :   
     333               0 :     if (mCanvasElement) {
     334               0 :         HTMLCanvasElement()->InvalidateCanvas();
     335                 :     }
     336                 : 
     337               0 :     if (gl && mWidth == width && mHeight == height)
     338               0 :         return NS_OK;
     339                 : 
     340                 :     // Zero-sized surfaces can cause problems.
     341               0 :     if (width == 0 || height == 0) {
     342               0 :         width = 1;
     343               0 :         height = 1;
     344                 :     }
     345                 : 
     346                 :     // If we already have a gl context, then we just need to resize it
     347               0 :     if (gl) {
     348               0 :         MakeContextCurrent();
     349                 : 
     350               0 :         gl->ResizeOffscreen(gfxIntSize(width, height)); // Doesn't matter if it succeeds (soft-fail)
     351                 :         // It's unlikely that we'll get a proper-sized context if we recreate if we didn't on resize
     352                 : 
     353                 :         // everything's good, we're done here
     354               0 :         mWidth = gl->OffscreenActualSize().width;
     355               0 :         mHeight = gl->OffscreenActualSize().height;
     356               0 :         mResetLayer = true;
     357                 : 
     358               0 :         gl->ClearSafely();
     359                 : 
     360               0 :         return NS_OK;
     361                 :     }
     362                 : 
     363                 :     /*** end of early success return cases ***/
     364                 : 
     365                 :     // At this point we know that the old context is not going to survive, even though we still don't
     366                 :     // know if creating the new context will succeed.
     367               0 :     DestroyResourcesAndContext();
     368                 : 
     369                 :     // Get some prefs for some preferred/overriden things
     370               0 :     NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
     371                 : 
     372                 :     bool forceOSMesa =
     373               0 :         Preferences::GetBool("webgl.force_osmesa", false);
     374                 : #ifdef XP_WIN
     375                 :     bool preferEGL =
     376                 :         Preferences::GetBool("webgl.prefer-egl", false);
     377                 :     bool preferOpenGL =
     378                 :         Preferences::GetBool("webgl.prefer-native-gl", false);
     379                 : #endif
     380                 :     bool forceEnabled =
     381               0 :         Preferences::GetBool("webgl.force-enabled", false);
     382                 :     bool disabled =
     383               0 :         Preferences::GetBool("webgl.disabled", false);
     384                 :     bool verbose =
     385               0 :         Preferences::GetBool("webgl.verbose", false);
     386                 : 
     387               0 :     ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
     388                 : 
     389               0 :     if (disabled)
     390               0 :         return NS_ERROR_FAILURE;
     391                 : 
     392               0 :     mVerbose = verbose;
     393                 : 
     394                 :     // We're going to create an entirely new context.  If our
     395                 :     // generation is not 0 right now (that is, if this isn't the first
     396                 :     // context we're creating), we may have to dispatch a context lost
     397                 :     // event.
     398                 : 
     399                 :     // If incrementing the generation would cause overflow,
     400                 :     // don't allow it.  Allowing this would allow us to use
     401                 :     // resource handles created from older context generations.
     402               0 :     if (!(mGeneration+1).valid())
     403               0 :         return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
     404                 : 
     405               0 :     gl::ContextFormat format(gl::ContextFormat::BasicRGBA32);
     406               0 :     if (mOptions.depth) {
     407               0 :         format.depth = 24;
     408               0 :         format.minDepth = 16;
     409                 :     }
     410                 : 
     411               0 :     if (mOptions.stencil) {
     412               0 :         format.stencil = 8;
     413               0 :         format.minStencil = 8;
     414                 :     }
     415                 : 
     416               0 :     if (!mOptions.alpha) {
     417                 :         // Select 565; we won't/shouldn't hit this on the desktop,
     418                 :         // but let mobile know we're ok with it.
     419               0 :         format.red = 5;
     420               0 :         format.green = 6;
     421               0 :         format.blue = 5;
     422                 : 
     423               0 :         format.alpha = 0;
     424               0 :         format.minAlpha = 0;
     425                 :     }
     426                 : 
     427                 :     bool forceMSAA =
     428               0 :         Preferences::GetBool("webgl.msaa-force", false);
     429                 : 
     430                 :     PRInt32 status;
     431               0 :     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     432               0 :     if (mOptions.antialias &&
     433               0 :         gfxInfo &&
     434               0 :         NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) {
     435               0 :         if (status == nsIGfxInfo::FEATURE_NO_INFO || forceMSAA) {
     436               0 :             PRUint32 msaaLevel = Preferences::GetUint("webgl.msaa-level", 2);
     437               0 :             format.samples = msaaLevel*msaaLevel;
     438                 :         }
     439                 :     }
     440                 : 
     441                 : #ifdef XP_WIN
     442                 :     if (PR_GetEnv("MOZ_WEBGL_PREFER_EGL")) {
     443                 :         preferEGL = true;
     444                 :     }
     445                 : #endif
     446                 : 
     447                 :     // Ask GfxInfo about what we should use
     448               0 :     bool useOpenGL = true;
     449                 : 
     450                 : #ifdef XP_WIN
     451                 :     bool useANGLE = true;
     452                 : #endif
     453                 : 
     454               0 :     if (gfxInfo && !forceEnabled) {
     455               0 :         if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_OPENGL, &status))) {
     456               0 :             if (status != nsIGfxInfo::FEATURE_NO_INFO) {
     457               0 :                 useOpenGL = false;
     458                 :             }
     459                 :         }
     460                 : #ifdef XP_WIN
     461                 :         if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_ANGLE, &status))) {
     462                 :             if (status != nsIGfxInfo::FEATURE_NO_INFO) {
     463                 :                 useANGLE = false;
     464                 :             }
     465                 :         }
     466                 : #endif
     467                 :     }
     468                 : 
     469                 : #ifdef XP_WIN
     470                 :     // allow forcing GL and not EGL/ANGLE
     471                 :     if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
     472                 :         preferEGL = false;
     473                 :         useANGLE = false;
     474                 :         useOpenGL = true;
     475                 :     }
     476                 : #endif
     477                 : 
     478                 :     // if we're forcing osmesa, do it first
     479               0 :     if (forceOSMesa) {
     480               0 :         gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
     481               0 :         if (!gl || !InitAndValidateGL()) {
     482               0 :             LogMessage("OSMesa forced, but creating context failed -- aborting!");
     483               0 :             return NS_ERROR_FAILURE;
     484                 :         }
     485               0 :         LogMessage("Using software rendering via OSMesa (THIS WILL BE SLOW)");
     486                 :     }
     487                 : 
     488                 : #ifdef XP_WIN
     489                 :     // if we want EGL, try it now
     490                 :     if (!gl && (preferEGL || useANGLE) && !preferOpenGL) {
     491                 :         gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
     492                 :         if (gl && !InitAndValidateGL()) {
     493                 :             LogMessage("Error during ANGLE OpenGL ES initialization");
     494                 :             return NS_ERROR_FAILURE;
     495                 :         }
     496                 :     }
     497                 : #endif
     498                 : 
     499                 :     // try the default provider, whatever that is
     500               0 :     if (!gl && useOpenGL) {
     501               0 :         gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
     502               0 :         if (gl && !InitAndValidateGL()) {
     503               0 :             LogMessage("Error during OpenGL initialization");
     504               0 :             return NS_ERROR_FAILURE;
     505                 :         }
     506                 :     }
     507                 : 
     508                 :     // finally, try OSMesa
     509               0 :     if (!gl) {
     510               0 :         gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
     511               0 :         if (gl) {
     512               0 :             if (!InitAndValidateGL()) {
     513               0 :                 LogMessage("Error during OSMesa initialization");
     514               0 :                 return NS_ERROR_FAILURE;
     515                 :             } else {
     516               0 :                 LogMessage("Using software rendering via OSMesa (THIS WILL BE SLOW)");
     517                 :             }
     518                 :         }
     519                 :     }
     520                 : 
     521               0 :     if (!gl) {
     522               0 :         LogMessage("Can't get a usable WebGL context");
     523               0 :         return NS_ERROR_FAILURE;
     524                 :     }
     525                 : 
     526                 : #ifdef DEBUG
     527               0 :     printf_stderr ("--- WebGL context created: %p\n", gl.get());
     528                 : #endif
     529                 : 
     530               0 :     mWidth = width;
     531               0 :     mHeight = height;
     532               0 :     mResetLayer = true;
     533               0 :     mOptionsFrozen = true;
     534                 : 
     535               0 :     mHasRobustness = gl->HasRobustness();
     536                 : 
     537                 :     // increment the generation number
     538               0 :     ++mGeneration;
     539                 : 
     540                 : #if 0
     541                 :     if (mGeneration > 0) {
     542                 :         // XXX dispatch context lost event
     543                 :     }
     544                 : #endif
     545                 : 
     546               0 :     MakeContextCurrent();
     547                 : 
     548                 :     // Make sure that we clear this out, otherwise
     549                 :     // we'll end up displaying random memory
     550               0 :     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, gl->GetOffscreenFBO());
     551                 : 
     552               0 :     gl->fViewport(0, 0, mWidth, mHeight);
     553               0 :     gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     554               0 :     gl->fClearDepth(1.0f);
     555               0 :     gl->fClearStencil(0);
     556                 : 
     557               0 :     gl->ClearSafely();
     558                 : 
     559               0 :     reporter.SetSuccessful();
     560               0 :     return NS_OK;
     561                 : }
     562                 : 
     563                 : NS_IMETHODIMP
     564               0 : WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f)
     565                 : {
     566               0 :     if (!gl)
     567               0 :         return NS_OK;
     568                 : 
     569                 :     nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
     570               0 :                                                          gfxASurface::ImageFormatARGB32);
     571               0 :     if (surf->CairoStatus() != 0)
     572               0 :         return NS_ERROR_FAILURE;
     573                 : 
     574               0 :     gl->ReadPixelsIntoImageSurface(0, 0, mWidth, mHeight, surf);
     575               0 :     gfxUtils::PremultiplyImageSurface(surf);
     576                 : 
     577               0 :     nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
     578               0 :     pat->SetFilter(f);
     579                 : 
     580                 :     // Pixels from ReadPixels will be "upside down" compared to
     581                 :     // what cairo wants, so draw with a y-flip and a translte to
     582                 :     // flip them.
     583               0 :     gfxMatrix m;
     584               0 :     m.Translate(gfxPoint(0.0, mHeight));
     585               0 :     m.Scale(1.0, -1.0);
     586               0 :     pat->SetMatrix(m);
     587                 : 
     588               0 :     ctx->NewPath();
     589               0 :     ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
     590               0 :     ctx->Fill();
     591                 : 
     592               0 :     return NS_OK;
     593                 : }
     594                 : 
     595                 : NS_IMETHODIMP
     596               0 : WebGLContext::GetInputStream(const char* aMimeType,
     597                 :                              const PRUnichar* aEncoderOptions,
     598                 :                              nsIInputStream **aStream)
     599                 : {
     600               0 :     NS_ASSERTION(gl, "GetInputStream on invalid context?");
     601               0 :     if (!gl)
     602               0 :         return NS_ERROR_FAILURE;
     603                 : 
     604                 :     nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(gfxIntSize(mWidth, mHeight),
     605               0 :                                                          gfxASurface::ImageFormatARGB32);
     606               0 :     if (surf->CairoStatus() != 0)
     607               0 :         return NS_ERROR_FAILURE;
     608                 : 
     609               0 :     nsRefPtr<gfxContext> tmpcx = new gfxContext(surf);
     610                 :     // Use Render() to make sure that appropriate y-flip gets applied
     611               0 :     nsresult rv = Render(tmpcx, gfxPattern::FILTER_NEAREST);
     612               0 :     if (NS_FAILED(rv))
     613               0 :         return rv;
     614                 : 
     615               0 :     const char encoderPrefix[] = "@mozilla.org/image/encoder;2?type=";
     616               0 :     nsAutoArrayPtr<char> conid(new char[strlen(encoderPrefix) + strlen(aMimeType) + 1]);
     617                 : 
     618               0 :     if (!conid)
     619               0 :         return NS_ERROR_OUT_OF_MEMORY;
     620                 : 
     621               0 :     strcpy(conid, encoderPrefix);
     622               0 :     strcat(conid, aMimeType);
     623                 : 
     624               0 :     nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(conid);
     625               0 :     if (!encoder)
     626               0 :         return NS_ERROR_FAILURE;
     627                 : 
     628               0 :     rv = encoder->InitFromData(surf->Data(),
     629                 :                                mWidth * mHeight * 4,
     630                 :                                mWidth, mHeight,
     631               0 :                                surf->Stride(),
     632                 :                                imgIEncoder::INPUT_FORMAT_HOSTARGB,
     633               0 :                                nsDependentString(aEncoderOptions));
     634               0 :     NS_ENSURE_SUCCESS(rv, rv);
     635                 : 
     636               0 :     return CallQueryInterface(encoder, aStream);
     637                 : }
     638                 : 
     639                 : NS_IMETHODIMP
     640               0 : WebGLContext::GetThebesSurface(gfxASurface **surface)
     641                 : {
     642               0 :     return NS_ERROR_NOT_AVAILABLE;
     643                 : }
     644                 : 
     645                 : static PRUint8 gWebGLLayerUserData;
     646                 : 
     647                 : namespace mozilla {
     648                 : 
     649               0 : class WebGLContextUserData : public LayerUserData {
     650                 : public:
     651               0 :     WebGLContextUserData(nsHTMLCanvasElement *aContent)
     652               0 :     : mContent(aContent) {}
     653                 : 
     654                 :   /** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
     655                 :     * so it really is the right place to put actions that have to be performed upon compositing
     656                 :     */
     657               0 :   static void DidTransactionCallback(void* aData)
     658                 :   {
     659               0 :     WebGLContextUserData *userdata = static_cast<WebGLContextUserData*>(aData);
     660               0 :     nsHTMLCanvasElement *canvas = userdata->mContent;
     661               0 :     WebGLContext *context = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
     662                 : 
     663               0 :     context->mBackbufferClearingStatus = BackbufferClearingStatus::NotClearedSinceLastPresented;
     664               0 :     canvas->MarkContextClean();
     665               0 :   }
     666                 : 
     667                 : private:
     668                 :   nsRefPtr<nsHTMLCanvasElement> mContent;
     669                 : };
     670                 : 
     671                 : } // end namespace mozilla
     672                 : 
     673                 : already_AddRefed<layers::CanvasLayer>
     674               0 : WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
     675                 :                              CanvasLayer *aOldLayer,
     676                 :                              LayerManager *aManager)
     677                 : {
     678               0 :     if (!IsContextStable())
     679               0 :         return nsnull;
     680                 : 
     681               0 :     if (!mResetLayer && aOldLayer &&
     682               0 :         aOldLayer->HasUserData(&gWebGLLayerUserData)) {
     683               0 :         NS_ADDREF(aOldLayer);
     684               0 :         return aOldLayer;
     685                 :     }
     686                 : 
     687               0 :     nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
     688               0 :     if (!canvasLayer) {
     689               0 :         NS_WARNING("CreateCanvasLayer returned null!");
     690               0 :         return nsnull;
     691                 :     }
     692               0 :     WebGLContextUserData *userData = nsnull;
     693               0 :     if (aBuilder->IsPaintingToWindow()) {
     694                 :       // Make the layer tell us whenever a transaction finishes (including
     695                 :       // the current transaction), so we can clear our invalidation state and
     696                 :       // start invalidating again. We need to do this for the layer that is
     697                 :       // being painted to a window (there shouldn't be more than one at a time,
     698                 :       // and if there is, flushing the invalidation state more often than
     699                 :       // necessary is harmless).
     700                 : 
     701                 :       // The layer will be destroyed when we tear down the presentation
     702                 :       // (at the latest), at which time this userData will be destroyed,
     703                 :       // releasing the reference to the element.
     704                 :       // The userData will receive DidTransactionCallbacks, which flush the
     705                 :       // the invalidation state to indicate that the canvas is up to date.
     706               0 :       userData = new WebGLContextUserData(HTMLCanvasElement());
     707                 :       canvasLayer->SetDidTransactionCallback(
     708               0 :               WebGLContextUserData::DidTransactionCallback, userData);
     709                 :     }
     710               0 :     canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
     711                 : 
     712               0 :     CanvasLayer::Data data;
     713                 : 
     714                 :     // the gl context may either provide a native PBuffer, in which case we want to initialize
     715                 :     // data with the gl context directly, or may provide a surface to which it renders (this is the case
     716                 :     // of OSMesa contexts), in which case we want to initialize data with that surface.
     717                 : 
     718               0 :     void* native_surface = gl->GetNativeData(gl::GLContext::NativeImageSurface);
     719                 : 
     720               0 :     if (native_surface) {
     721               0 :         data.mSurface = static_cast<gfxASurface*>(native_surface);
     722                 :     } else {
     723               0 :         data.mGLContext = gl.get();
     724                 :     }
     725                 : 
     726               0 :     data.mSize = nsIntSize(mWidth, mHeight);
     727               0 :     data.mGLBufferIsPremultiplied = mOptions.premultipliedAlpha ? true : false;
     728                 : 
     729               0 :     canvasLayer->Initialize(data);
     730               0 :     PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0;
     731               0 :     canvasLayer->SetContentFlags(flags);
     732               0 :     canvasLayer->Updated();
     733                 : 
     734               0 :     mResetLayer = false;
     735                 : 
     736               0 :     return canvasLayer.forget().get();
     737                 : }
     738                 : 
     739                 : NS_IMETHODIMP
     740               0 : WebGLContext::GetContextAttributes(jsval *aResult)
     741                 : {
     742               0 :     if (!IsContextStable())
     743                 :     {
     744               0 :         *aResult = OBJECT_TO_JSVAL(NULL);
     745               0 :         return NS_OK;
     746                 :     }
     747                 : 
     748               0 :     JSContext *cx = nsContentUtils::GetCurrentJSContext();
     749               0 :     if (!cx)
     750               0 :         return NS_ERROR_FAILURE;
     751                 : 
     752               0 :     JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
     753               0 :     if (!obj)
     754               0 :         return NS_ERROR_FAILURE;
     755                 : 
     756               0 :     *aResult = OBJECT_TO_JSVAL(obj);
     757                 : 
     758               0 :     gl::ContextFormat cf = gl->ActualFormat();
     759                 : 
     760               0 :     if (!JS_DefineProperty(cx, obj, "alpha", cf.alpha > 0 ? JSVAL_TRUE : JSVAL_FALSE,
     761               0 :                            NULL, NULL, JSPROP_ENUMERATE) ||
     762                 :         !JS_DefineProperty(cx, obj, "depth", cf.depth > 0 ? JSVAL_TRUE : JSVAL_FALSE,
     763               0 :                            NULL, NULL, JSPROP_ENUMERATE) ||
     764                 :         !JS_DefineProperty(cx, obj, "stencil", cf.stencil > 0 ? JSVAL_TRUE : JSVAL_FALSE,
     765               0 :                            NULL, NULL, JSPROP_ENUMERATE) ||
     766                 :         !JS_DefineProperty(cx, obj, "antialias", cf.samples > 0 ? JSVAL_TRUE : JSVAL_FALSE,
     767               0 :                            NULL, NULL, JSPROP_ENUMERATE) ||
     768                 :         !JS_DefineProperty(cx, obj, "premultipliedAlpha",
     769                 :                            mOptions.premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE,
     770               0 :                            NULL, NULL, JSPROP_ENUMERATE) ||
     771                 :         !JS_DefineProperty(cx, obj, "preserveDrawingBuffer",
     772                 :                            mOptions.preserveDrawingBuffer ? JSVAL_TRUE : JSVAL_FALSE,
     773               0 :                            NULL, NULL, JSPROP_ENUMERATE))
     774                 :     {
     775               0 :         *aResult = JSVAL_VOID;
     776               0 :         return NS_ERROR_FAILURE;
     777                 :     }
     778                 : 
     779               0 :     return NS_OK;
     780                 : }
     781                 : 
     782                 : /* [noscript] DOMString mozGetUnderlyingParamString(in WebGLenum pname); */
     783                 : NS_IMETHODIMP
     784               0 : WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
     785                 : {
     786               0 :     if (!IsContextStable())
     787               0 :         return NS_OK;
     788                 : 
     789               0 :     retval.SetIsVoid(true);
     790                 : 
     791               0 :     MakeContextCurrent();
     792                 : 
     793               0 :     switch (pname) {
     794                 :     case LOCAL_GL_VENDOR:
     795                 :     case LOCAL_GL_RENDERER:
     796                 :     case LOCAL_GL_VERSION:
     797                 :     case LOCAL_GL_SHADING_LANGUAGE_VERSION:
     798                 :     case LOCAL_GL_EXTENSIONS: {
     799               0 :         const char *s = (const char *) gl->fGetString(pname);
     800               0 :         retval.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(s)));
     801                 :     }
     802                 :         break;
     803                 : 
     804                 :     default:
     805               0 :         return NS_ERROR_INVALID_ARG;
     806                 :     }
     807                 : 
     808               0 :     return NS_OK;
     809                 : }
     810                 : 
     811               0 : bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
     812                 : {
     813                 :     bool isSupported;
     814                 : 
     815               0 :     switch (ei) {
     816                 :         case WebGL_OES_texture_float:
     817               0 :             isSupported = gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float 
     818               0 :                                                                  : GLContext::ARB_texture_float);
     819               0 :             break;
     820                 :         case WebGL_OES_standard_derivatives:
     821                 :             // We always support this extension.
     822               0 :             isSupported = true;
     823               0 :             break;
     824                 :         case WebGL_EXT_texture_filter_anisotropic:
     825               0 :             isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
     826               0 :             break;
     827                 :         case WebGL_MOZ_WEBGL_lose_context:
     828                 :             // We always support this extension.
     829               0 :             isSupported = true;
     830               0 :             break;
     831                 :         default:
     832               0 :             isSupported = false;
     833                 :     }
     834                 : 
     835               0 :     return isSupported;
     836                 : }
     837                 : 
     838                 : NS_IMETHODIMP
     839               0 : WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
     840                 : {
     841               0 :     *retval = nsnull;
     842               0 :     if (!IsContextStable())
     843               0 :         return NS_OK;
     844                 :     
     845               0 :     if (mDisableExtensions) {
     846               0 :         return NS_OK;
     847                 :     }
     848                 : 
     849                 :     // handle simple extensions that don't need custom objects first
     850               0 :     WebGLExtensionID ei = WebGLExtensionID_Max;
     851               0 :     if (aName.EqualsLiteral("OES_texture_float")) {
     852               0 :         if (IsExtensionSupported(WebGL_OES_texture_float))
     853               0 :             ei = WebGL_OES_texture_float;
     854                 :     }
     855               0 :     else if (aName.EqualsLiteral("OES_standard_derivatives")) {
     856               0 :         if (IsExtensionSupported(WebGL_OES_standard_derivatives))
     857               0 :             ei = WebGL_OES_standard_derivatives;
     858                 :     }
     859               0 :     else if (aName.EqualsLiteral("MOZ_EXT_texture_filter_anisotropic")) {
     860               0 :         if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
     861               0 :             ei = WebGL_EXT_texture_filter_anisotropic;
     862                 :     }
     863               0 :     else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) {
     864               0 :         if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
     865               0 :             ei = WebGL_MOZ_WEBGL_lose_context;
     866                 :     }
     867                 : 
     868               0 :     if (ei != WebGLExtensionID_Max) {
     869               0 :         if (!IsExtensionEnabled(ei)) {
     870               0 :             switch (ei) {
     871                 :                 case WebGL_OES_standard_derivatives:
     872               0 :                     mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
     873               0 :                     break;
     874                 :                 case WebGL_EXT_texture_filter_anisotropic:
     875               0 :                     mEnabledExtensions[ei] = new WebGLExtensionTextureFilterAnisotropic(this);
     876               0 :                     break;
     877                 :                 case WebGL_MOZ_WEBGL_lose_context:
     878               0 :                     mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
     879               0 :                     break;
     880                 :                 // create an extension for any types that don't
     881                 :                 // have any additional tokens or methods
     882                 :                 default:
     883               0 :                     mEnabledExtensions[ei] = new WebGLExtension(this);
     884               0 :                     break;
     885                 :             }
     886                 :         }
     887               0 :         NS_ADDREF(*retval = mEnabledExtensions[ei]);
     888                 :     }
     889                 : 
     890               0 :     return NS_OK;
     891                 : }
     892                 : 
     893                 : void
     894               0 : WebGLContext::ForceClearFramebufferWithDefaultValues(PRUint32 mask, const nsIntRect& viewportRect)
     895                 : {
     896               0 :     MakeContextCurrent();
     897                 : 
     898               0 :     bool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
     899               0 :     bool initializeDepthBuffer = 0 != (mask & LOCAL_GL_DEPTH_BUFFER_BIT);
     900               0 :     bool initializeStencilBuffer = 0 != (mask & LOCAL_GL_STENCIL_BUFFER_BIT);
     901                 : 
     902                 :     // fun GL fact: no need to worry about the viewport here, glViewport is just setting up a coordinates transformation,
     903                 :     // it doesn't affect glClear at all
     904                 : 
     905                 :     // prepare GL state for clearing
     906               0 :     gl->fDisable(LOCAL_GL_SCISSOR_TEST);
     907               0 :     gl->fDisable(LOCAL_GL_DITHER);
     908                 : 
     909               0 :     if (initializeColorBuffer) {
     910               0 :         gl->fColorMask(1, 1, 1, 1);
     911               0 :         gl->fClearColor(0.f, 0.f, 0.f, 0.f);
     912                 :     }
     913                 : 
     914               0 :     if (initializeDepthBuffer) {
     915               0 :         gl->fDepthMask(1);
     916               0 :         gl->fClearDepth(1.0f);
     917                 :     }
     918                 : 
     919               0 :     if (initializeStencilBuffer) {
     920               0 :         gl->fStencilMask(0xffffffff);
     921               0 :         gl->fClearStencil(0);
     922                 :     }
     923                 : 
     924                 :     // do clear
     925               0 :     gl->fClear(mask);
     926                 : 
     927                 :     // restore GL state after clearing
     928               0 :     if (initializeColorBuffer) {
     929               0 :         gl->fColorMask(mColorWriteMask[0],
     930               0 :                        mColorWriteMask[1],
     931               0 :                        mColorWriteMask[2],
     932               0 :                        mColorWriteMask[3]);
     933                 :         gl->fClearColor(mColorClearValue[0],
     934                 :                         mColorClearValue[1],
     935                 :                         mColorClearValue[2],
     936               0 :                         mColorClearValue[3]);
     937                 :     }
     938                 : 
     939               0 :     if (initializeDepthBuffer) {
     940               0 :         gl->fDepthMask(mDepthWriteMask);
     941               0 :         gl->fClearDepth(mDepthClearValue);
     942                 :     }
     943                 : 
     944               0 :     if (initializeStencilBuffer) {
     945               0 :         gl->fStencilMaskSeparate(LOCAL_GL_FRONT, mStencilWriteMaskFront);
     946               0 :         gl->fStencilMaskSeparate(LOCAL_GL_BACK, mStencilWriteMaskBack);
     947               0 :         gl->fClearStencil(mStencilClearValue);
     948                 :     }
     949                 : 
     950               0 :     if (mDitherEnabled)
     951               0 :         gl->fEnable(LOCAL_GL_DITHER);
     952                 :     else
     953               0 :         gl->fDisable(LOCAL_GL_DITHER);
     954                 : 
     955               0 :     if (mScissorTestEnabled)
     956               0 :         gl->fEnable(LOCAL_GL_SCISSOR_TEST);
     957                 :     else
     958               0 :         gl->fDisable(LOCAL_GL_SCISSOR_TEST);
     959               0 : }
     960                 : 
     961                 : void
     962               0 : WebGLContext::EnsureBackbufferClearedAsNeeded()
     963                 : {
     964               0 :     if (mOptions.preserveDrawingBuffer)
     965               0 :         return;
     966                 : 
     967               0 :     NS_ABORT_IF_FALSE(!mBoundFramebuffer,
     968                 :                       "EnsureBackbufferClearedAsNeeded must not be called when a FBO is bound");
     969                 : 
     970               0 :     if (mBackbufferClearingStatus != BackbufferClearingStatus::NotClearedSinceLastPresented)
     971               0 :         return;
     972                 : 
     973               0 :     mBackbufferClearingStatus = BackbufferClearingStatus::ClearedToDefaultValues;
     974                 : 
     975                 :     ForceClearFramebufferWithDefaultValues(LOCAL_GL_COLOR_BUFFER_BIT |
     976                 :                                            LOCAL_GL_DEPTH_BUFFER_BIT |
     977                 :                                            LOCAL_GL_STENCIL_BUFFER_BIT,
     978               0 :                                            nsIntRect(0, 0, mWidth, mHeight));
     979                 : 
     980               0 :     Invalidate();
     981                 : }
     982                 : 
     983                 : nsresult
     984               0 : WebGLContext::DummyFramebufferOperation(const char *info)
     985                 : {
     986                 :     WebGLenum status;
     987               0 :     CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER, &status);
     988               0 :     if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE)
     989               0 :         return NS_OK;
     990                 :     else
     991               0 :         return ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
     992                 : }
     993                 : 
     994                 : // We use this timer for many things. Here are the things that it is activated for:
     995                 : // 1) If a script is using the MOZ_WEBGL_lose_context extension.
     996                 : // 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
     997                 : //    CONTEXT_LOST_WEBGL error has been triggered.
     998                 : // 3) If we are using ANGLE, or anything that supports ARB_robustness, query the
     999                 : //    GPU periodically to see if the reset status bit has been set.
    1000                 : // In all of these situations, we use this timer to send the script context lost
    1001                 : // and restored events asynchronously. For example, if it triggers a context loss,
    1002                 : // the webglcontextlost event will be sent to it the next time the robustness timer
    1003                 : // fires.
    1004                 : // Note that this timer mechanism is not used unless one of these 3 criteria
    1005                 : // are met.
    1006                 : // At a bare minimum, from context lost to context restores, it would take 3
    1007                 : // full timer iterations: detection, webglcontextlost, webglcontextrestored.
    1008                 : NS_IMETHODIMP
    1009               0 : WebGLContext::Notify(nsITimer* timer)
    1010                 : {
    1011               0 :     TerminateRobustnessTimer();
    1012                 :     // If the context has been lost and we're waiting for it to be restored, do
    1013                 :     // that now.
    1014               0 :     if (mContextStatus == ContextLostAwaitingEvent) {
    1015                 :         bool defaultAction;
    1016               0 :         nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
    1017               0 :                                              (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
    1018               0 :                                              NS_LITERAL_STRING("webglcontextlost"),
    1019                 :                                              true,
    1020                 :                                              true,
    1021               0 :                                              &defaultAction);
    1022                 : 
    1023                 :         // If the script didn't handle the event, we don't allow restores.
    1024               0 :         if (defaultAction)
    1025               0 :             mAllowRestore = false;
    1026                 : 
    1027                 :         // If the script handled the event and we are allowing restores, then
    1028                 :         // mark it to be restored. Otherwise, leave it as context lost
    1029                 :         // (unusable).
    1030               0 :         if (!defaultAction && mAllowRestore) {
    1031               0 :             ForceRestoreContext();
    1032                 :             // Restart the timer so that it will be restored on the next
    1033                 :             // callback.
    1034               0 :             SetupRobustnessTimer();
    1035                 :         } else {
    1036               0 :             mContextStatus = ContextLost;
    1037                 :         }
    1038               0 :     } else if (mContextStatus == ContextLostAwaitingRestore) {
    1039                 :         // Try to restore the context. If it fails, try again later.
    1040               0 :         if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
    1041               0 :             SetupRobustnessTimer();
    1042               0 :             return NS_OK;
    1043                 :         }
    1044               0 :         mContextStatus = ContextStable;
    1045               0 :         nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
    1046               0 :                                              (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
    1047               0 :                                              NS_LITERAL_STRING("webglcontextrestored"),
    1048                 :                                              true,
    1049               0 :                                              true);
    1050                 :         // Set all flags back to the state they were in before the context was
    1051                 :         // lost.
    1052               0 :         mContextLostErrorSet = false;
    1053               0 :         mContextLostDueToTest = false;
    1054               0 :         mAllowRestore = true;
    1055                 :     }
    1056                 : 
    1057               0 :     MaybeRestoreContext();
    1058               0 :     return NS_OK;
    1059                 : }
    1060                 : 
    1061                 : void
    1062               0 : WebGLContext::MaybeRestoreContext()
    1063                 : {
    1064                 :     // Don't try to handle it if we already know it's busted.
    1065               0 :     if (mContextStatus != ContextStable || gl == nsnull)
    1066               0 :         return;
    1067                 : 
    1068               0 :     bool isEGL = gl->GetContextType() == GLContext::ContextTypeEGL,
    1069               0 :          isANGLE = gl->IsANGLE();
    1070                 : 
    1071                 :     // If was lost due to a forced context loss, don't try to handle it.
    1072                 :     // Also, we also don't try to handle if if we don't have robustness.
    1073                 :     // Note that the code in this function is used only for situations where
    1074                 :     // we have an actual context loss, and not a simulated one.
    1075               0 :     if (mContextLostDueToTest ||
    1076               0 :         (!mHasRobustness && !isEGL))
    1077               0 :         return;
    1078                 : 
    1079               0 :     GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
    1080               0 :     if (mHasRobustness) {
    1081               0 :         gl->MakeCurrent();
    1082               0 :         resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
    1083               0 :     } else if (isEGL) {
    1084                 :         // Simulate a ARB_robustness guilty context loss for when we
    1085                 :         // get an EGL_CONTEXT_LOST error. It may not actually be guilty,
    1086                 :         // but we can't make any distinction, so we must assume the worst
    1087                 :         // case.
    1088               0 :         if (!gl->MakeCurrent(true) && gl->IsContextLost()) {
    1089               0 :             resetStatus = GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB;
    1090                 :         }
    1091                 :     }
    1092                 :     
    1093               0 :     if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
    1094                 :         // It's already lost, but clean up after it and signal to JS that it is
    1095                 :         // lost.
    1096               0 :         ForceLoseContext();
    1097                 :     }
    1098                 : 
    1099               0 :     switch (resetStatus) {
    1100                 :         case GLContext::CONTEXT_NO_ERROR:
    1101                 :             // If there has been activity since the timer was set, it's possible
    1102                 :             // that we did or are going to miss something, so clear this flag and
    1103                 :             // run it again some time later.
    1104               0 :             if (mDrawSinceRobustnessTimerSet)
    1105               0 :                 SetupRobustnessTimer();
    1106               0 :             break;
    1107                 :         case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
    1108               0 :             NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
    1109               0 :             mAllowRestore = false;
    1110               0 :             break;
    1111                 :         case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
    1112               0 :             break;
    1113                 :         case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
    1114               0 :             NS_WARNING("WebGL content on the page might have caused the graphics card to reset");
    1115               0 :             if (isEGL && isANGLE) {
    1116                 :                 // If we're using ANGLE, we ONLY get back UNKNOWN context resets, including for guilty contexts.
    1117                 :                 // This means that we can't restore it or risk restoring a guilty context. Should this ever change,
    1118                 :                 // we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the
    1119                 :                 // only use for it. See ANGLE issue 261.
    1120               0 :                 mAllowRestore = false;
    1121                 :             }
    1122               0 :             break;
    1123                 :     }
    1124                 : }
    1125                 : 
    1126                 : void
    1127               0 : WebGLContext::ForceLoseContext()
    1128                 : {
    1129               0 :     mContextStatus = ContextLostAwaitingEvent;
    1130                 :     // Queue up a task to restore the event.
    1131               0 :     SetupRobustnessTimer();
    1132               0 :     DestroyResourcesAndContext();
    1133               0 : }
    1134                 : 
    1135                 : void
    1136               0 : WebGLContext::ForceRestoreContext()
    1137                 : {
    1138               0 :     mContextStatus = ContextLostAwaitingRestore;
    1139               0 : }
    1140                 : 
    1141                 : //
    1142                 : // XPCOM goop
    1143                 : //
    1144                 : 
    1145               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
    1146               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
    1147                 : 
    1148            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLContext)
    1149               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
    1150               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
    1151               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1152               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLContext)
    1153               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
    1154               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1155                 : 
    1156                 : DOMCI_DATA(WebGLRenderingContext, WebGLContext)
    1157                 : 
    1158               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
    1159               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
    1160               0 :   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
    1161               0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    1162               0 :   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
    1163               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
    1164               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderingContext)
    1165               0 : NS_INTERFACE_MAP_END
    1166                 : 
    1167               0 : NS_IMPL_ADDREF(WebGLBuffer)
    1168               0 : NS_IMPL_RELEASE(WebGLBuffer)
    1169                 : 
    1170                 : DOMCI_DATA(WebGLBuffer, WebGLBuffer)
    1171                 : 
    1172               0 : NS_INTERFACE_MAP_BEGIN(WebGLBuffer)
    1173               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLBuffer)
    1174               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1175               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLBuffer)
    1176               0 : NS_INTERFACE_MAP_END
    1177                 : 
    1178               0 : NS_IMPL_ADDREF(WebGLTexture)
    1179               0 : NS_IMPL_RELEASE(WebGLTexture)
    1180                 : 
    1181                 : DOMCI_DATA(WebGLTexture, WebGLTexture)
    1182                 : 
    1183               0 : NS_INTERFACE_MAP_BEGIN(WebGLTexture)
    1184               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLTexture)
    1185               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1186               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLTexture)
    1187               0 : NS_INTERFACE_MAP_END
    1188                 : 
    1189               0 : NS_IMPL_ADDREF(WebGLProgram)
    1190               0 : NS_IMPL_RELEASE(WebGLProgram)
    1191                 : 
    1192                 : DOMCI_DATA(WebGLProgram, WebGLProgram)
    1193                 : 
    1194               0 : NS_INTERFACE_MAP_BEGIN(WebGLProgram)
    1195               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLProgram)
    1196               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1197               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLProgram)
    1198               0 : NS_INTERFACE_MAP_END
    1199                 : 
    1200               0 : NS_IMPL_ADDREF(WebGLShader)
    1201               0 : NS_IMPL_RELEASE(WebGLShader)
    1202                 : 
    1203                 : DOMCI_DATA(WebGLShader, WebGLShader)
    1204                 : 
    1205               0 : NS_INTERFACE_MAP_BEGIN(WebGLShader)
    1206               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLShader)
    1207               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1208               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLShader)
    1209               0 : NS_INTERFACE_MAP_END
    1210                 : 
    1211               0 : NS_IMPL_ADDREF(WebGLFramebuffer)
    1212               0 : NS_IMPL_RELEASE(WebGLFramebuffer)
    1213                 : 
    1214                 : DOMCI_DATA(WebGLFramebuffer, WebGLFramebuffer)
    1215                 : 
    1216               0 : NS_INTERFACE_MAP_BEGIN(WebGLFramebuffer)
    1217               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLFramebuffer)
    1218               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1219               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLFramebuffer)
    1220               0 : NS_INTERFACE_MAP_END
    1221                 : 
    1222               0 : NS_IMPL_ADDREF(WebGLRenderbuffer)
    1223               0 : NS_IMPL_RELEASE(WebGLRenderbuffer)
    1224                 : 
    1225                 : DOMCI_DATA(WebGLRenderbuffer, WebGLRenderbuffer)
    1226                 : 
    1227               0 : NS_INTERFACE_MAP_BEGIN(WebGLRenderbuffer)
    1228               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLRenderbuffer)
    1229               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1230               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLRenderbuffer)
    1231               0 : NS_INTERFACE_MAP_END
    1232                 : 
    1233               0 : NS_IMPL_ADDREF(WebGLUniformLocation)
    1234               0 : NS_IMPL_RELEASE(WebGLUniformLocation)
    1235                 : 
    1236                 : DOMCI_DATA(WebGLUniformLocation, WebGLUniformLocation)
    1237                 : 
    1238               0 : NS_INTERFACE_MAP_BEGIN(WebGLUniformLocation)
    1239               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLUniformLocation)
    1240               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1241               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLUniformLocation)
    1242               0 : NS_INTERFACE_MAP_END
    1243                 : 
    1244               0 : NS_IMPL_ADDREF(WebGLShaderPrecisionFormat)
    1245               0 : NS_IMPL_RELEASE(WebGLShaderPrecisionFormat)
    1246                 : 
    1247                 : DOMCI_DATA(WebGLShaderPrecisionFormat, WebGLShaderPrecisionFormat)
    1248                 : 
    1249               0 : NS_INTERFACE_MAP_BEGIN(WebGLShaderPrecisionFormat)
    1250               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLShaderPrecisionFormat)
    1251               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1252               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLShaderPrecisionFormat)
    1253               0 : NS_INTERFACE_MAP_END
    1254                 : 
    1255               0 : NS_IMPL_ADDREF(WebGLActiveInfo)
    1256               0 : NS_IMPL_RELEASE(WebGLActiveInfo)
    1257                 : 
    1258                 : DOMCI_DATA(WebGLActiveInfo, WebGLActiveInfo)
    1259                 : 
    1260               0 : NS_INTERFACE_MAP_BEGIN(WebGLActiveInfo)
    1261               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLActiveInfo)
    1262               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1263               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLActiveInfo)
    1264               0 : NS_INTERFACE_MAP_END
    1265                 : 
    1266                 : #define NAME_NOT_SUPPORTED(base) \
    1267                 : NS_IMETHODIMP base::GetName(WebGLuint *aName) \
    1268                 : { return NS_ERROR_NOT_IMPLEMENTED; } \
    1269                 : NS_IMETHODIMP base::SetName(WebGLuint aName) \
    1270                 : { return NS_ERROR_NOT_IMPLEMENTED; }
    1271                 : 
    1272               0 : NAME_NOT_SUPPORTED(WebGLTexture)
    1273               0 : NAME_NOT_SUPPORTED(WebGLBuffer)
    1274               0 : NAME_NOT_SUPPORTED(WebGLProgram)
    1275               0 : NAME_NOT_SUPPORTED(WebGLShader)
    1276               0 : NAME_NOT_SUPPORTED(WebGLFramebuffer)
    1277               0 : NAME_NOT_SUPPORTED(WebGLRenderbuffer)
    1278                 : 
    1279               0 : NS_IMPL_ADDREF(WebGLExtension)
    1280               0 : NS_IMPL_RELEASE(WebGLExtension)
    1281                 : 
    1282                 : DOMCI_DATA(WebGLExtension, WebGLExtension)
    1283                 : 
    1284               0 : NS_INTERFACE_MAP_BEGIN(WebGLExtension)
    1285               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLExtension)
    1286               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1287               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtension)
    1288               0 : NS_INTERFACE_MAP_END
    1289                 : 
    1290               0 : NS_IMPL_ADDREF(WebGLExtensionStandardDerivatives)
    1291               0 : NS_IMPL_RELEASE(WebGLExtensionStandardDerivatives)
    1292                 : 
    1293                 : DOMCI_DATA(WebGLExtensionStandardDerivatives, WebGLExtensionStandardDerivatives)
    1294                 : 
    1295               0 : NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
    1296               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
    1297               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
    1298               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
    1299               0 : NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
    1300                 : 
    1301               0 : NS_IMPL_ADDREF(WebGLExtensionTextureFilterAnisotropic)
    1302               0 : NS_IMPL_RELEASE(WebGLExtensionTextureFilterAnisotropic)
    1303                 : 
    1304                 : DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, WebGLExtensionTextureFilterAnisotropic)
    1305                 : 
    1306               0 : NS_IMPL_ADDREF(WebGLExtensionLoseContext)
    1307               0 : NS_IMPL_RELEASE(WebGLExtensionLoseContext)
    1308                 : 
    1309                 : DOMCI_DATA(WebGLExtensionLoseContext, WebGLExtensionLoseContext)
    1310                 : 
    1311               0 : NS_INTERFACE_MAP_BEGIN(WebGLExtensionLoseContext)
    1312               0 :   NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionLoseContext)
    1313               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
    1314               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionLoseContext)
    1315               0 : NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
    1316                 : 
    1317                 : /* readonly attribute WebGLsizei drawingBufferWidth; */
    1318                 : NS_IMETHODIMP
    1319               0 : WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
    1320                 : {
    1321               0 :     if (!IsContextStable())
    1322               0 :         return NS_OK;
    1323                 : 
    1324               0 :     *aWidth = mWidth;
    1325               0 :     return NS_OK;
    1326                 : }
    1327                 : 
    1328                 : /* readonly attribute WebGLsizei drawingBufferHeight; */
    1329                 : NS_IMETHODIMP
    1330               0 : WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight)
    1331                 : {
    1332               0 :     if (!IsContextStable())
    1333               0 :         return NS_OK;
    1334                 : 
    1335               0 :     *aHeight = mHeight;
    1336               0 :     return NS_OK;
    1337                 : }
    1338                 : 
    1339                 : /* [noscript] attribute WebGLint location; */
    1340                 : NS_IMETHODIMP
    1341               0 : WebGLUniformLocation::GetLocation(WebGLint *aLocation)
    1342                 : {
    1343               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1344                 : }
    1345                 : 
    1346                 : NS_IMETHODIMP
    1347               0 : WebGLUniformLocation::SetLocation(WebGLint aLocation)
    1348                 : {
    1349               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1350                 : }
    1351                 : 
    1352                 : /* readonly attribute WebGLint size; */
    1353                 : NS_IMETHODIMP
    1354               0 : WebGLActiveInfo::GetSize(WebGLint *aSize)
    1355                 : {
    1356               0 :     *aSize = mSize;
    1357               0 :     return NS_OK;
    1358                 : }
    1359                 : 
    1360                 : /* readonly attribute WebGLenum type; */
    1361                 : NS_IMETHODIMP
    1362               0 : WebGLActiveInfo::GetType(WebGLenum *aType)
    1363                 : {
    1364               0 :     *aType = mType;
    1365               0 :     return NS_OK;
    1366                 : }
    1367                 : 
    1368                 : /* readonly attribute DOMString name; */
    1369                 : NS_IMETHODIMP
    1370               0 : WebGLActiveInfo::GetName(nsAString & aName)
    1371                 : {
    1372               0 :     aName = mName;
    1373               0 :     return NS_OK;
    1374                 : }
    1375                 : 
    1376                 : /* readonly attribute WebGLint rangeMin */
    1377                 : NS_IMETHODIMP
    1378               0 : WebGLShaderPrecisionFormat::GetRangeMin(WebGLint *aRangeMin)
    1379                 : {
    1380               0 :     *aRangeMin = mRangeMin;
    1381               0 :     return NS_OK;
    1382                 : }
    1383                 : 
    1384                 : /* readonly attribute WebGLint rangeMax */
    1385                 : NS_IMETHODIMP
    1386               0 : WebGLShaderPrecisionFormat::GetRangeMax(WebGLint *aRangeMax)
    1387                 : {
    1388               0 :     *aRangeMax = mRangeMax;
    1389               0 :     return NS_OK;
    1390                 : }
    1391                 : 
    1392                 : /* readonly attribute WebGLint precision */
    1393                 : NS_IMETHODIMP
    1394               0 : WebGLShaderPrecisionFormat::GetPrecision(WebGLint *aPrecision)
    1395                 : {
    1396               0 :     *aPrecision = mPrecision;
    1397               0 :     return NS_OK;
    1398                 : }
    1399                 : 
    1400                 : NS_IMETHODIMP
    1401               0 : WebGLContext::GetSupportedExtensions(nsIVariant **retval)
    1402                 : {
    1403               0 :     *retval = nsnull;
    1404               0 :     if (!IsContextStable())
    1405               0 :         return NS_OK;
    1406                 :     
    1407               0 :     if (mDisableExtensions) {
    1408               0 :         return NS_OK;
    1409                 :     }
    1410                 :     
    1411               0 :     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
    1412               0 :     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
    1413                 : 
    1414               0 :     nsTArray<const char *> extList;
    1415                 : 
    1416               0 :     if (IsExtensionSupported(WebGL_OES_texture_float))
    1417               0 :         extList.InsertElementAt(extList.Length(), "OES_texture_float");
    1418               0 :     if (IsExtensionSupported(WebGL_OES_standard_derivatives))
    1419               0 :         extList.InsertElementAt(extList.Length(), "OES_standard_derivatives");
    1420               0 :     if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
    1421               0 :         extList.InsertElementAt(extList.Length(), "MOZ_EXT_texture_filter_anisotropic");
    1422               0 :     if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
    1423               0 :         extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context");
    1424                 : 
    1425                 :     nsresult rv;
    1426               0 :     if (extList.Length() > 0) {
    1427               0 :         rv = wrval->SetAsArray(nsIDataType::VTYPE_CHAR_STR, nsnull,
    1428               0 :                                extList.Length(), &extList[0]);
    1429                 :     } else {
    1430               0 :         rv = wrval->SetAsEmptyArray();
    1431                 :     }
    1432               0 :     if (NS_FAILED(rv))
    1433               0 :         return rv;
    1434                 : 
    1435               0 :     *retval = wrval.forget().get();
    1436               0 :     return NS_OK;
    1437                 : }
    1438                 : 
    1439                 : NS_IMETHODIMP
    1440               0 : WebGLContext::IsContextLost(WebGLboolean *retval)
    1441                 : {
    1442               0 :     *retval = mContextStatus != ContextStable;
    1443               0 :     return NS_OK;
    1444                 : }
    1445                 : 
    1446                 : // Internalized version of IsContextLost.
    1447                 : bool
    1448               0 : WebGLContext::IsContextStable()
    1449                 : {
    1450               0 :     return mContextStatus == ContextStable;
    1451            4392 : }

Generated by: LCOV version 1.7