2009-09-02 17:47:49 -07:00
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2010-05-17 21:04:22 -07:00
/* ***** BEGIN LICENSE BLOCK *****
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is mozilla . org code .
*
* The Initial Developer of the Original Code is
* Mozilla Corporation .
* Portions created by the Initial Developer are Copyright ( C ) 2009
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
* Vladimir Vukicevic < vladimir @ pobox . com > ( original author )
* Mark Steele < mwsteele @ gmail . com >
*
* Alternatively , the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later ( the " GPL " ) , or
* the GNU Lesser General Public License Version 2.1 or later ( the " LGPL " ) ,
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above . If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL , and not to allow others to
* use your version of this file under the terms of the MPL , indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL . If you do not delete
* the provisions above , a recipient may use your version of this file under
* the terms of any one of the MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
2009-09-02 17:47:49 -07:00
# include "WebGLContext.h"
2011-09-30 21:45:50 -07:00
# include "WebGLExtensions.h"
2009-09-02 17:47:49 -07:00
# include "nsIConsoleService.h"
# include "nsServiceManagerUtils.h"
# include "nsIClassInfoImpl.h"
# include "nsContentUtils.h"
2009-11-01 16:33:39 -08:00
# include "nsIXPConnect.h"
2009-09-17 23:01:07 -07:00
# include "nsDOMError.h"
2010-09-16 09:45:23 -07:00
# include "nsIGfxInfo.h"
2009-09-02 17:47:49 -07:00
2010-11-16 20:33:03 -08:00
# include "nsIPropertyBag.h"
# include "nsIVariant.h"
2010-11-16 20:33:03 -08:00
# include "imgIEncoder.h"
2009-09-02 17:47:49 -07:00
# include "gfxContext.h"
# include "gfxPattern.h"
2010-07-01 09:43:33 -07:00
# include "gfxUtils.h"
2009-09-02 17:47:49 -07:00
2009-11-01 16:33:39 -08:00
# include "CanvasUtils.h"
2011-03-27 16:59:47 -07:00
# include "nsDisplayList.h"
2009-11-01 16:33:39 -08:00
2010-05-17 21:04:22 -07:00
# include "GLContextProvider.h"
2011-03-02 12:50:36 -08:00
# include "gfxCrashReporterUtils.h"
2010-08-13 06:36:13 -07:00
# include "nsSVGEffects.h"
2010-08-06 22:09:18 -07:00
# include "prenv.h"
2011-07-06 19:00:02 -07:00
# include "mozilla/Preferences.h"
2011-09-19 13:08:56 -07:00
# include "mozilla/Telemetry.h"
2011-07-06 19:00:02 -07:00
2009-09-02 17:47:49 -07:00
using namespace mozilla ;
2010-05-17 21:04:22 -07:00
using namespace mozilla : : gl ;
2010-09-02 02:18:40 -07:00
using namespace mozilla : : layers ;
2009-09-02 17:47:49 -07:00
2011-07-07 17:01:12 -07:00
WebGLMemoryReporter * WebGLMemoryReporter : : sUniqueInstance = nsnull ;
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLTextureMemoryUsed ,
" webgl-texture-memory " ,
KIND_OTHER ,
UNITS_BYTES ,
WebGLMemoryReporter : : GetTextureMemoryUsed ,
2011-07-07 17:01:16 -07:00
" Memory used by WebGL textures. The OpenGL implementation is free to store these textures in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided. " )
2011-07-07 17:01:12 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLTextureCount ,
" webgl-texture-count " ,
KIND_OTHER ,
UNITS_COUNT ,
WebGLMemoryReporter : : GetTextureCount ,
" Number of WebGL textures. " )
2011-07-07 17:01:15 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLBufferMemoryUsed ,
" webgl-buffer-memory " ,
KIND_OTHER ,
UNITS_BYTES ,
WebGLMemoryReporter : : GetBufferMemoryUsed ,
2011-07-07 17:01:16 -07:00
" Memory used by WebGL buffers. The OpenGL implementation is free to store these buffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided. " )
2011-07-07 17:01:15 -07:00
2011-07-07 17:01:16 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLBufferCacheMemoryUsed ,
2011-07-27 11:46:15 -07:00
" explicit/webgl/buffer-cache-memory " ,
2011-07-07 17:01:16 -07:00
KIND_HEAP ,
UNITS_BYTES ,
WebGLMemoryReporter : : GetBufferCacheMemoryUsed ,
" Memory used by WebGL buffer caches. The WebGL implementation caches the contents of element array buffers only. This adds up with the webgl-buffer-memory value, but contrary to it, this one represents bytes on the heap, not managed by OpenGL. " )
2011-07-07 17:01:15 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLBufferCount ,
" webgl-buffer-count " ,
KIND_OTHER ,
UNITS_COUNT ,
WebGLMemoryReporter : : GetBufferCount ,
" Number of WebGL buffers. " )
2011-07-07 17:01:16 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLRenderbufferMemoryUsed ,
" webgl-renderbuffer-memory " ,
KIND_OTHER ,
UNITS_BYTES ,
WebGLMemoryReporter : : GetRenderbufferMemoryUsed ,
" Memory used by WebGL renderbuffers. The OpenGL implementation is free to store these renderbuffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided. " )
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLRenderbufferCount ,
" webgl-renderbuffer-count " ,
KIND_OTHER ,
UNITS_COUNT ,
WebGLMemoryReporter : : GetRenderbufferCount ,
" Number of WebGL renderbuffers. " )
2011-07-07 17:01:16 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLShaderSourcesSize ,
2011-07-27 11:46:15 -07:00
" explicit/webgl/shader-sources-size " ,
2011-07-07 17:01:16 -07:00
KIND_HEAP ,
UNITS_BYTES ,
WebGLMemoryReporter : : GetShaderSourcesSize ,
" Combined size of WebGL shader ASCII sources, cached on the heap. This should always be at most a few kilobytes, or dozen kilobytes for very shader-intensive WebGL demos. " )
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLShaderTranslationLogsSize ,
2011-07-27 11:46:15 -07:00
" explicit/webgl/shader-translationlogs-size " ,
2011-07-07 17:01:16 -07:00
KIND_HEAP ,
UNITS_BYTES ,
WebGLMemoryReporter : : GetShaderTranslationLogsSize ,
" Combined size of WebGL shader ASCII translation logs, cached on the heap. " )
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLShaderCount ,
" webgl-shader-count " ,
KIND_OTHER ,
UNITS_COUNT ,
WebGLMemoryReporter : : GetShaderCount ,
" Number of WebGL shaders. " )
2011-07-07 17:01:12 -07:00
NS_MEMORY_REPORTER_IMPLEMENT ( WebGLContextCount ,
" webgl-context-count " ,
KIND_OTHER ,
UNITS_COUNT ,
WebGLMemoryReporter : : GetContextCount ,
" Number of WebGL contexts. " )
WebGLMemoryReporter * WebGLMemoryReporter : : UniqueInstance ( )
{
if ( ! sUniqueInstance ) {
sUniqueInstance = new WebGLMemoryReporter ;
}
return sUniqueInstance ;
}
WebGLMemoryReporter : : WebGLMemoryReporter ( )
: mTextureMemoryUsageReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLTextureMemoryUsed ) )
, mTextureCountReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLTextureCount ) )
2011-07-07 17:01:15 -07:00
, mBufferMemoryUsageReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLBufferMemoryUsed ) )
2011-07-07 17:01:16 -07:00
, mBufferCacheMemoryUsageReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLBufferCacheMemoryUsed ) )
2011-07-07 17:01:15 -07:00
, mBufferCountReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLBufferCount ) )
2011-07-07 17:01:16 -07:00
, mRenderbufferMemoryUsageReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLRenderbufferMemoryUsed ) )
, mRenderbufferCountReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLRenderbufferCount ) )
2011-07-07 17:01:16 -07:00
, mShaderSourcesSizeReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLShaderSourcesSize ) )
, mShaderTranslationLogsSizeReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLShaderTranslationLogsSize ) )
, mShaderCountReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLShaderCount ) )
2011-07-07 17:01:12 -07:00
, mContextCountReporter ( new NS_MEMORY_REPORTER_NAME ( WebGLContextCount ) )
{
NS_RegisterMemoryReporter ( mTextureMemoryUsageReporter ) ;
NS_RegisterMemoryReporter ( mTextureCountReporter ) ;
2011-07-07 17:01:15 -07:00
NS_RegisterMemoryReporter ( mBufferMemoryUsageReporter ) ;
2011-07-07 17:01:16 -07:00
NS_RegisterMemoryReporter ( mBufferCacheMemoryUsageReporter ) ;
2011-07-07 17:01:15 -07:00
NS_RegisterMemoryReporter ( mBufferCountReporter ) ;
2011-07-07 17:01:16 -07:00
NS_RegisterMemoryReporter ( mRenderbufferMemoryUsageReporter ) ;
NS_RegisterMemoryReporter ( mRenderbufferCountReporter ) ;
2011-07-07 17:01:16 -07:00
NS_RegisterMemoryReporter ( mShaderSourcesSizeReporter ) ;
NS_RegisterMemoryReporter ( mShaderTranslationLogsSizeReporter ) ;
NS_RegisterMemoryReporter ( mShaderCountReporter ) ;
2011-07-07 17:01:12 -07:00
NS_RegisterMemoryReporter ( mContextCountReporter ) ;
}
WebGLMemoryReporter : : ~ WebGLMemoryReporter ( )
{
NS_UnregisterMemoryReporter ( mTextureMemoryUsageReporter ) ;
NS_UnregisterMemoryReporter ( mTextureCountReporter ) ;
2011-07-07 17:01:15 -07:00
NS_UnregisterMemoryReporter ( mBufferMemoryUsageReporter ) ;
2011-07-07 17:01:16 -07:00
NS_UnregisterMemoryReporter ( mBufferCacheMemoryUsageReporter ) ;
2011-07-07 17:01:15 -07:00
NS_UnregisterMemoryReporter ( mBufferCountReporter ) ;
2011-07-07 17:01:16 -07:00
NS_UnregisterMemoryReporter ( mRenderbufferMemoryUsageReporter ) ;
NS_UnregisterMemoryReporter ( mRenderbufferCountReporter ) ;
2011-07-07 17:01:16 -07:00
NS_UnregisterMemoryReporter ( mShaderSourcesSizeReporter ) ;
NS_UnregisterMemoryReporter ( mShaderTranslationLogsSizeReporter ) ;
NS_UnregisterMemoryReporter ( mShaderCountReporter ) ;
2011-07-07 17:01:12 -07:00
NS_UnregisterMemoryReporter ( mContextCountReporter ) ;
}
2010-11-16 20:33:04 -08:00
nsresult NS_NewCanvasRenderingContextWebGL ( nsIDOMWebGLRenderingContext * * aResult ) ;
2009-09-02 17:47:49 -07:00
nsresult
2010-11-16 20:33:04 -08:00
NS_NewCanvasRenderingContextWebGL ( nsIDOMWebGLRenderingContext * * aResult )
2009-09-02 17:47:49 -07:00
{
2011-09-19 13:08:56 -07:00
Telemetry : : Accumulate ( Telemetry : : CANVAS_WEBGL_USED , 1 ) ;
2010-11-16 20:33:04 -08:00
nsIDOMWebGLRenderingContext * ctx = new WebGLContext ( ) ;
2009-09-02 17:47:49 -07:00
if ( ! ctx )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( * aResult = ctx ) ;
return NS_OK ;
}
WebGLContext : : WebGLContext ( )
2010-05-17 21:04:22 -07:00
: mCanvasElement ( nsnull ) ,
2011-05-20 12:53:53 -07:00
gl ( nsnull )
2009-09-02 17:47:49 -07:00
{
2010-07-14 20:52:34 -07:00
mWidth = mHeight = 0 ;
mGeneration = 0 ;
2011-10-17 07:59:28 -07:00
mInvalidated = false ;
mResetLayer = true ;
mVerbose = false ;
mOptionsFrozen = false ;
2010-07-14 20:52:34 -07:00
mActiveTexture = 0 ;
2011-07-07 17:01:16 -07:00
mWebGLError = LOCAL_GL_NO_ERROR ;
2011-10-17 07:59:28 -07:00
mPixelStoreFlipY = false ;
mPixelStorePremultiplyAlpha = false ;
2010-12-06 03:34:35 -08:00
mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL ;
2010-07-14 20:52:34 -07:00
2011-10-17 07:59:28 -07:00
mShaderValidation = true ;
2010-07-14 20:52:34 -07:00
2011-10-17 07:59:28 -07:00
mBlackTexturesAreInitialized = false ;
2010-08-23 14:03:53 -07:00
mFakeBlackStatus = DoNotNeedFakeBlack ;
2010-09-02 07:34:08 -07:00
mVertexAttrib0Vector [ 0 ] = 0 ;
mVertexAttrib0Vector [ 1 ] = 0 ;
mVertexAttrib0Vector [ 2 ] = 0 ;
mVertexAttrib0Vector [ 3 ] = 1 ;
2011-02-24 14:17:34 -08:00
mFakeVertexAttrib0BufferObjectVector [ 0 ] = 0 ;
mFakeVertexAttrib0BufferObjectVector [ 1 ] = 0 ;
mFakeVertexAttrib0BufferObjectVector [ 2 ] = 0 ;
mFakeVertexAttrib0BufferObjectVector [ 3 ] = 1 ;
mFakeVertexAttrib0BufferObjectSize = 0 ;
mFakeVertexAttrib0BufferObject = 0 ;
mFakeVertexAttrib0BufferStatus = VertexAttrib0Status : : Default ;
2011-05-20 12:53:53 -07:00
// these are de default values, see 6.2 State tables in the OpenGL ES 2.0.25 spec
mColorWriteMask [ 0 ] = 1 ;
mColorWriteMask [ 1 ] = 1 ;
mColorWriteMask [ 2 ] = 1 ;
mColorWriteMask [ 3 ] = 1 ;
mDepthWriteMask = 1 ;
mColorClearValue [ 0 ] = 0.f ;
mColorClearValue [ 1 ] = 0.f ;
mColorClearValue [ 2 ] = 0.f ;
mColorClearValue [ 3 ] = 0.f ;
mDepthClearValue = 1.f ;
mStencilClearValue = 0 ;
2011-05-20 12:53:53 -07:00
mStencilRefFront = 0 ;
mStencilRefBack = 0 ;
mStencilValueMaskFront = 0xffffffff ;
mStencilValueMaskBack = 0xffffffff ;
mStencilWriteMaskFront = 0xffffffff ;
mStencilWriteMaskBack = 0xffffffff ;
2011-05-20 12:53:53 -07:00
mScissorTestEnabled = 0 ;
mDitherEnabled = 1 ;
2011-05-20 12:53:53 -07:00
mBackbufferClearingStatus = BackbufferClearingStatus : : NotClearedSinceLastPresented ;
2011-06-27 10:27:04 -07:00
// initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
// so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
mGLMaxVertexAttribs = 0 ;
mGLMaxTextureUnits = 0 ;
mGLMaxTextureSize = 0 ;
mGLMaxCubeMapTextureSize = 0 ;
mGLMaxTextureImageUnits = 0 ;
mGLMaxVertexTextureImageUnits = 0 ;
mGLMaxVaryingVectors = 0 ;
mGLMaxFragmentUniformVectors = 0 ;
mGLMaxVertexUniformVectors = 0 ;
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
mPixelStorePackAlignment = 4 ;
mPixelStoreUnpackAlignment = 4 ;
2011-10-26 13:00:44 -07:00
2011-07-07 17:01:12 -07:00
WebGLMemoryReporter : : AddWebGLContext ( this ) ;
2011-10-26 13:00:44 -07:00
2012-01-04 13:12:03 -08:00
mAllowRestore = true ;
2011-11-18 19:57:29 -08:00
mRobustnessTimerRunning = false ;
mDrawSinceRobustnessTimerSet = false ;
mContextRestorer = do_CreateInstance ( " @mozilla.org/timer;1 " ) ;
2012-01-04 13:12:03 -08:00
mContextStatus = ContextStable ;
mContextLostErrorSet = false ;
mContextLostDueToTest = false ;
2009-09-02 17:47:49 -07:00
}
WebGLContext : : ~ WebGLContext ( )
{
2010-07-18 22:01:14 -07:00
DestroyResourcesAndContext ( ) ;
2011-07-07 17:01:12 -07:00
WebGLMemoryReporter : : RemoveWebGLContext ( this ) ;
2011-11-18 19:57:29 -08:00
TerminateRobustnessTimer ( ) ;
mContextRestorer = nsnull ;
2010-07-18 22:01:14 -07:00
}
void
WebGLContext : : DestroyResourcesAndContext ( )
{
if ( ! gl )
return ;
gl - > MakeCurrent ( ) ;
2011-12-04 11:15:42 -08:00
mBound2DTextures . Clear ( ) ;
mBoundCubeMapTextures . Clear ( ) ;
mBoundArrayBuffer = nsnull ;
mBoundElementArrayBuffer = nsnull ;
mCurrentProgram = nsnull ;
mBoundFramebuffer = nsnull ;
mBoundRenderbuffer = nsnull ;
mAttribBuffers . Clear ( ) ;
2011-12-04 11:15:43 -08:00
while ( mTextures . Length ( ) )
mTextures . Last ( ) - > DeleteOnce ( ) ;
2011-12-04 11:15:43 -08:00
while ( mBuffers . Length ( ) )
mBuffers . Last ( ) - > DeleteOnce ( ) ;
2011-12-04 11:15:43 -08:00
while ( mRenderbuffers . Length ( ) )
mRenderbuffers . Last ( ) - > DeleteOnce ( ) ;
2011-12-04 11:15:43 -08:00
while ( mFramebuffers . Length ( ) )
mFramebuffers . Last ( ) - > DeleteOnce ( ) ;
2011-12-04 11:15:43 -08:00
while ( mShaders . Length ( ) )
mShaders . Last ( ) - > DeleteOnce ( ) ;
2011-12-04 11:15:43 -08:00
while ( mPrograms . Length ( ) )
mPrograms . Last ( ) - > DeleteOnce ( ) ;
2011-12-04 11:15:43 -08:00
while ( mUniformLocations . Length ( ) )
mUniformLocations . Last ( ) - > DeleteOnce ( ) ;
2010-07-18 22:01:14 -07:00
2010-08-23 14:03:53 -07:00
if ( mBlackTexturesAreInitialized ) {
gl - > fDeleteTextures ( 1 , & mBlackTexture2D ) ;
gl - > fDeleteTextures ( 1 , & mBlackTextureCubeMap ) ;
2011-10-17 07:59:28 -07:00
mBlackTexturesAreInitialized = false ;
2010-08-23 14:03:53 -07:00
}
2011-02-24 14:17:34 -08:00
if ( mFakeVertexAttrib0BufferObject ) {
gl - > fDeleteBuffers ( 1 , & mFakeVertexAttrib0BufferObject ) ;
}
2010-07-18 22:01:14 -07:00
// We just got rid of everything, so the context had better
// have been going away.
2010-09-13 08:40:01 -07:00
# ifdef DEBUG
2010-07-18 22:01:14 -07:00
printf_stderr ( " --- WebGL context destroyed: %p \n " , gl . get ( ) ) ;
2010-09-13 08:40:01 -07:00
# endif
2010-07-18 22:01:14 -07:00
gl = nsnull ;
2009-09-02 17:47:49 -07:00
}
void
WebGLContext : : Invalidate ( )
{
2011-03-27 16:59:47 -07:00
if ( mInvalidated )
return ;
2009-09-02 17:47:49 -07:00
if ( ! mCanvasElement )
return ;
2010-08-13 06:36:13 -07:00
nsSVGEffects : : InvalidateDirectRenderingObservers ( HTMLCanvasElement ( ) ) ;
2011-10-17 07:59:28 -07:00
mInvalidated = true ;
2011-03-27 16:59:47 -07:00
HTMLCanvasElement ( ) - > InvalidateCanvasContent ( nsnull ) ;
2009-09-02 17:47:49 -07:00
}
2010-06-08 07:34:56 -07:00
/* readonly attribute nsIDOMHTMLCanvasElement canvas; */
NS_IMETHODIMP
WebGLContext : : GetCanvas ( nsIDOMHTMLCanvasElement * * canvas )
{
2010-06-15 14:38:05 -07:00
NS_IF_ADDREF ( * canvas = mCanvasElement ) ;
2010-06-08 07:34:56 -07:00
return NS_OK ;
2009-09-02 17:47:49 -07:00
}
//
// nsICanvasRenderingContextInternal
//
NS_IMETHODIMP
2010-05-17 21:04:22 -07:00
WebGLContext : : SetCanvasElement ( nsHTMLCanvasElement * aParentCanvas )
2009-09-02 17:47:49 -07:00
{
mCanvasElement = aParentCanvas ;
return NS_OK ;
}
2010-11-16 20:33:03 -08:00
static bool
GetBoolFromPropertyBag ( nsIPropertyBag * bag , const char * propName , bool * boolResult )
{
nsCOMPtr < nsIVariant > vv ;
2011-09-28 23:19:26 -07:00
bool bv ;
2010-11-16 20:33:03 -08:00
nsresult rv = bag - > GetProperty ( NS_ConvertASCIItoUTF16 ( propName ) , getter_AddRefs ( vv ) ) ;
if ( NS_FAILED ( rv ) | | ! vv )
return false ;
rv = vv - > GetAsBool ( & bv ) ;
if ( NS_FAILED ( rv ) )
return false ;
* boolResult = bv ? true : false ;
return true ;
}
NS_IMETHODIMP
WebGLContext : : SetContextOptions ( nsIPropertyBag * aOptions )
{
if ( ! aOptions )
return NS_OK ;
WebGLContextOptions newOpts ;
2011-05-20 12:53:53 -07:00
GetBoolFromPropertyBag ( aOptions , " stencil " , & newOpts . stencil ) ;
GetBoolFromPropertyBag ( aOptions , " depth " , & newOpts . depth ) ;
GetBoolFromPropertyBag ( aOptions , " alpha " , & newOpts . alpha ) ;
GetBoolFromPropertyBag ( aOptions , " premultipliedAlpha " , & newOpts . premultipliedAlpha ) ;
GetBoolFromPropertyBag ( aOptions , " antialias " , & newOpts . antialias ) ;
GetBoolFromPropertyBag ( aOptions , " preserveDrawingBuffer " , & newOpts . preserveDrawingBuffer ) ;
2010-11-16 20:33:03 -08:00
// enforce that if stencil is specified, we also give back depth
newOpts . depth | = newOpts . stencil ;
2010-12-03 14:44:01 -08:00
#if 0
2011-05-20 12:53:53 -07:00
LogMessage ( " aaHint: %d stencil: %d depth: %d alpha: %d premult: %d preserve: %d \n " ,
newOpts . antialias ? 1 : 0 ,
2010-11-16 20:33:03 -08:00
newOpts . stencil ? 1 : 0 ,
newOpts . depth ? 1 : 0 ,
newOpts . alpha ? 1 : 0 ,
2011-05-20 12:53:53 -07:00
newOpts . premultipliedAlpha ? 1 : 0 ,
newOpts . preserveDrawingBuffer ? 1 : 0 ) ;
2010-12-03 14:44:01 -08:00
# endif
2010-11-16 20:33:03 -08:00
if ( mOptionsFrozen & & newOpts ! = mOptions ) {
// Error if the options are already frozen, and the ones that were asked for
// aren't the same as what they were originally.
return NS_ERROR_FAILURE ;
}
mOptions = newOpts ;
return NS_OK ;
}
2009-09-02 17:47:49 -07:00
NS_IMETHODIMP
WebGLContext : : SetDimensions ( PRInt32 width , PRInt32 height )
{
2011-06-10 12:02:06 -07:00
/*** early success return cases ***/
2011-03-27 16:59:47 -07:00
if ( mCanvasElement ) {
HTMLCanvasElement ( ) - > InvalidateCanvas ( ) ;
}
2011-05-06 11:44:26 -07:00
if ( gl & & mWidth = = width & & mHeight = = height )
2009-09-02 17:47:49 -07:00
return NS_OK ;
2011-05-19 03:49:18 -07:00
// Zero-sized surfaces can cause problems.
if ( width = = 0 | | height = = 0 ) {
width = 1 ;
height = 1 ;
}
2011-10-19 12:09:57 -07:00
// If we already have a gl context, then we just need to resize it
if ( gl ) {
2011-12-19 15:47:54 -08:00
MakeContextCurrent ( ) ;
2011-10-19 12:09:57 -07:00
gl - > ResizeOffscreen ( gfxIntSize ( width , height ) ) ; // Doesn't matter if it succeeds (soft-fail)
// It's unlikely that we'll get a proper-sized context if we recreate if we didn't on resize
2010-07-18 22:01:14 -07:00
// everything's good, we're done here
2011-10-19 12:09:57 -07:00
mWidth = gl - > OffscreenActualSize ( ) . width ;
mHeight = gl - > OffscreenActualSize ( ) . height ;
2011-10-17 07:59:28 -07:00
mResetLayer = true ;
2011-12-19 15:47:54 -08:00
gl - > ClearSafely ( ) ;
2010-07-18 22:01:14 -07:00
return NS_OK ;
}
2010-06-09 15:07:12 -07:00
2011-06-10 12:02:06 -07:00
/*** end of early success return cases ***/
2011-05-06 11:44:25 -07:00
ScopedGfxFeatureReporter reporter ( " WebGL " ) ;
2011-06-10 12:02:06 -07:00
// At this point we know that the old context is not going to survive, even though we still don't
// know if creating the new context will succeed.
DestroyResourcesAndContext ( ) ;
// Get some prefs for some preferred/overriden things
2011-07-06 19:00:02 -07:00
NS_ENSURE_TRUE ( Preferences : : GetRootBranch ( ) , NS_ERROR_FAILURE ) ;
2011-09-28 23:19:26 -07:00
bool forceOSMesa =
Preferences : : GetBool ( " webgl.force_osmesa " , false ) ;
bool preferEGL =
Preferences : : GetBool ( " webgl.prefer-egl " , false ) ;
2011-12-17 22:00:42 -08:00
# ifdef XP_WIN
2011-09-28 23:19:26 -07:00
bool preferOpenGL =
Preferences : : GetBool ( " webgl.prefer-native-gl " , false ) ;
2011-12-17 22:00:42 -08:00
# endif
2011-09-28 23:19:26 -07:00
bool forceEnabled =
Preferences : : GetBool ( " webgl.force-enabled " , false ) ;
bool disabled =
Preferences : : GetBool ( " webgl.disabled " , false ) ;
bool verbose =
Preferences : : GetBool ( " webgl.verbose " , false ) ;
2011-06-10 12:02:06 -07:00
if ( disabled )
return NS_ERROR_FAILURE ;
mVerbose = verbose ;
2010-07-18 22:01:14 -07:00
// We're going to create an entirely new context. If our
// generation is not 0 right now (that is, if this isn't the first
// context we're creating), we may have to dispatch a context lost
// event.
2010-06-09 15:07:12 -07:00
2010-07-18 22:01:14 -07:00
// If incrementing the generation would cause overflow,
// don't allow it. Allowing this would allow us to use
// resource handles created from older context generations.
if ( ! ( mGeneration + 1 ) . valid ( ) )
return NS_ERROR_FAILURE ; // exit without changing the value of mGeneration
2010-06-09 15:07:12 -07:00
2010-07-18 22:01:14 -07:00
gl : : ContextFormat format ( gl : : ContextFormat : : BasicRGBA32 ) ;
2010-11-16 20:33:03 -08:00
if ( mOptions . depth ) {
format . depth = 24 ;
format . minDepth = 16 ;
}
if ( mOptions . stencil ) {
format . stencil = 8 ;
format . minStencil = 8 ;
}
if ( ! mOptions . alpha ) {
// Select 565; we won't/shouldn't hit this on the desktop,
// but let mobile know we're ok with it.
format . red = 5 ;
format . green = 6 ;
format . blue = 5 ;
format . alpha = 0 ;
format . minAlpha = 0 ;
}
2009-09-02 17:47:49 -07:00
2011-11-03 07:50:40 -07:00
bool forceMSAA =
Preferences : : GetBool ( " webgl.msaa-force " , false ) ;
2011-11-03 07:50:40 -07:00
PRInt32 status ;
nsCOMPtr < nsIGfxInfo > gfxInfo = do_GetService ( " @mozilla.org/gfx/info;1 " ) ;
2011-11-22 11:51:51 -08:00
if ( mOptions . antialias & &
gfxInfo & &
2011-11-03 07:50:40 -07:00
NS_SUCCEEDED ( gfxInfo - > GetFeatureStatus ( nsIGfxInfo : : FEATURE_WEBGL_MSAA , & status ) ) ) {
2011-11-03 07:50:40 -07:00
if ( status = = nsIGfxInfo : : FEATURE_NO_INFO | | forceMSAA ) {
2011-11-03 07:50:40 -07:00
PRUint32 msaaLevel = Preferences : : GetUint ( " webgl.msaa-level " , 2 ) ;
format . samples = msaaLevel * msaaLevel ;
}
2011-10-19 12:09:57 -07:00
}
2010-12-03 14:44:01 -08:00
if ( PR_GetEnv ( " MOZ_WEBGL_PREFER_EGL " ) ) {
2011-10-17 07:59:28 -07:00
preferEGL = true ;
2010-12-03 14:44:01 -08:00
}
2010-08-25 05:14:12 -07:00
2010-09-13 08:53:52 -07:00
// Ask GfxInfo about what we should use
2011-09-28 23:19:26 -07:00
bool useOpenGL = true ;
bool useANGLE = true ;
2010-09-16 09:45:23 -07:00
2011-01-28 18:12:24 -08:00
if ( gfxInfo & & ! forceEnabled ) {
2010-09-20 10:20:45 -07:00
if ( NS_SUCCEEDED ( gfxInfo - > GetFeatureStatus ( nsIGfxInfo : : FEATURE_WEBGL_OPENGL , & status ) ) ) {
2011-01-25 19:21:45 -08:00
if ( status ! = nsIGfxInfo : : FEATURE_NO_INFO ) {
2011-10-17 07:59:28 -07:00
useOpenGL = false ;
2010-09-20 10:20:45 -07:00
}
}
if ( NS_SUCCEEDED ( gfxInfo - > GetFeatureStatus ( nsIGfxInfo : : FEATURE_WEBGL_ANGLE , & status ) ) ) {
2011-01-25 19:21:45 -08:00
if ( status ! = nsIGfxInfo : : FEATURE_NO_INFO ) {
2011-10-17 07:59:28 -07:00
useANGLE = false ;
2010-09-20 10:20:45 -07:00
}
}
2010-09-16 09:45:23 -07:00
}
2010-12-03 14:44:01 -08:00
// allow forcing GL and not EGL/ANGLE
if ( PR_GetEnv ( " MOZ_WEBGL_FORCE_OPENGL " ) ) {
2011-10-17 07:59:28 -07:00
preferEGL = false ;
useANGLE = false ;
useOpenGL = true ;
2010-12-03 14:44:01 -08:00
}
2010-09-13 08:53:52 -07:00
// if we're forcing osmesa, do it first
if ( forceOSMesa ) {
gl = gl : : GLContextProviderOSMesa : : CreateOffscreen ( gfxIntSize ( width , height ) , format ) ;
if ( ! gl | | ! InitAndValidateGL ( ) ) {
2010-11-05 12:57:58 -07:00
LogMessage ( " OSMesa forced, but creating context failed -- aborting! " ) ;
2010-09-13 08:53:52 -07:00
return NS_ERROR_FAILURE ;
2010-08-06 22:09:18 -07:00
}
2010-11-05 12:57:58 -07:00
LogMessage ( " Using software rendering via OSMesa (THIS WILL BE SLOW) " ) ;
2010-09-13 08:53:52 -07:00
}
2010-07-18 22:01:14 -07:00
2010-09-13 08:53:52 -07:00
# ifdef XP_WIN
2010-12-03 14:44:01 -08:00
// if we want EGL, try it now
if ( ! gl & & ( preferEGL | | useANGLE ) & & ! preferOpenGL ) {
2010-09-13 08:53:52 -07:00
gl = gl : : GLContextProviderEGL : : CreateOffscreen ( gfxIntSize ( width , height ) , format ) ;
2011-12-16 14:24:46 -08:00
if ( gl ) {
if ( InitAndValidateGL ( ) ) {
if ( useANGLE ) {
gl - > SetFlushGuaranteesResolve ( true ) ;
}
} else {
2012-01-16 14:07:18 -08:00
LogMessage ( " Error during ANGLE OpenGL ES initialization " ) ;
return NS_ERROR_FAILURE ;
2011-12-16 14:24:46 -08:00
}
2010-08-06 22:09:18 -07:00
}
2010-09-13 08:53:52 -07:00
}
2012-01-16 14:07:18 -08:00
# endif
2010-09-13 08:53:52 -07:00
2012-01-16 14:07:18 -08:00
// try the default provider, whatever that is
2010-09-13 08:53:52 -07:00
if ( ! gl & & useOpenGL ) {
gl = gl : : GLContextProvider : : CreateOffscreen ( gfxIntSize ( width , height ) , format ) ;
if ( gl & & ! InitAndValidateGL ( ) ) {
2012-01-16 14:07:18 -08:00
LogMessage ( " Error during OpenGL initialization " ) ;
return NS_ERROR_FAILURE ;
2010-05-19 13:46:08 -07:00
}
2010-08-06 22:09:18 -07:00
}
2010-11-05 12:57:58 -07:00
// finally, try OSMesa
if ( ! gl ) {
gl = gl : : GLContextProviderOSMesa : : CreateOffscreen ( gfxIntSize ( width , height ) , format ) ;
2012-01-16 14:07:18 -08:00
if ( gl ) {
if ( ! InitAndValidateGL ( ) ) {
LogMessage ( " Error during OSMesa initialization " ) ;
return NS_ERROR_FAILURE ;
} else {
LogMessage ( " Using software rendering via OSMesa (THIS WILL BE SLOW) " ) ;
}
2010-11-05 12:57:58 -07:00
}
}
2010-08-06 22:09:18 -07:00
if ( ! gl ) {
2010-11-05 12:57:58 -07:00
LogMessage ( " Can't get a usable WebGL context " ) ;
2010-08-06 22:09:18 -07:00
return NS_ERROR_FAILURE ;
}
2010-09-13 08:40:01 -07:00
# ifdef DEBUG
2010-08-06 22:09:18 -07:00
printf_stderr ( " --- WebGL context created: %p \n " , gl . get ( ) ) ;
2010-09-13 08:40:01 -07:00
# endif
2010-08-06 22:09:18 -07:00
2009-09-02 17:47:49 -07:00
mWidth = width ;
mHeight = height ;
2011-10-17 07:59:28 -07:00
mResetLayer = true ;
mOptionsFrozen = true ;
2009-09-02 17:47:49 -07:00
2011-11-18 19:57:29 -08:00
mHasRobustness = gl - > HasRobustness ( ) ;
2010-06-04 12:03:37 -07:00
// increment the generation number
2010-07-03 15:32:19 -07:00
+ + mGeneration ;
2009-09-02 17:47:49 -07:00
2010-07-18 22:01:14 -07:00
#if 0
if ( mGeneration > 0 ) {
// XXX dispatch context lost event
}
# endif
2009-09-02 17:47:49 -07:00
MakeContextCurrent ( ) ;
2010-06-04 12:03:37 -07:00
// Make sure that we clear this out, otherwise
// we'll end up displaying random memory
2010-07-18 22:01:14 -07:00
gl - > fBindFramebuffer ( LOCAL_GL_FRAMEBUFFER , gl - > GetOffscreenFBO ( ) ) ;
2011-12-19 15:47:54 -08:00
2009-09-02 17:47:49 -07:00
gl - > fViewport ( 0 , 0 , mWidth , mHeight ) ;
2010-07-18 22:01:14 -07:00
gl - > fClearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
2010-07-21 12:34:26 -07:00
gl - > fClearDepth ( 1.0f ) ;
2010-07-18 22:01:14 -07:00
gl - > fClearStencil ( 0 ) ;
2011-12-19 15:47:54 -08:00
gl - > ClearSafely ( ) ;
2009-09-02 17:47:49 -07:00
2011-03-02 12:50:36 -08:00
reporter . SetSuccessful ( ) ;
2009-09-02 17:47:49 -07:00
return NS_OK ;
}
NS_IMETHODIMP
WebGLContext : : Render ( gfxContext * ctx , gfxPattern : : GraphicsFilter f )
{
2010-05-17 21:04:22 -07:00
if ( ! gl )
2009-09-02 17:47:49 -07:00
return NS_OK ;
2010-05-17 21:04:22 -07:00
nsRefPtr < gfxImageSurface > surf = new gfxImageSurface ( gfxIntSize ( mWidth , mHeight ) ,
gfxASurface : : ImageFormatARGB32 ) ;
if ( surf - > CairoStatus ( ) ! = 0 )
return NS_ERROR_FAILURE ;
2009-09-02 17:47:49 -07:00
2010-10-09 12:44:24 -07:00
gl - > ReadPixelsIntoImageSurface ( 0 , 0 , mWidth , mHeight , surf ) ;
2010-05-17 21:04:22 -07:00
gfxUtils : : PremultiplyImageSurface ( surf ) ;
2009-09-02 17:47:49 -07:00
2010-05-17 21:04:22 -07:00
nsRefPtr < gfxPattern > pat = new gfxPattern ( surf ) ;
pat - > SetFilter ( f ) ;
2009-09-02 17:47:49 -07:00
2010-10-09 12:44:24 -07:00
// Pixels from ReadPixels will be "upside down" compared to
// what cairo wants, so draw with a y-flip and a translte to
// flip them.
gfxMatrix m ;
m . Translate ( gfxPoint ( 0.0 , mHeight ) ) ;
m . Scale ( 1.0 , - 1.0 ) ;
pat - > SetMatrix ( m ) ;
2010-05-17 21:04:22 -07:00
ctx - > NewPath ( ) ;
ctx - > PixelSnappedRectangleAndSetPattern ( gfxRect ( 0 , 0 , mWidth , mHeight ) , pat ) ;
ctx - > Fill ( ) ;
2009-09-02 17:47:49 -07:00
2010-05-17 21:04:22 -07:00
return NS_OK ;
2009-09-02 17:47:49 -07:00
}
NS_IMETHODIMP
WebGLContext : : GetInputStream ( const char * aMimeType ,
const PRUnichar * aEncoderOptions ,
nsIInputStream * * aStream )
{
2010-11-16 20:33:03 -08:00
NS_ASSERTION ( gl , " GetInputStream on invalid context? " ) ;
if ( ! gl )
return NS_ERROR_FAILURE ;
2009-09-02 17:47:49 -07:00
2010-11-16 20:33:03 -08:00
nsRefPtr < gfxImageSurface > surf = new gfxImageSurface ( gfxIntSize ( mWidth , mHeight ) ,
gfxASurface : : ImageFormatARGB32 ) ;
if ( surf - > CairoStatus ( ) ! = 0 )
2009-09-02 17:47:49 -07:00
return NS_ERROR_FAILURE ;
2011-01-31 13:11:04 -08:00
nsRefPtr < gfxContext > tmpcx = new gfxContext ( surf ) ;
// Use Render() to make sure that appropriate y-flip gets applied
nsresult rv = Render ( tmpcx , gfxPattern : : FILTER_NEAREST ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2010-11-16 20:33:03 -08:00
2009-09-02 17:47:49 -07:00
const char encoderPrefix [ ] = " @mozilla.org/image/encoder;2?type= " ;
2010-11-16 20:33:03 -08:00
nsAutoArrayPtr < char > conid ( new char [ strlen ( encoderPrefix ) + strlen ( aMimeType ) + 1 ] ) ;
2009-09-02 17:47:49 -07:00
if ( ! conid )
return NS_ERROR_OUT_OF_MEMORY ;
strcpy ( conid , encoderPrefix ) ;
strcat ( conid , aMimeType ) ;
nsCOMPtr < imgIEncoder > encoder = do_CreateInstance ( conid ) ;
if ( ! encoder )
return NS_ERROR_FAILURE ;
2010-11-16 20:33:03 -08:00
rv = encoder - > InitFromData ( surf - > Data ( ) ,
mWidth * mHeight * 4 ,
mWidth , mHeight ,
surf - > Stride ( ) ,
2009-09-02 17:47:49 -07:00
imgIEncoder : : INPUT_FORMAT_HOSTARGB ,
nsDependentString ( aEncoderOptions ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
return CallQueryInterface ( encoder , aStream ) ;
}
NS_IMETHODIMP
WebGLContext : : GetThebesSurface ( gfxASurface * * surface )
{
2010-05-17 21:04:22 -07:00
return NS_ERROR_NOT_AVAILABLE ;
}
2010-07-15 14:07:46 -07:00
static PRUint8 gWebGLLayerUserData ;
2011-10-31 14:14:12 -07:00
namespace mozilla {
2011-03-27 16:59:47 -07:00
class WebGLContextUserData : public LayerUserData {
public :
WebGLContextUserData ( nsHTMLCanvasElement * aContent )
: mContent ( aContent ) { }
2011-10-31 14:14:12 -07:00
/** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
* so it really is the right place to put actions that have to be performed upon compositing
*/
2011-03-27 16:59:47 -07:00
static void DidTransactionCallback ( void * aData )
{
2011-10-31 14:14:12 -07:00
WebGLContextUserData * userdata = static_cast < WebGLContextUserData * > ( aData ) ;
nsHTMLCanvasElement * canvas = userdata - > mContent ;
WebGLContext * context = static_cast < WebGLContext * > ( canvas - > GetContextAtIndex ( 0 ) ) ;
context - > mBackbufferClearingStatus = BackbufferClearingStatus : : NotClearedSinceLastPresented ;
canvas - > MarkContextClean ( ) ;
2011-03-27 16:59:47 -07:00
}
private :
nsRefPtr < nsHTMLCanvasElement > mContent ;
} ;
2011-10-31 14:14:12 -07:00
} // end namespace mozilla
2010-05-17 21:04:22 -07:00
already_AddRefed < layers : : CanvasLayer >
2011-03-27 16:59:47 -07:00
WebGLContext : : GetCanvasLayer ( nsDisplayListBuilder * aBuilder ,
CanvasLayer * aOldLayer ,
2010-07-15 14:07:46 -07:00
LayerManager * aManager )
2010-05-17 21:04:22 -07:00
{
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
return nsnull ;
2010-07-15 14:07:46 -07:00
if ( ! mResetLayer & & aOldLayer & &
2010-09-02 02:18:39 -07:00
aOldLayer - > HasUserData ( & gWebGLLayerUserData ) ) {
2010-07-15 14:07:46 -07:00
NS_ADDREF ( aOldLayer ) ;
return aOldLayer ;
}
nsRefPtr < CanvasLayer > canvasLayer = aManager - > CreateCanvasLayer ( ) ;
2010-05-17 21:04:22 -07:00
if ( ! canvasLayer ) {
NS_WARNING ( " CreateCanvasLayer returned null! " ) ;
return nsnull ;
2009-09-02 17:47:49 -07:00
}
2011-03-27 16:59:47 -07:00
WebGLContextUserData * userData = nsnull ;
if ( aBuilder - > IsPaintingToWindow ( ) ) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new WebGLContextUserData ( HTMLCanvasElement ( ) ) ;
canvasLayer - > SetDidTransactionCallback (
WebGLContextUserData : : DidTransactionCallback , userData ) ;
}
canvasLayer - > SetUserData ( & gWebGLLayerUserData , userData ) ;
2009-09-02 17:47:49 -07:00
2010-05-17 21:04:22 -07:00
CanvasLayer : : Data data ;
2010-05-19 13:46:08 -07:00
// the gl context may either provide a native PBuffer, in which case we want to initialize
// data with the gl context directly, or may provide a surface to which it renders (this is the case
// of OSMesa contexts), in which case we want to initialize data with that surface.
void * native_surface = gl - > GetNativeData ( gl : : GLContext : : NativeImageSurface ) ;
2010-07-18 22:01:14 -07:00
if ( native_surface ) {
2010-05-19 13:46:08 -07:00
data . mSurface = static_cast < gfxASurface * > ( native_surface ) ;
2010-07-18 22:01:14 -07:00
} else {
data . mGLContext = gl . get ( ) ;
2010-05-19 13:46:08 -07:00
}
2010-05-17 21:04:22 -07:00
data . mSize = nsIntSize ( mWidth , mHeight ) ;
2011-10-17 07:59:28 -07:00
data . mGLBufferIsPremultiplied = mOptions . premultipliedAlpha ? true : false ;
2010-05-17 21:04:22 -07:00
canvasLayer - > Initialize ( data ) ;
2010-09-02 02:18:40 -07:00
PRUint32 flags = gl - > CreationFormat ( ) . alpha = = 0 ? Layer : : CONTENT_OPAQUE : 0 ;
canvasLayer - > SetContentFlags ( flags ) ;
2011-03-27 16:59:46 -07:00
canvasLayer - > Updated ( ) ;
2010-05-17 21:04:22 -07:00
2011-10-17 07:59:28 -07:00
mResetLayer = false ;
2010-05-17 21:04:22 -07:00
return canvasLayer . forget ( ) . get ( ) ;
2009-09-02 17:47:49 -07:00
}
2010-11-16 20:33:03 -08:00
NS_IMETHODIMP
WebGLContext : : GetContextAttributes ( jsval * aResult )
{
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
{
* aResult = OBJECT_TO_JSVAL ( NULL ) ;
return NS_OK ;
}
2010-11-16 20:33:03 -08:00
JSContext * cx = nsContentUtils : : GetCurrentJSContext ( ) ;
if ( ! cx )
return NS_ERROR_FAILURE ;
JSObject * obj = JS_NewObject ( cx , NULL , NULL , NULL ) ;
if ( ! obj )
return NS_ERROR_FAILURE ;
* aResult = OBJECT_TO_JSVAL ( obj ) ;
gl : : ContextFormat cf = gl - > ActualFormat ( ) ;
if ( ! JS_DefineProperty ( cx , obj , " alpha " , cf . alpha > 0 ? JSVAL_TRUE : JSVAL_FALSE ,
NULL , NULL , JSPROP_ENUMERATE ) | |
! JS_DefineProperty ( cx , obj , " depth " , cf . depth > 0 ? JSVAL_TRUE : JSVAL_FALSE ,
NULL , NULL , JSPROP_ENUMERATE ) | |
! JS_DefineProperty ( cx , obj , " stencil " , cf . stencil > 0 ? JSVAL_TRUE : JSVAL_FALSE ,
NULL , NULL , JSPROP_ENUMERATE ) | |
2011-10-19 12:09:57 -07:00
! JS_DefineProperty ( cx , obj , " antialias " , cf . samples > 0 ? JSVAL_TRUE : JSVAL_FALSE ,
2010-11-16 20:33:03 -08:00
NULL , NULL , JSPROP_ENUMERATE ) | |
! JS_DefineProperty ( cx , obj , " premultipliedAlpha " ,
mOptions . premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE ,
2011-05-20 12:53:53 -07:00
NULL , NULL , JSPROP_ENUMERATE ) | |
! JS_DefineProperty ( cx , obj , " preserveDrawingBuffer " ,
mOptions . preserveDrawingBuffer ? JSVAL_TRUE : JSVAL_FALSE ,
2010-11-16 20:33:03 -08:00
NULL , NULL , JSPROP_ENUMERATE ) )
{
* aResult = JSVAL_VOID ;
return NS_ERROR_FAILURE ;
}
return NS_OK ;
}
2010-12-16 12:49:54 -08:00
/* [noscript] DOMString mozGetUnderlyingParamString(in WebGLenum pname); */
NS_IMETHODIMP
WebGLContext : : MozGetUnderlyingParamString ( PRUint32 pname , nsAString & retval )
{
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
return NS_OK ;
2011-10-17 07:59:28 -07:00
retval . SetIsVoid ( true ) ;
2010-12-16 12:49:54 -08:00
MakeContextCurrent ( ) ;
switch ( pname ) {
case LOCAL_GL_VENDOR :
case LOCAL_GL_RENDERER :
case LOCAL_GL_VERSION :
case LOCAL_GL_SHADING_LANGUAGE_VERSION :
case LOCAL_GL_EXTENSIONS : {
const char * s = ( const char * ) gl - > fGetString ( pname ) ;
retval . Assign ( NS_ConvertASCIItoUTF16 ( nsDependentCString ( s ) ) ) ;
}
break ;
default :
return NS_ERROR_INVALID_ARG ;
}
return NS_OK ;
}
2011-08-15 12:53:02 -07:00
bool WebGLContext : : IsExtensionSupported ( WebGLExtensionID ei )
{
2011-09-30 21:45:50 -07:00
bool isSupported ;
switch ( ei ) {
case WebGL_OES_texture_float :
MakeContextCurrent ( ) ;
isSupported = gl - > IsExtensionSupported ( gl - > IsGLES2 ( ) ? GLContext : : OES_texture_float
: GLContext : : ARB_texture_float ) ;
break ;
case WebGL_OES_standard_derivatives :
// We always support this extension.
isSupported = true ;
break ;
2012-01-04 13:12:03 -08:00
case WebGL_MOZ_WEBGL_lose_context :
2011-10-26 13:00:44 -07:00
// We always support this extension.
isSupported = true ;
break ;
2011-09-30 21:45:50 -07:00
default :
isSupported = false ;
2011-08-15 12:53:02 -07:00
}
2011-09-30 21:45:50 -07:00
return isSupported ;
2011-08-15 12:53:02 -07:00
}
2011-05-20 12:53:53 -07:00
NS_IMETHODIMP
WebGLContext : : GetExtension ( const nsAString & aName , nsIWebGLExtension * * retval )
{
* retval = nsnull ;
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
return NS_OK ;
2011-10-13 05:09:22 -07:00
if ( mDisableExtensions ) {
return NS_OK ;
}
2011-05-20 12:53:53 -07:00
// handle simple extensions that don't need custom objects first
WebGLExtensionID ei = WebGLExtensionID_Max ;
if ( aName . EqualsLiteral ( " OES_texture_float " ) ) {
2011-08-15 12:53:02 -07:00
if ( IsExtensionSupported ( WebGL_OES_texture_float ) )
2011-05-20 12:53:53 -07:00
ei = WebGL_OES_texture_float ;
}
2011-09-30 21:45:50 -07:00
else if ( aName . EqualsLiteral ( " OES_standard_derivatives " ) ) {
if ( IsExtensionSupported ( WebGL_OES_standard_derivatives ) )
ei = WebGL_OES_standard_derivatives ;
}
2012-01-04 13:12:03 -08:00
else if ( aName . EqualsLiteral ( " MOZ_WEBGL_lose_context " ) ) {
if ( IsExtensionSupported ( WebGL_MOZ_WEBGL_lose_context ) )
ei = WebGL_MOZ_WEBGL_lose_context ;
2011-10-26 13:00:44 -07:00
}
2011-05-20 12:53:53 -07:00
if ( ei ! = WebGLExtensionID_Max ) {
if ( ! IsExtensionEnabled ( ei ) ) {
2011-09-30 21:45:50 -07:00
switch ( ei ) {
case WebGL_OES_standard_derivatives :
mEnabledExtensions [ ei ] = new WebGLExtensionStandardDerivatives ( this ) ;
break ;
2012-01-04 13:12:03 -08:00
case WebGL_MOZ_WEBGL_lose_context :
2011-10-26 13:00:44 -07:00
mEnabledExtensions [ ei ] = new WebGLExtensionLoseContext ( this ) ;
break ;
2011-09-30 21:45:50 -07:00
// create an extension for any types that don't
// have any additional tokens or methods
default :
mEnabledExtensions [ ei ] = new WebGLExtension ( this ) ;
break ;
}
2011-05-20 12:53:53 -07:00
}
NS_ADDREF ( * retval = mEnabledExtensions [ ei ] ) ;
}
return NS_OK ;
}
2010-12-16 12:49:54 -08:00
2011-05-20 12:53:53 -07:00
void
WebGLContext : : ForceClearFramebufferWithDefaultValues ( PRUint32 mask , const nsIntRect & viewportRect )
{
MakeContextCurrent ( ) ;
2011-09-28 23:19:26 -07:00
bool initializeColorBuffer = 0 ! = ( mask & LOCAL_GL_COLOR_BUFFER_BIT ) ;
bool initializeDepthBuffer = 0 ! = ( mask & LOCAL_GL_DEPTH_BUFFER_BIT ) ;
bool initializeStencilBuffer = 0 ! = ( mask & LOCAL_GL_STENCIL_BUFFER_BIT ) ;
2011-05-20 12:53:53 -07:00
// prepare GL state for clearing
gl - > fDisable ( LOCAL_GL_SCISSOR_TEST ) ;
gl - > fDisable ( LOCAL_GL_DITHER ) ;
gl - > PushViewportRect ( viewportRect ) ;
if ( initializeColorBuffer ) {
gl - > fColorMask ( 1 , 1 , 1 , 1 ) ;
gl - > fClearColor ( 0.f , 0.f , 0.f , 0.f ) ;
}
if ( initializeDepthBuffer ) {
gl - > fDepthMask ( 1 ) ;
gl - > fClearDepth ( 1.0f ) ;
}
if ( initializeStencilBuffer ) {
gl - > fStencilMask ( 0xffffffff ) ;
gl - > fClearStencil ( 0 ) ;
}
// do clear
gl - > fClear ( mask ) ;
// restore GL state after clearing
if ( initializeColorBuffer ) {
gl - > fColorMask ( mColorWriteMask [ 0 ] ,
mColorWriteMask [ 1 ] ,
mColorWriteMask [ 2 ] ,
mColorWriteMask [ 3 ] ) ;
gl - > fClearColor ( mColorClearValue [ 0 ] ,
mColorClearValue [ 1 ] ,
mColorClearValue [ 2 ] ,
mColorClearValue [ 3 ] ) ;
}
if ( initializeDepthBuffer ) {
gl - > fDepthMask ( mDepthWriteMask ) ;
gl - > fClearDepth ( mDepthClearValue ) ;
}
if ( initializeStencilBuffer ) {
2011-05-20 12:53:53 -07:00
gl - > fStencilMaskSeparate ( LOCAL_GL_FRONT , mStencilWriteMaskFront ) ;
gl - > fStencilMaskSeparate ( LOCAL_GL_BACK , mStencilWriteMaskBack ) ;
2011-05-20 12:53:53 -07:00
gl - > fClearStencil ( mStencilClearValue ) ;
}
gl - > PopViewportRect ( ) ;
if ( mDitherEnabled )
gl - > fEnable ( LOCAL_GL_DITHER ) ;
else
gl - > fDisable ( LOCAL_GL_DITHER ) ;
if ( mScissorTestEnabled )
gl - > fEnable ( LOCAL_GL_SCISSOR_TEST ) ;
else
gl - > fDisable ( LOCAL_GL_SCISSOR_TEST ) ;
}
2011-05-20 12:53:53 -07:00
void
WebGLContext : : EnsureBackbufferClearedAsNeeded ( )
{
if ( mOptions . preserveDrawingBuffer )
return ;
NS_ABORT_IF_FALSE ( ! mBoundFramebuffer ,
" EnsureBackbufferClearedAsNeeded must not be called when a FBO is bound " ) ;
if ( mBackbufferClearingStatus ! = BackbufferClearingStatus : : NotClearedSinceLastPresented )
return ;
mBackbufferClearingStatus = BackbufferClearingStatus : : ClearedToDefaultValues ;
ForceClearFramebufferWithDefaultValues ( LOCAL_GL_COLOR_BUFFER_BIT |
LOCAL_GL_DEPTH_BUFFER_BIT |
LOCAL_GL_STENCIL_BUFFER_BIT ,
nsIntRect ( 0 , 0 , mWidth , mHeight ) ) ;
Invalidate ( ) ;
}
2012-01-04 13:12:03 -08:00
// We use this timer for many things. Here are the things that it is activated for:
// 1) If a script is using the MOZ_WEBGL_lose_context extension.
// 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
// CONTEXT_LOST_WEBGL error has been triggered.
// 3) If we are using ANGLE, or anything that supports ARB_robustness, query the
// GPU periodically to see if the reset status bit has been set.
// In all of these situations, we use this timer to send the script context lost
// and restored events asynchronously. For example, if it triggers a context loss,
// the webglcontextlost event will be sent to it the next time the robustness timer
// fires.
// Note that this timer mechanism is not used unless one of these 3 criteria
// are met.
// At a bare minimum, from context lost to context restores, it would take 3
// full timer iterations: detection, webglcontextlost, webglcontextrestored.
2011-10-26 13:00:44 -07:00
NS_IMETHODIMP
WebGLContext : : Notify ( nsITimer * timer )
{
2011-11-18 19:57:29 -08:00
TerminateRobustnessTimer ( ) ;
2012-01-04 13:12:03 -08:00
// If the context has been lost and we're waiting for it to be restored, do
// that now.
if ( mContextStatus = = ContextLostAwaitingEvent ) {
bool defaultAction ;
nsContentUtils : : DispatchTrustedEvent ( HTMLCanvasElement ( ) - > OwnerDoc ( ) ,
( nsIDOMHTMLCanvasElement * ) HTMLCanvasElement ( ) ,
NS_LITERAL_STRING ( " webglcontextlost " ) ,
PR_TRUE ,
PR_TRUE ,
& defaultAction ) ;
// If the script didn't handle the event, we don't allow restores.
if ( defaultAction )
mAllowRestore = false ;
// If the script handled the event and we are allowing restores, then
// mark it to be restored. Otherwise, leave it as context lost
// (unusable).
if ( ! defaultAction & & mAllowRestore ) {
ForceRestoreContext ( ) ;
// Restart the timer so that it will be restored on the next
// callback.
SetupRobustnessTimer ( ) ;
} else {
mContextStatus = ContextLost ;
}
} else if ( mContextStatus = = ContextLostAwaitingRestore ) {
// Try to restore the context. If it fails, try again later.
if ( NS_FAILED ( SetDimensions ( mWidth , mHeight ) ) ) {
SetupRobustnessTimer ( ) ;
return NS_OK ;
}
mContextStatus = ContextStable ;
nsContentUtils : : DispatchTrustedEvent ( HTMLCanvasElement ( ) - > OwnerDoc ( ) ,
( nsIDOMHTMLCanvasElement * ) HTMLCanvasElement ( ) ,
NS_LITERAL_STRING ( " webglcontextrestored " ) ,
PR_TRUE ,
PR_TRUE ) ;
// Set all flags back to the state they were in before the context was
// lost.
mContextLostErrorSet = false ;
mContextLostDueToTest = false ;
mAllowRestore = true ;
}
2011-10-26 13:00:44 -07:00
MaybeRestoreContext ( ) ;
return NS_OK ;
}
void
WebGLContext : : MaybeRestoreContext ( )
{
2012-01-04 13:12:03 -08:00
// Don't try to handle it if we already know it's busted.
if ( mContextStatus ! = ContextStable | | gl = = nsnull )
2011-10-26 13:00:44 -07:00
return ;
2011-12-14 16:57:09 -08:00
bool isEGL = gl - > GetContextType ( ) = = GLContext : : ContextTypeEGL ,
isANGLE = gl - > IsANGLE ( ) ;
2012-01-04 13:12:03 -08:00
// If was lost due to a forced context loss, don't try to handle it.
// Also, we also don't try to handle if if we don't have robustness.
// Note that the code in this function is used only for situations where
// we have an actual context loss, and not a simulated one.
if ( mContextLostDueToTest | |
( ! mHasRobustness & & ! isEGL ) )
return ;
2011-12-02 23:52:35 -08:00
GLContext : : ContextResetARB resetStatus = GLContext : : CONTEXT_NO_ERROR ;
if ( mHasRobustness ) {
gl - > MakeCurrent ( ) ;
resetStatus = ( GLContext : : ContextResetARB ) gl - > fGetGraphicsResetStatus ( ) ;
2011-12-14 16:57:09 -08:00
} else if ( isEGL ) {
2011-12-02 23:52:35 -08:00
// Simulate a ARB_robustness guilty context loss for when we
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
// but we can't make any distinction, so we must assume the worst
// case.
if ( ! gl - > MakeCurrent ( true ) & & gl - > IsContextLost ( ) ) {
resetStatus = GLContext : : CONTEXT_GUILTY_CONTEXT_RESET_ARB ;
}
}
2011-10-26 13:00:44 -07:00
if ( resetStatus ! = GLContext : : CONTEXT_NO_ERROR ) {
// It's already lost, but clean up after it and signal to JS that it is
// lost.
ForceLoseContext ( ) ;
}
switch ( resetStatus ) {
case GLContext : : CONTEXT_NO_ERROR :
2011-11-18 19:57:29 -08:00
// If there has been activity since the timer was set, it's possible
// that we did or are going to miss something, so clear this flag and
// run it again some time later.
if ( mDrawSinceRobustnessTimerSet )
SetupRobustnessTimer ( ) ;
2012-01-04 13:12:03 -08:00
break ;
2011-10-26 13:00:44 -07:00
case GLContext : : CONTEXT_GUILTY_CONTEXT_RESET_ARB :
NS_WARNING ( " WebGL content on the page caused the graphics card to reset; not restoring the context " ) ;
2012-01-04 13:12:03 -08:00
mAllowRestore = false ;
break ;
2011-10-26 13:00:44 -07:00
case GLContext : : CONTEXT_INNOCENT_CONTEXT_RESET_ARB :
break ;
case GLContext : : CONTEXT_UNKNOWN_CONTEXT_RESET_ARB :
NS_WARNING ( " WebGL content on the page might have caused the graphics card to reset " ) ;
2011-12-14 16:57:09 -08:00
if ( isEGL & & isANGLE ) {
// If we're using ANGLE, we ONLY get back UNKNOWN context resets, including for guilty contexts.
// This means that we can't restore it or risk restoring a guilty context. Should this ever change,
// we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the
// only use for it. See ANGLE issue 261.
2012-01-04 13:12:03 -08:00
mAllowRestore = false ;
2011-12-14 16:57:09 -08:00
}
2011-10-26 13:00:44 -07:00
break ;
}
}
void
WebGLContext : : ForceLoseContext ( )
{
2012-01-04 13:12:03 -08:00
mContextStatus = ContextLostAwaitingEvent ;
// Queue up a task to restore the event.
SetupRobustnessTimer ( ) ;
2011-10-26 13:00:44 -07:00
DestroyResourcesAndContext ( ) ;
}
void
WebGLContext : : ForceRestoreContext ( )
{
2012-01-04 13:12:03 -08:00
mContextStatus = ContextLostAwaitingRestore ;
2011-10-26 13:00:44 -07:00
}
2009-09-02 17:47:49 -07:00
//
// XPCOM goop
//
2011-03-06 03:11:31 -08:00
NS_IMPL_CYCLE_COLLECTING_ADDREF ( WebGLContext )
NS_IMPL_CYCLE_COLLECTING_RELEASE ( WebGLContext )
2010-06-15 14:38:05 -07:00
NS_IMPL_CYCLE_COLLECTION_CLASS ( WebGLContext )
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN ( WebGLContext )
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR ( mCanvasElement )
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN ( WebGLContext )
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR ( mCanvasElement )
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
2009-09-02 17:47:49 -07:00
2010-12-13 14:09:19 -08:00
DOMCI_DATA ( WebGLRenderingContext , WebGLContext )
2010-01-12 05:08:43 -08:00
2010-06-15 14:38:05 -07:00
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION ( WebGLContext )
2010-11-16 20:33:04 -08:00
NS_INTERFACE_MAP_ENTRY ( nsIDOMWebGLRenderingContext )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_ENTRY ( nsICanvasRenderingContextInternal )
NS_INTERFACE_MAP_ENTRY ( nsISupportsWeakReference )
2011-10-26 13:00:44 -07:00
NS_INTERFACE_MAP_ENTRY ( nsITimerCallback )
2010-11-16 20:33:04 -08:00
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , nsIDOMWebGLRenderingContext )
2010-12-13 14:09:19 -08:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLRenderingContext )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( WebGLBuffer )
NS_IMPL_RELEASE ( WebGLBuffer )
2010-01-12 05:08:43 -08:00
DOMCI_DATA ( WebGLBuffer , WebGLBuffer )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLBuffer )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLBuffer )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
2010-03-17 08:09:05 -07:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLBuffer )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( WebGLTexture )
NS_IMPL_RELEASE ( WebGLTexture )
2010-01-12 05:08:43 -08:00
DOMCI_DATA ( WebGLTexture , WebGLTexture )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLTexture )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLTexture )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
2010-03-17 08:09:05 -07:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLTexture )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( WebGLProgram )
NS_IMPL_RELEASE ( WebGLProgram )
2010-01-12 05:08:43 -08:00
DOMCI_DATA ( WebGLProgram , WebGLProgram )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLProgram )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLProgram )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
2010-03-17 08:09:05 -07:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLProgram )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( WebGLShader )
NS_IMPL_RELEASE ( WebGLShader )
2010-01-12 05:08:43 -08:00
DOMCI_DATA ( WebGLShader , WebGLShader )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLShader )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLShader )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
2010-03-17 08:09:05 -07:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLShader )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( WebGLFramebuffer )
NS_IMPL_RELEASE ( WebGLFramebuffer )
2010-01-12 05:08:43 -08:00
DOMCI_DATA ( WebGLFramebuffer , WebGLFramebuffer )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLFramebuffer )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLFramebuffer )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
2010-03-17 08:09:05 -07:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLFramebuffer )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( WebGLRenderbuffer )
NS_IMPL_RELEASE ( WebGLRenderbuffer )
2010-01-12 05:08:43 -08:00
DOMCI_DATA ( WebGLRenderbuffer , WebGLRenderbuffer )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLRenderbuffer )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLRenderbuffer )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
2010-03-17 08:09:05 -07:00
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLRenderbuffer )
2009-09-02 17:47:49 -07:00
NS_INTERFACE_MAP_END
2010-06-01 23:09:19 -07:00
NS_IMPL_ADDREF ( WebGLUniformLocation )
NS_IMPL_RELEASE ( WebGLUniformLocation )
2009-09-02 17:47:49 -07:00
2010-06-01 23:09:19 -07:00
DOMCI_DATA ( WebGLUniformLocation , WebGLUniformLocation )
2009-09-02 17:47:49 -07:00
2010-06-01 23:09:19 -07:00
NS_INTERFACE_MAP_BEGIN ( WebGLUniformLocation )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLUniformLocation )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLUniformLocation )
NS_INTERFACE_MAP_END
2009-09-02 17:47:49 -07:00
2011-12-16 13:11:59 -08:00
NS_IMPL_ADDREF ( WebGLShaderPrecisionFormat )
NS_IMPL_RELEASE ( WebGLShaderPrecisionFormat )
DOMCI_DATA ( WebGLShaderPrecisionFormat , WebGLShaderPrecisionFormat )
NS_INTERFACE_MAP_BEGIN ( WebGLShaderPrecisionFormat )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLShaderPrecisionFormat )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLShaderPrecisionFormat )
NS_INTERFACE_MAP_END
2010-08-23 14:03:49 -07:00
NS_IMPL_ADDREF ( WebGLActiveInfo )
NS_IMPL_RELEASE ( WebGLActiveInfo )
DOMCI_DATA ( WebGLActiveInfo , WebGLActiveInfo )
NS_INTERFACE_MAP_BEGIN ( WebGLActiveInfo )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLActiveInfo )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLActiveInfo )
NS_INTERFACE_MAP_END
2010-05-28 15:52:39 -07:00
# define NAME_NOT_SUPPORTED(base) \
NS_IMETHODIMP base : : GetName ( WebGLuint * aName ) \
{ return NS_ERROR_NOT_IMPLEMENTED ; } \
NS_IMETHODIMP base : : SetName ( WebGLuint aName ) \
{ return NS_ERROR_NOT_IMPLEMENTED ; }
NAME_NOT_SUPPORTED ( WebGLTexture )
NAME_NOT_SUPPORTED ( WebGLBuffer )
NAME_NOT_SUPPORTED ( WebGLProgram )
NAME_NOT_SUPPORTED ( WebGLShader )
NAME_NOT_SUPPORTED ( WebGLFramebuffer )
NAME_NOT_SUPPORTED ( WebGLRenderbuffer )
2010-06-01 23:09:19 -07:00
2011-05-20 12:53:53 -07:00
NS_IMPL_ADDREF ( WebGLExtension )
NS_IMPL_RELEASE ( WebGLExtension )
DOMCI_DATA ( WebGLExtension , WebGLExtension )
NS_INTERFACE_MAP_BEGIN ( WebGLExtension )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLExtension )
NS_INTERFACE_MAP_ENTRY ( nsISupports )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLExtension )
NS_INTERFACE_MAP_END
2011-09-30 21:45:50 -07:00
NS_IMPL_ADDREF ( WebGLExtensionStandardDerivatives )
NS_IMPL_RELEASE ( WebGLExtensionStandardDerivatives )
DOMCI_DATA ( WebGLExtensionStandardDerivatives , WebGLExtensionStandardDerivatives )
NS_INTERFACE_MAP_BEGIN ( WebGLExtensionStandardDerivatives )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLExtensionStandardDerivatives )
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , WebGLExtension )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLExtensionStandardDerivatives )
NS_INTERFACE_MAP_END_INHERITING ( WebGLExtension )
2011-10-26 13:00:44 -07:00
NS_IMPL_ADDREF ( WebGLExtensionLoseContext )
NS_IMPL_RELEASE ( WebGLExtensionLoseContext )
DOMCI_DATA ( WebGLExtensionLoseContext , WebGLExtensionLoseContext )
NS_INTERFACE_MAP_BEGIN ( WebGLExtensionLoseContext )
NS_INTERFACE_MAP_ENTRY ( nsIWebGLExtensionLoseContext )
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , WebGLExtension )
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO ( WebGLExtensionLoseContext )
NS_INTERFACE_MAP_END_INHERITING ( WebGLExtension )
2011-09-01 12:28:34 -07:00
/* readonly attribute WebGLsizei drawingBufferWidth; */
NS_IMETHODIMP
WebGLContext : : GetDrawingBufferWidth ( WebGLsizei * aWidth )
{
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
return NS_OK ;
2011-09-01 12:28:34 -07:00
* aWidth = mWidth ;
return NS_OK ;
}
/* readonly attribute WebGLsizei drawingBufferHeight; */
NS_IMETHODIMP
WebGLContext : : GetDrawingBufferHeight ( WebGLsizei * aHeight )
{
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
return NS_OK ;
2011-09-01 12:28:34 -07:00
* aHeight = mHeight ;
return NS_OK ;
}
2010-06-01 23:09:19 -07:00
/* [noscript] attribute WebGLint location; */
2010-12-16 12:49:54 -08:00
NS_IMETHODIMP
WebGLUniformLocation : : GetLocation ( WebGLint * aLocation )
2009-09-02 17:47:49 -07:00
{
return NS_ERROR_NOT_IMPLEMENTED ;
}
2010-12-16 12:49:54 -08:00
NS_IMETHODIMP
WebGLUniformLocation : : SetLocation ( WebGLint aLocation )
2009-09-02 17:47:49 -07:00
{
return NS_ERROR_NOT_IMPLEMENTED ;
}
2010-08-23 14:03:49 -07:00
/* readonly attribute WebGLint size; */
2010-12-16 12:49:54 -08:00
NS_IMETHODIMP
WebGLActiveInfo : : GetSize ( WebGLint * aSize )
2010-08-23 14:03:49 -07:00
{
* aSize = mSize ;
return NS_OK ;
}
/* readonly attribute WebGLenum type; */
2010-12-16 12:49:54 -08:00
NS_IMETHODIMP
WebGLActiveInfo : : GetType ( WebGLenum * aType )
2010-08-23 14:03:49 -07:00
{
* aType = mType ;
return NS_OK ;
}
/* readonly attribute DOMString name; */
2010-12-16 12:49:54 -08:00
NS_IMETHODIMP
WebGLActiveInfo : : GetName ( nsAString & aName )
2010-08-23 14:03:49 -07:00
{
aName = mName ;
return NS_OK ;
}
2011-03-01 14:25:22 -08:00
2011-12-16 13:11:59 -08:00
/* readonly attribute WebGLint rangeMin */
NS_IMETHODIMP
WebGLShaderPrecisionFormat : : GetRangeMin ( WebGLint * aRangeMin )
{
* aRangeMin = mRangeMin ;
return NS_OK ;
}
/* readonly attribute WebGLint rangeMax */
NS_IMETHODIMP
WebGLShaderPrecisionFormat : : GetRangeMax ( WebGLint * aRangeMax )
{
* aRangeMax = mRangeMax ;
return NS_OK ;
}
/* readonly attribute WebGLint precision */
NS_IMETHODIMP
WebGLShaderPrecisionFormat : : GetPrecision ( WebGLint * aPrecision )
{
* aPrecision = mPrecision ;
return NS_OK ;
}
2011-03-01 14:25:22 -08:00
NS_IMETHODIMP
WebGLContext : : GetSupportedExtensions ( nsIVariant * * retval )
{
2011-10-13 05:09:22 -07:00
* retval = nsnull ;
2012-01-04 13:12:05 -08:00
if ( ! IsContextStable ( ) )
2011-10-26 13:00:44 -07:00
return NS_OK ;
2011-10-13 05:09:22 -07:00
if ( mDisableExtensions ) {
return NS_OK ;
}
2011-03-01 14:25:22 -08:00
nsCOMPtr < nsIWritableVariant > wrval = do_CreateInstance ( " @mozilla.org/variant;1 " ) ;
NS_ENSURE_TRUE ( wrval , NS_ERROR_FAILURE ) ;
nsTArray < const char * > extList ;
2011-08-15 12:53:02 -07:00
if ( IsExtensionSupported ( WebGL_OES_texture_float ) )
extList . InsertElementAt ( extList . Length ( ) , " OES_texture_float " ) ;
2011-09-30 21:45:50 -07:00
if ( IsExtensionSupported ( WebGL_OES_standard_derivatives ) )
extList . InsertElementAt ( extList . Length ( ) , " OES_standard_derivatives " ) ;
2012-01-04 13:12:03 -08:00
if ( IsExtensionSupported ( WebGL_MOZ_WEBGL_lose_context ) )
extList . InsertElementAt ( extList . Length ( ) , " MOZ_WEBGL_lose_context " ) ;
2011-03-01 14:25:22 -08:00
nsresult rv ;
if ( extList . Length ( ) > 0 ) {
rv = wrval - > SetAsArray ( nsIDataType : : VTYPE_CHAR_STR , nsnull ,
extList . Length ( ) , & extList [ 0 ] ) ;
} else {
rv = wrval - > SetAsEmptyArray ( ) ;
}
if ( NS_FAILED ( rv ) )
return rv ;
* retval = wrval . forget ( ) . get ( ) ;
return NS_OK ;
}
2011-03-01 14:25:22 -08:00
NS_IMETHODIMP
WebGLContext : : IsContextLost ( WebGLboolean * retval )
{
2012-01-04 13:12:03 -08:00
* retval = mContextStatus ! = ContextStable ;
2011-03-01 14:25:22 -08:00
return NS_OK ;
}
2012-01-04 13:12:03 -08:00
// Internalized version of IsContextLost.
bool
WebGLContext : : IsContextStable ( )
{
return mContextStatus = = ContextStable ;
}