LCOV - code coverage report
Current view: directory - gfx/gl - GLContext.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1218 2 0.2 %
Date: 2012-06-02 Functions: 81 2 2.5 %

       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                 :  * the Mozilla Foundation.
      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>
      24                 :  *   Mark Steele <mwsteele@gmail.com>
      25                 :  *   Bas Schouten <bschouten@mozilla.com>
      26                 :  *   Jeff Gilbert <jgilbert@mozilla.com>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      30                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : 
      43                 : #include <string.h>
      44                 : #include <stdio.h>
      45                 : 
      46                 : #include "prlink.h"
      47                 : #include "prenv.h"
      48                 : 
      49                 : #include "nsThreadUtils.h"
      50                 : 
      51                 : #include "gfxPlatform.h"
      52                 : #include "GLContext.h"
      53                 : #include "GLContextProvider.h"
      54                 : 
      55                 : #include "gfxCrashReporterUtils.h"
      56                 : #include "gfxUtils.h"
      57                 : 
      58                 : #include "mozilla/Util.h" // for DebugOnly
      59                 : 
      60                 : namespace mozilla {
      61                 : namespace gl {
      62                 : 
      63                 : #ifdef DEBUG
      64                 : PRUintn GLContext::sCurrentGLContextTLS = -1;
      65                 : #endif
      66                 : 
      67                 : PRUint32 GLContext::sDebugMode = 0;
      68                 : 
      69                 : // define this here since it's global to GLContextProvider, not any
      70                 : // specific implementation
      71            1464 : const ContextFormat ContextFormat::BasicRGBA32Format(ContextFormat::BasicRGBA32);
      72                 : 
      73                 : #define MAX_SYMBOL_LENGTH 128
      74                 : #define MAX_SYMBOL_NAMES 5
      75                 : 
      76                 : // should match the order of GLExtensions
      77                 : static const char *sExtensionNames[] = {
      78                 :     "GL_EXT_framebuffer_object",
      79                 :     "GL_ARB_framebuffer_object",
      80                 :     "GL_ARB_texture_rectangle",
      81                 :     "GL_EXT_bgra",
      82                 :     "GL_EXT_texture_format_BGRA8888",
      83                 :     "GL_OES_depth24",
      84                 :     "GL_OES_depth32",
      85                 :     "GL_OES_stencil8",
      86                 :     "GL_OES_texture_npot",
      87                 :     "GL_OES_depth_texture",
      88                 :     "GL_OES_packed_depth_stencil",
      89                 :     "GL_IMG_read_format",
      90                 :     "GL_EXT_read_format_bgra",
      91                 :     "GL_APPLE_client_storage",
      92                 :     "GL_ARB_texture_non_power_of_two",
      93                 :     "GL_ARB_pixel_buffer_object",
      94                 :     "GL_ARB_ES2_compatibility",
      95                 :     "GL_OES_texture_float",
      96                 :     "GL_ARB_texture_float",
      97                 :     "GL_EXT_unpack_subimage",
      98                 :     "GL_OES_standard_derivatives",
      99                 :     "GL_EXT_texture_filter_anisotropic",
     100                 :     "GL_EXT_framebuffer_blit",
     101                 :     "GL_ANGLE_framebuffer_blit",
     102                 :     "GL_EXT_framebuffer_multisample",
     103                 :     "GL_ANGLE_framebuffer_multisample",
     104                 :     "GL_OES_rgb8_rgba8",
     105                 :     "GL_ARB_robustness",
     106                 :     "GL_EXT_robustness",
     107                 :     NULL
     108                 : };
     109                 : 
     110                 : bool
     111               0 : LibrarySymbolLoader::OpenLibrary(const char *library)
     112                 : {
     113                 :     PRLibSpec lspec;
     114               0 :     lspec.type = PR_LibSpec_Pathname;
     115               0 :     lspec.value.pathname = library;
     116                 : 
     117               0 :     mLibrary = PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL);
     118               0 :     if (!mLibrary)
     119               0 :         return false;
     120                 : 
     121               0 :     return true;
     122                 : }
     123                 : 
     124                 : bool
     125               0 : LibrarySymbolLoader::LoadSymbols(SymLoadStruct *firstStruct, bool tryplatform, const char *prefix)
     126                 : {
     127               0 :     return LoadSymbols(mLibrary, firstStruct, tryplatform ? mLookupFunc : nsnull, prefix);
     128                 : }
     129                 : 
     130                 : PRFuncPtr
     131               0 : LibrarySymbolLoader::LookupSymbol(PRLibrary *lib,
     132                 :                                   const char *sym,
     133                 :                                   PlatformLookupFunction lookupFunction)
     134                 : {
     135               0 :     PRFuncPtr res = 0;
     136                 : 
     137                 :     // try finding it in the library directly, if we have one
     138               0 :     if (lib) {
     139               0 :         res = PR_FindFunctionSymbol(lib, sym);
     140                 :     }
     141                 : 
     142                 :     // then try looking it up via the lookup symbol
     143               0 :     if (!res && lookupFunction) {
     144               0 :         res = lookupFunction(sym);
     145                 :     }
     146                 : 
     147                 :     // finally just try finding it in the process
     148               0 :     if (!res) {
     149                 :         PRLibrary *leakedLibRef;
     150               0 :         res = PR_FindFunctionSymbolAndLibrary(sym, &leakedLibRef);
     151                 :     }
     152                 : 
     153               0 :     return res;
     154                 : }
     155                 : 
     156                 : bool
     157               0 : LibrarySymbolLoader::LoadSymbols(PRLibrary *lib,
     158                 :                                  SymLoadStruct *firstStruct,
     159                 :                                  PlatformLookupFunction lookupFunction,
     160                 :                                  const char *prefix)
     161                 : {
     162                 :     char sbuf[MAX_SYMBOL_LENGTH * 2];
     163               0 :     int failCount = 0;
     164                 : 
     165               0 :     SymLoadStruct *ss = firstStruct;
     166               0 :     while (ss->symPointer) {
     167               0 :         *ss->symPointer = 0;
     168                 : 
     169               0 :         for (int i = 0; i < MAX_SYMBOL_NAMES; i++) {
     170               0 :             if (ss->symNames[i] == nsnull)
     171               0 :                 break;
     172                 : 
     173               0 :             const char *s = ss->symNames[i];
     174               0 :             if (prefix && *prefix != 0) {
     175               0 :                 strcpy(sbuf, prefix);
     176               0 :                 strcat(sbuf, ss->symNames[i]);
     177               0 :                 s = sbuf;
     178                 :             }
     179                 : 
     180               0 :             PRFuncPtr p = LookupSymbol(lib, s, lookupFunction);
     181               0 :             if (p) {
     182               0 :                 *ss->symPointer = p;
     183               0 :                 break;
     184                 :             }
     185                 :         }
     186                 : 
     187               0 :         if (*ss->symPointer == 0) {
     188               0 :             fprintf (stderr, "Can't find symbol '%s'\n", ss->symNames[0]);
     189               0 :             failCount++;
     190                 :         }
     191                 : 
     192               0 :         ss++;
     193                 :     }
     194                 : 
     195               0 :     return failCount == 0 ? true : false;
     196                 : }
     197                 : 
     198                 : /*
     199                 :  * XXX - we should really know the ARB/EXT variants of these
     200                 :  * instead of only handling the symbol if it's exposed directly.
     201                 :  */
     202                 : 
     203                 : bool
     204               0 : GLContext::InitWithPrefix(const char *prefix, bool trygl)
     205                 : {
     206               0 :     ScopedGfxFeatureReporter reporter("GL Context");
     207                 : 
     208               0 :     if (mInitialized) {
     209               0 :         reporter.SetSuccessful();
     210               0 :         return true;
     211                 :     }
     212                 : 
     213                 :     SymLoadStruct symbols[] = {
     214                 :         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", NULL } },
     215                 :         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", NULL } },
     216                 :         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", NULL } },
     217                 :         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", NULL } },
     218                 :         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", NULL } },
     219                 :         { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", NULL } },
     220                 :         { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", NULL } },
     221                 :         { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", NULL } },
     222                 :         { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", NULL } },
     223                 :         { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", NULL } },
     224                 :         { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", NULL } },
     225                 :         { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", NULL } },
     226                 :         { (PRFuncPtr*) &mSymbols.fClear, { "Clear", NULL } },
     227                 :         { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", NULL } },
     228                 :         { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", NULL } },
     229                 :         { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", NULL } },
     230                 :         { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", NULL } },
     231                 :         { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", NULL } },
     232                 :         { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", NULL } },
     233                 :         { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", NULL } },
     234                 :         { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", NULL } },
     235                 :         { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", NULL } },
     236                 :         { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", NULL } },
     237                 :         { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", NULL } },
     238                 :         { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", NULL } },
     239                 :         { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", NULL } },
     240                 :         { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", NULL } },
     241                 :         { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", NULL } },
     242                 :         { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", NULL } },
     243                 :         { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", NULL } },
     244                 :         { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", NULL } },
     245                 :         { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", NULL } },
     246                 :         { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", NULL } },
     247                 :         { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", NULL } },
     248                 :         { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", NULL } },
     249                 :         { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", NULL } },
     250                 :         { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", NULL } },
     251                 :         { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", NULL } },
     252                 :         { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", NULL } },
     253                 :         { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", NULL } },
     254                 :         { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", NULL } },
     255                 :         { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", NULL } },
     256                 :         { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", NULL } },
     257                 :         { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", NULL } },
     258                 :         { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", NULL } },
     259                 :         { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", NULL } },
     260                 :         { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", NULL } },
     261                 :         { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", NULL } },
     262                 :         { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", NULL } },
     263                 :         { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", NULL } },
     264                 :         { (PRFuncPtr*) &mSymbols.fHint, { "Hint", NULL } },
     265                 :         { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", NULL } },
     266                 :         { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", NULL } },
     267                 :         { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", NULL } },
     268                 :         { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", NULL } },
     269                 :         { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", NULL } },
     270                 :         { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", NULL } },
     271                 :         { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", NULL } },
     272                 :         { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", NULL } },
     273                 :         { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", NULL } },
     274                 :         { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", NULL } },
     275                 :         { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", NULL } },
     276                 :         { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", NULL } },
     277                 :         { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", NULL } },
     278                 :         { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", NULL } },
     279                 :         { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", NULL } },
     280                 :         { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", NULL } },
     281                 :         { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", NULL } },
     282                 :         { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", NULL } },
     283                 :         { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", NULL } },
     284                 :         { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", NULL } },
     285                 :         { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", NULL } },
     286                 :         { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", NULL } },
     287                 :         { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", NULL } },
     288                 :         { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", NULL } },
     289                 :         { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", NULL } },
     290                 :         { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", NULL } },
     291                 :         { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", NULL } },
     292                 :         { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", NULL } },
     293                 :         { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", NULL } },
     294                 :         { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", NULL } },
     295                 :         { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", NULL } },
     296                 :         { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", NULL } },
     297                 :         { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", NULL } },
     298                 :         { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", NULL } },
     299                 :         { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", NULL } },
     300                 :         { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", NULL } },
     301                 :         { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", NULL } },
     302                 :         { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", NULL } },
     303                 :         { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", NULL } },
     304                 :         { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", NULL } },
     305                 :         { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", NULL } },
     306                 :         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", NULL } },
     307                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", NULL } },
     308                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", NULL } },
     309                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", NULL } },
     310                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", NULL } },
     311                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", NULL } },
     312                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", NULL } },
     313                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", NULL } },
     314                 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", NULL } },
     315                 :         { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", NULL } },
     316                 :         { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", NULL } },
     317                 :         { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", NULL } },
     318                 :         { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", NULL } },
     319                 :         { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", NULL } },
     320                 :         { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", NULL } },
     321                 :         { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", NULL } },
     322                 :         { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", NULL } },
     323                 :         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", NULL } },
     324                 :         { (PRFuncPtr*) &mSymbols.fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", NULL } },
     325                 :         { (PRFuncPtr*) &mSymbols.fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", NULL } },
     326                 :         { (PRFuncPtr*) &mSymbols.fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", NULL } },
     327                 :         { (PRFuncPtr*) &mSymbols.fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", NULL } },
     328                 :         { (PRFuncPtr*) &mSymbols.fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", NULL } },
     329                 :         { (PRFuncPtr*) &mSymbols.fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", NULL } },
     330                 :         { (PRFuncPtr*) &mSymbols.fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", NULL } },
     331                 :         { (PRFuncPtr*) &mSymbols.fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", NULL } },
     332                 :         { (PRFuncPtr*) &mSymbols.fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", NULL } },
     333                 :         { (PRFuncPtr*) &mSymbols.fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", NULL } },
     334                 :         { (PRFuncPtr*) &mSymbols.fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", NULL } },
     335                 : 
     336                 :         { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", NULL } },
     337                 :         { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", NULL } },
     338                 :         { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", NULL } },
     339                 :         { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", NULL } },
     340                 :         { (PRFuncPtr*) &mSymbols.fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", NULL } },
     341                 :         { (PRFuncPtr*) &mSymbols.fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", NULL } },
     342                 : 
     343                 :         { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", NULL } },
     344                 :         { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", NULL } },
     345                 :         { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", NULL } },
     346                 :         { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", NULL } },
     347                 :         { (PRFuncPtr*) &mSymbols.fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", NULL } },
     348                 :         { (PRFuncPtr*) &mSymbols.fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", NULL } },
     349                 : 
     350                 :         { NULL, { NULL } },
     351                 : 
     352               0 :     };
     353                 : 
     354               0 :     mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
     355                 : 
     356                 :     // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
     357               0 :     if (mInitialized) {
     358               0 :         if (mIsGLES2) {
     359                 :             SymLoadStruct symbols_ES2[] = {
     360                 :                 { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", NULL } },
     361                 :                 { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", NULL } },
     362                 :                 { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", NULL } },
     363                 :                 { NULL, { NULL } },
     364               0 :             };
     365                 : 
     366               0 :             if (!LoadSymbols(&symbols_ES2[0], trygl, prefix)) {
     367               0 :                 NS_RUNTIMEABORT("OpenGL ES 2.0 supported, but symbols could not be loaded.");
     368               0 :                 mInitialized = false;
     369                 :             }
     370                 :         } else {
     371                 :             SymLoadStruct symbols_desktop[] = {
     372                 :                 { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", NULL } },
     373                 :                 { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", NULL } },
     374                 :                 { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", NULL } },
     375                 :                 { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", NULL } },
     376                 :                 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", NULL } },
     377                 :                 { NULL, { NULL } },
     378               0 :             };
     379                 : 
     380               0 :             if (!LoadSymbols(&symbols_desktop[0], trygl, prefix)) {
     381               0 :                 NS_RUNTIMEABORT("Desktop symbols failed to load.");
     382               0 :                 mInitialized = false;
     383                 :             }
     384                 :         }
     385                 :     }
     386                 : 
     387                 :     const char *glVendorString;
     388                 :     const char *glRendererString;
     389                 : 
     390               0 :     if (mInitialized) {
     391               0 :         glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
     392                 :         const char *vendorMatchStrings[VendorOther] = {
     393                 :                 "Intel",
     394                 :                 "NVIDIA",
     395                 :                 "ATI",
     396                 :                 "Qualcomm"
     397               0 :         };
     398               0 :         mVendor = VendorOther;
     399               0 :         for (int i = 0; i < VendorOther; ++i) {
     400               0 :             if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
     401               0 :                 mVendor = i;
     402               0 :                 break;
     403                 :             }
     404                 :         }
     405                 : 
     406               0 :         glRendererString = (const char *)fGetString(LOCAL_GL_RENDERER);
     407                 :         const char *rendererMatchStrings[RendererOther] = {
     408                 :                 "Adreno 200"
     409               0 :         };
     410               0 :         mRenderer = RendererOther;
     411               0 :         for (int i = 0; i < RendererOther; ++i) {
     412               0 :             if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
     413               0 :                 mRenderer = i;
     414               0 :                 break;
     415                 :             }
     416                 :         }
     417                 :     }
     418                 : 
     419               0 :     if (mInitialized) {
     420                 : #ifdef DEBUG
     421                 :         static bool once = false;
     422               0 :         if (!once) {
     423                 :             const char *vendors[VendorOther] = {
     424                 :                 "Intel",
     425                 :                 "NVIDIA",
     426                 :                 "ATI",
     427                 :                 "Qualcomm"
     428               0 :             };
     429                 : 
     430               0 :             once = true;
     431               0 :             if (mVendor < VendorOther) {
     432                 :                 printf_stderr("OpenGL vendor ('%s') recognized as: %s\n",
     433               0 :                               glVendorString, vendors[mVendor]);
     434                 :             } else {
     435               0 :                 printf_stderr("OpenGL vendor ('%s') unrecognized\n", glVendorString);
     436                 :             }
     437                 :         }
     438                 : #endif
     439                 : 
     440               0 :         InitExtensions();
     441                 : 
     442               0 :         NS_ASSERTION(!IsExtensionSupported(GLContext::ARB_pixel_buffer_object) ||
     443                 :                      (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
     444                 :                      "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!");
     445                 : 
     446               0 :         if (SupportsRobustness()) {
     447               0 :             if (IsExtensionSupported(ARB_robustness)) {
     448                 :                 SymLoadStruct robustnessSymbols[] = {
     449                 :                     { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", NULL } },
     450                 :                     { NULL, { NULL } },
     451               0 :                 };
     452                 : 
     453               0 :                 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
     454               0 :                     NS_RUNTIMEABORT("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
     455               0 :                     mInitialized = false;
     456                 :                 } else {
     457               0 :                     mHasRobustness = true;
     458                 :                 }
     459               0 :             } else if (IsExtensionSupported(EXT_robustness)) {
     460                 :                 SymLoadStruct robustnessSymbols[] = {
     461                 :                     { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", NULL } },
     462                 :                     { NULL, { NULL } },
     463               0 :                 };
     464                 : 
     465               0 :                 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
     466               0 :                     NS_RUNTIMEABORT("GL supports EGL_robustness without supplying GetGraphicsResetStatusEXT.");
     467               0 :                     mInitialized = false;
     468                 :                 } else {
     469               0 :                     mHasRobustness = true;
     470                 :                 }
     471                 :             }
     472                 :         }
     473                 : 
     474                 :         // Check for aux symbols based on extensions
     475               0 :         if (IsExtensionSupported(GLContext::ANGLE_framebuffer_blit) ||
     476               0 :             IsExtensionSupported(GLContext::EXT_framebuffer_blit)) {
     477                 :             SymLoadStruct auxSymbols[] = {
     478                 :                     { (PRFuncPtr*) &mSymbols.fBlitFramebuffer, { "BlitFramebuffer", "BlitFramebufferEXT", "BlitFramebufferANGLE", NULL } },
     479                 :                     { NULL, { NULL } },
     480               0 :             };
     481               0 :             if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
     482               0 :                 NS_RUNTIMEABORT("GL supports framebuffer_blit without supplying glBlitFramebuffer");
     483               0 :                 mInitialized = false;
     484                 :             }
     485                 :         }
     486                 : 
     487               0 :         if (IsExtensionSupported(GLContext::ANGLE_framebuffer_multisample) ||
     488               0 :             IsExtensionSupported(GLContext::EXT_framebuffer_multisample)) {
     489                 :             SymLoadStruct auxSymbols[] = {
     490                 :                     { (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample, { "RenderbufferStorageMultisample", "RenderbufferStorageMultisampleEXT", "RenderbufferStorageMultisampleANGLE", NULL } },
     491                 :                     { NULL, { NULL } },
     492               0 :             };
     493               0 :             if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
     494               0 :                 NS_RUNTIMEABORT("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample");
     495               0 :                 mInitialized = false;
     496                 :             }
     497                 :         }
     498                 :        
     499                 :         // Load developer symbols, don't fail if we can't find them.
     500                 :         SymLoadStruct auxSymbols[] = {
     501                 :                 { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", NULL } },
     502                 :                 { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", NULL } },
     503                 :                 { NULL, { NULL } },
     504               0 :         };
     505               0 :         LoadSymbols(&auxSymbols[0], trygl, prefix);
     506                 :     }
     507                 : 
     508               0 :     if (mInitialized) {
     509                 :         GLint v[4];
     510                 : 
     511               0 :         fGetIntegerv(LOCAL_GL_SCISSOR_BOX, v);
     512               0 :         mScissorStack.AppendElement(nsIntRect(v[0], v[1], v[2], v[3]));
     513                 : 
     514               0 :         fGetIntegerv(LOCAL_GL_VIEWPORT, v);
     515               0 :         mViewportStack.AppendElement(nsIntRect(v[0], v[1], v[2], v[3]));
     516                 : 
     517               0 :         fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     518               0 :         fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
     519               0 :         fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
     520                 : 
     521                 : #ifdef XP_MACOSX
     522                 :         if (mVendor == VendorIntel) {
     523                 :             // see bug 737182 for 2D textures, bug 684822 for cube map textures.
     524                 :             mMaxTextureSize        = NS_MIN(mMaxTextureSize,        4096);
     525                 :             mMaxCubeMapTextureSize = NS_MIN(mMaxCubeMapTextureSize, 512);
     526                 :             // for good measure, we align renderbuffers on what we do for 2D textures
     527                 :             mMaxRenderbufferSize   = NS_MIN(mMaxRenderbufferSize,   4096);
     528                 :         }
     529                 : #endif
     530                 : 
     531               0 :         mMaxTextureImageSize = mMaxTextureSize;
     532                 : 
     533               0 :         UpdateActualFormat();
     534                 :     }
     535                 : 
     536                 : #ifdef DEBUG
     537               0 :     if (PR_GetEnv("MOZ_GL_DEBUG"))
     538               0 :         sDebugMode |= DebugEnabled;
     539                 : 
     540                 :     // enables extra verbose output, informing of the start and finish of every GL call.
     541                 :     // useful e.g. to record information to investigate graphics system crashes/lockups
     542               0 :     if (PR_GetEnv("MOZ_GL_DEBUG_VERBOSE"))
     543               0 :         sDebugMode |= DebugTrace;
     544                 : 
     545                 :     // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
     546               0 :     if (PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"))
     547               0 :         sDebugMode |= DebugAbortOnError;
     548                 : #endif
     549                 : 
     550               0 :     if (mInitialized)
     551               0 :         reporter.SetSuccessful();
     552                 :     else {
     553                 :         // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
     554               0 :         mSymbols.Zero();
     555               0 :         NS_WARNING("InitWithPrefix failed!");
     556                 :     }
     557                 : 
     558               0 :     return mInitialized;
     559                 : }
     560                 : 
     561                 : void
     562               0 : GLContext::InitExtensions()
     563                 : {
     564               0 :     MakeCurrent();
     565               0 :     const GLubyte *extensions = fGetString(LOCAL_GL_EXTENSIONS);
     566               0 :     if (!extensions)
     567               0 :         return;
     568                 : 
     569               0 :     char *exts = strdup((char *)extensions);
     570                 : 
     571                 : #ifdef DEBUG
     572                 :     static bool once = false;
     573                 : #else
     574                 :     const bool once = true;
     575                 : #endif
     576                 : 
     577               0 :     if (!once) {
     578               0 :         printf_stderr("GL extensions: %s\n", exts);
     579                 :     }
     580                 : 
     581               0 :     char *s = exts;
     582               0 :     bool done = false;
     583               0 :     while (!done) {
     584               0 :         char *space = strchr(s, ' ');
     585               0 :         if (space) {
     586               0 :             *space = '\0';
     587                 :         } else {
     588               0 :             done = true;
     589                 :         }
     590                 : 
     591               0 :         for (int i = 0; sExtensionNames[i]; ++i) {
     592               0 :             if (strcmp(s, sExtensionNames[i]) == 0) {
     593               0 :                 if (!once) {
     594               0 :                     printf_stderr("Found extension %s\n", s);
     595                 :                 }
     596               0 :                 mAvailableExtensions[i] = 1;
     597                 :             }
     598                 :         }
     599                 : 
     600               0 :         s = space+1;
     601                 :     }
     602                 : 
     603               0 :     free(exts);
     604                 : 
     605                 : #ifdef DEBUG
     606               0 :     once = true;
     607                 : #endif
     608                 : }
     609                 : 
     610                 : bool
     611               0 : GLContext::IsExtensionSupported(const char *extension)
     612                 : {
     613               0 :     return ListHasExtension(fGetString(LOCAL_GL_EXTENSIONS), extension);
     614                 : }
     615                 : 
     616                 : bool
     617               0 : GLContext::CanUploadSubTextures()
     618                 : {
     619                 :     // There are certain GPUs that we don't want to use glTexSubImage2D on
     620                 :     // because that function can be very slow and/or buggy
     621                 : 
     622               0 :     return !(Renderer() == RendererAdreno200);
     623                 : }
     624                 : 
     625                 : // Common code for checking for both GL extensions and GLX extensions.
     626                 : bool
     627               0 : GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
     628                 : {
     629                 :     // fix bug 612572 - we were crashing as we were calling this function with extensions==null
     630               0 :     if (extensions == nsnull || extension == nsnull)
     631               0 :         return false;
     632                 : 
     633                 :     const GLubyte *start;
     634                 :     GLubyte *where, *terminator;
     635                 : 
     636                 :     /* Extension names should not have spaces. */
     637               0 :     where = (GLubyte *) strchr(extension, ' ');
     638               0 :     if (where || *extension == '\0')
     639               0 :         return false;
     640                 : 
     641                 :     /* 
     642                 :      * It takes a bit of care to be fool-proof about parsing the
     643                 :      * OpenGL extensions string. Don't be fooled by sub-strings,
     644                 :      * etc. 
     645                 :      */
     646               0 :     start = extensions;
     647               0 :     for (;;) {
     648               0 :         where = (GLubyte *) strstr((const char *) start, extension);
     649               0 :         if (!where) {
     650                 :             break;
     651                 :         }
     652               0 :         terminator = where + strlen(extension);
     653               0 :         if (where == start || *(where - 1) == ' ') {
     654               0 :             if (*terminator == ' ' || *terminator == '\0') {
     655               0 :                 return true;
     656                 :             }
     657                 :         }
     658               0 :         start = terminator;
     659                 :     }
     660               0 :     return false;
     661                 : }
     662                 : 
     663                 : already_AddRefed<TextureImage>
     664               0 : GLContext::CreateTextureImage(const nsIntSize& aSize,
     665                 :                               TextureImage::ContentType aContentType,
     666                 :                               GLenum aWrapMode,
     667                 :                               bool aUseNearestFilter)
     668                 : {
     669               0 :     MakeCurrent();
     670                 : 
     671                 :     GLuint texture;
     672               0 :     fGenTextures(1, &texture);
     673                 : 
     674               0 :     fActiveTexture(LOCAL_GL_TEXTURE0);
     675               0 :     fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
     676                 : 
     677               0 :     GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
     678               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
     679               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
     680               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
     681               0 :     fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
     682                 : 
     683               0 :     return CreateBasicTextureImage(texture, aSize, aWrapMode, aContentType, this);
     684                 : }
     685                 : 
     686               0 : void GLContext::ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter)
     687                 : {
     688               0 :     if (aFilter == gfxPattern::FILTER_NEAREST) {
     689               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
     690               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
     691                 :     } else {
     692               0 :         if (aFilter != gfxPattern::FILTER_GOOD) {
     693               0 :             NS_WARNING("Unsupported filter type!");
     694                 :         }
     695               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
     696               0 :        fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
     697                 :     }
     698               0 : }
     699                 : 
     700               0 : BasicTextureImage::~BasicTextureImage()
     701                 : {
     702               0 :     GLContext *ctx = mGLContext;
     703               0 :     if (ctx->IsDestroyed() || !NS_IsMainThread()) {
     704               0 :         ctx = ctx->GetSharedContext();
     705                 :     }
     706                 : 
     707                 :     // If we have a context, then we need to delete the texture;
     708                 :     // if we don't have a context (either real or shared),
     709                 :     // then they went away when the contex was deleted, because it
     710                 :     // was the only one that had access to it.
     711               0 :     if (ctx && !ctx->IsDestroyed()) {
     712               0 :         mGLContext->MakeCurrent();
     713               0 :         mGLContext->fDeleteTextures(1, &mTexture);
     714                 :     }
     715               0 : }
     716                 : 
     717                 : gfxASurface*
     718               0 : BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
     719                 : {
     720               0 :     NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
     721                 : 
     722                 :     // determine the region the client will need to repaint
     723               0 :     if (mGLContext->CanUploadSubTextures()) {
     724               0 :         GetUpdateRegion(aRegion);
     725                 :     } else {
     726               0 :         aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     727                 :     }
     728                 : 
     729               0 :     mUpdateRegion = aRegion;
     730                 : 
     731               0 :     nsIntRect rgnSize = mUpdateRegion.GetBounds();
     732               0 :     if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
     733               0 :         NS_ERROR("update outside of image");
     734               0 :         return NULL;
     735                 :     }
     736                 : 
     737                 :     ImageFormat format =
     738               0 :         (GetContentType() == gfxASurface::CONTENT_COLOR) ?
     739               0 :         gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
     740                 :     mUpdateSurface =
     741               0 :         GetSurfaceForUpdate(gfxIntSize(rgnSize.width, rgnSize.height), format);
     742                 : 
     743               0 :     if (!mUpdateSurface || mUpdateSurface->CairoStatus()) {
     744               0 :         mUpdateSurface = NULL;
     745               0 :         return NULL;
     746                 :     }
     747                 : 
     748               0 :     mUpdateSurface->SetDeviceOffset(gfxPoint(-rgnSize.x, -rgnSize.y));
     749                 : 
     750               0 :     return mUpdateSurface;
     751                 : }
     752                 : 
     753                 : void
     754               0 : BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
     755                 : {
     756                 :   // if the texture hasn't been initialized yet, or something important
     757                 :   // changed, we need to recreate our backing surface and force the
     758                 :   // client to paint everything
     759               0 :   if (mTextureState != Valid)
     760               0 :       aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     761               0 : }
     762                 : 
     763                 : void
     764               0 : BasicTextureImage::EndUpdate()
     765                 : {
     766               0 :     NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
     767                 : 
     768                 :     // FIXME: this is the slow boat.  Make me fast (with GLXPixmap?).
     769                 : 
     770                 :     // Undo the device offset that BeginUpdate set; doesn't much matter for us here,
     771                 :     // but important if we ever do anything directly with the surface.
     772               0 :     mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
     773                 : 
     774               0 :     bool relative = FinishedSurfaceUpdate();
     775                 : 
     776                 :     mShaderType =
     777                 :         mGLContext->UploadSurfaceToTexture(mUpdateSurface,
     778                 :                                            mUpdateRegion,
     779                 :                                            mTexture,
     780                 :                                            mTextureState == Created,
     781                 :                                            mUpdateOffset,
     782               0 :                                            relative);
     783               0 :     FinishedSurfaceUpload();
     784                 : 
     785               0 :     mUpdateSurface = nsnull;
     786               0 :     mTextureState = Valid;
     787               0 : }
     788                 : 
     789                 : void
     790               0 : BasicTextureImage::BindTexture(GLenum aTextureUnit)
     791                 : {
     792               0 :     mGLContext->fActiveTexture(aTextureUnit);
     793               0 :     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     794               0 :     mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
     795               0 : }
     796                 : 
     797                 : void
     798               0 : BasicTextureImage::ApplyFilter()
     799                 : {
     800               0 :   mGLContext->ApplyFilterToBoundTexture(mFilter);
     801               0 : }
     802                 : 
     803                 : 
     804                 : already_AddRefed<gfxASurface>
     805               0 : BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
     806                 : {
     807               0 :     return gfxPlatform::GetPlatform()->
     808               0 :         CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt));
     809                 : }
     810                 : 
     811                 : bool
     812               0 : BasicTextureImage::FinishedSurfaceUpdate()
     813                 : {
     814               0 :     return false;
     815                 : }
     816                 : 
     817                 : void
     818               0 : BasicTextureImage::FinishedSurfaceUpload()
     819                 : {
     820               0 : }
     821                 : 
     822                 : bool 
     823               0 : BasicTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
     824                 : {
     825               0 :     nsIntRect bounds = aRegion.GetBounds();
     826               0 :     nsIntRegion region;
     827               0 :     if (mTextureState != Valid) {
     828               0 :         bounds = nsIntRect(0, 0, mSize.width, mSize.height);
     829               0 :         region = nsIntRegion(bounds);
     830                 :     } else {
     831               0 :         region = aRegion;
     832                 :     }
     833                 : 
     834                 :     mShaderType =
     835                 :         mGLContext->UploadSurfaceToTexture(aSurf,
     836                 :                                            region,
     837                 :                                            mTexture,
     838                 :                                            mTextureState == Created,
     839                 :                                            bounds.TopLeft() + aFrom,
     840               0 :                                            false);
     841               0 :     mTextureState = Valid;
     842               0 :     return true;
     843                 : }
     844                 : 
     845                 : void
     846               0 : BasicTextureImage::Resize(const nsIntSize& aSize)
     847                 : {
     848               0 :     NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
     849                 : 
     850               0 :     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     851                 : 
     852                 :     mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
     853                 :                             0,
     854                 :                             LOCAL_GL_RGBA,
     855                 :                             aSize.width,
     856                 :                             aSize.height,
     857                 :                             0,
     858                 :                             LOCAL_GL_RGBA,
     859                 :                             LOCAL_GL_UNSIGNED_BYTE,
     860               0 :                             NULL);
     861                 : 
     862               0 :     mTextureState = Allocated;
     863               0 :     mSize = aSize;
     864               0 : }
     865                 : 
     866               0 : TiledTextureImage::TiledTextureImage(GLContext* aGL,
     867                 :                                      nsIntSize aSize,
     868                 :                                      TextureImage::ContentType aContentType,
     869                 :                                      bool aUseNearestFilter)
     870                 :     : TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aUseNearestFilter)
     871                 :     , mCurrentImage(0)
     872                 :     , mInUpdate(false)
     873                 :     , mGL(aGL)
     874                 :     , mUseNearestFilter(aUseNearestFilter)
     875               0 :     , mTextureState(Created)
     876                 : {
     877               0 :     mTileSize = mGL->GetMaxTextureSize();
     878               0 :     if (aSize != nsIntSize(0,0)) {
     879               0 :         Resize(aSize);
     880                 :     }
     881               0 : }
     882                 : 
     883               0 : TiledTextureImage::~TiledTextureImage()
     884                 : {
     885               0 : }
     886                 : 
     887                 : bool 
     888               0 : TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
     889                 : {
     890               0 :     nsIntRegion region;
     891                 : 
     892               0 :     if (mTextureState != Valid) {
     893               0 :         nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
     894               0 :         region = nsIntRegion(bounds);
     895                 :     } else {
     896               0 :         region = aRegion;
     897                 :     }
     898                 : 
     899               0 :     bool result = true;
     900               0 :     for (unsigned i = 0; i < mImages.Length(); i++) {
     901               0 :         int xPos = (i % mColumns) * mTileSize;
     902               0 :         int yPos = (i / mColumns) * mTileSize;
     903               0 :         nsIntRegion tileRegion;
     904               0 :         nsIntRect tileRect = nsIntRect(nsIntPoint(xPos, yPos), mImages[i]->GetSize());
     905               0 :         tileRegion.And(region, tileRect); // intersect with tile
     906               0 :         if (tileRegion.IsEmpty())
     907               0 :             continue;
     908               0 :         if (mGL->CanUploadSubTextures()) {
     909               0 :           tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
     910                 :         } else {
     911                 :           // If sub-textures are unsupported, expand to tile boundaries
     912               0 :           tileRect.x = tileRect.y = 0;
     913               0 :           tileRegion = nsIntRegion(tileRect);
     914                 :         }
     915               0 :         result &= mImages[i]->DirectUpdate(aSurf,
     916                 :                                            tileRegion,
     917               0 :                                            aFrom + nsIntPoint(xPos, yPos));
     918                 :     }
     919               0 :     mShaderType = mImages[0]->GetShaderProgramType();
     920               0 :     mTextureState = Valid;
     921               0 :     return result;
     922                 : }
     923                 : 
     924                 : void
     925               0 : TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
     926                 : {
     927               0 :     if (mTextureState != Valid) {
     928                 :         // if the texture hasn't been initialized yet, or something important
     929                 :         // changed, we need to recreate our backing surface and force the
     930                 :         // client to paint everything
     931               0 :         aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     932               0 :         return;
     933                 :     }
     934                 : 
     935               0 :     nsIntRegion newRegion;
     936                 : 
     937                 :     // We need to query each texture with the region it will be drawing and
     938                 :     // set aForRegion to be the combination of all of these regions
     939               0 :     for (unsigned i = 0; i < mImages.Length(); i++) {
     940               0 :         int xPos = (i % mColumns) * mTileSize;
     941               0 :         int yPos = (i / mColumns) * mTileSize;
     942               0 :         nsIntRect imageRect = nsIntRect(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
     943                 : 
     944               0 :         if (aForRegion.Intersects(imageRect)) {
     945                 :             // Make a copy of the region
     946               0 :             nsIntRegion subRegion;
     947               0 :             subRegion.And(aForRegion, imageRect);
     948                 :             // Translate it into tile-space
     949               0 :             subRegion.MoveBy(-xPos, -yPos);
     950                 :             // Query region
     951               0 :             mImages[i]->GetUpdateRegion(subRegion);
     952                 :             // Translate back
     953               0 :             subRegion.MoveBy(xPos, yPos);
     954                 :             // Add to the accumulated region
     955               0 :             newRegion.Or(newRegion, subRegion);
     956                 :         }
     957                 :     }
     958                 : 
     959               0 :     aForRegion = newRegion;
     960                 : }
     961                 : 
     962                 : gfxASurface*
     963               0 : TiledTextureImage::BeginUpdate(nsIntRegion& aRegion)
     964                 : {
     965               0 :     NS_ASSERTION(!mInUpdate, "nested update");
     966               0 :     mInUpdate = true;
     967                 : 
     968                 :     // Note, we don't call GetUpdateRegion here as if the updated region is
     969                 :     // fully contained in a single tile, we get to avoid iterating through
     970                 :     // the tiles again (and a little copying).
     971               0 :     if (mTextureState != Valid)
     972                 :     {
     973                 :         // if the texture hasn't been initialized yet, or something important
     974                 :         // changed, we need to recreate our backing surface and force the
     975                 :         // client to paint everything
     976               0 :         aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     977                 :     }
     978                 : 
     979               0 :     nsIntRect bounds = aRegion.GetBounds();
     980                 : 
     981               0 :     for (unsigned i = 0; i < mImages.Length(); i++) {
     982               0 :         int xPos = (i % mColumns) * mTileSize;
     983               0 :         int yPos = (i / mColumns) * mTileSize;
     984               0 :         nsIntRegion imageRegion = nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize()));
     985                 : 
     986                 :         // a single Image can handle this update request
     987               0 :         if (imageRegion.Contains(aRegion)) {
     988                 :             // adjust for tile offset
     989               0 :             aRegion.MoveBy(-xPos, -yPos);
     990                 :             // forward the actual call
     991               0 :             nsRefPtr<gfxASurface> surface = mImages[i]->BeginUpdate(aRegion);
     992                 :             // caller expects container space
     993               0 :             aRegion.MoveBy(xPos, yPos);
     994                 :             // Correct the device offset
     995               0 :             gfxPoint offset = surface->GetDeviceOffset();
     996                 :             surface->SetDeviceOffset(gfxPoint(offset.x - xPos,
     997               0 :                                               offset.y - yPos));
     998                 :             // we don't have a temp surface
     999               0 :             mUpdateSurface = nsnull;
    1000                 :             // remember which image to EndUpdate
    1001               0 :             mCurrentImage = i;
    1002               0 :             return surface.get();
    1003                 :         }
    1004                 :     }
    1005                 : 
    1006                 :     // Get the real updated region, taking into account the capabilities of
    1007                 :     // each TextureImage tile
    1008               0 :     GetUpdateRegion(aRegion);
    1009               0 :     mUpdateRegion = aRegion;
    1010               0 :     bounds = aRegion.GetBounds();
    1011                 : 
    1012                 :     // update covers multiple Images - create a temp surface to paint in
    1013                 :     gfxASurface::gfxImageFormat format =
    1014               0 :         (GetContentType() == gfxASurface::CONTENT_COLOR) ?
    1015               0 :         gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32;
    1016               0 :     mUpdateSurface = gfxPlatform::GetPlatform()->
    1017               0 :         CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), gfxASurface::ContentFromFormat(format));
    1018               0 :     mUpdateSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
    1019                 : 
    1020               0 :     return mUpdateSurface;
    1021                 : }
    1022                 : 
    1023                 : void
    1024               0 : TiledTextureImage::EndUpdate()
    1025                 : {
    1026               0 :     NS_ASSERTION(mInUpdate, "EndUpdate not in update");
    1027               0 :     if (!mUpdateSurface) { // update was to a single TextureImage
    1028               0 :         mImages[mCurrentImage]->EndUpdate();
    1029               0 :         mInUpdate = false;
    1030               0 :         mTextureState = Valid;
    1031               0 :         mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
    1032               0 :         return;
    1033                 :     }
    1034                 : 
    1035                 :     // upload tiles from temp surface
    1036               0 :     for (unsigned i = 0; i < mImages.Length(); i++) {
    1037               0 :         int xPos = (i % mColumns) * mTileSize;
    1038               0 :         int yPos = (i / mColumns) * mTileSize;
    1039               0 :         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
    1040                 : 
    1041               0 :         nsIntRegion subregion;
    1042               0 :         subregion.And(mUpdateRegion, imageRect);
    1043               0 :         if (subregion.IsEmpty())
    1044               0 :             continue;
    1045               0 :         subregion.MoveBy(-xPos, -yPos); // Tile-local space
    1046                 :         // copy tile from temp surface
    1047               0 :         gfxASurface* surf = mImages[i]->BeginUpdate(subregion);
    1048               0 :         nsRefPtr<gfxContext> ctx = new gfxContext(surf);
    1049               0 :         gfxUtils::ClipToRegion(ctx, subregion);
    1050               0 :         ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
    1051               0 :         ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
    1052               0 :         ctx->Paint();
    1053               0 :         mImages[i]->EndUpdate();
    1054                 :     }
    1055                 : 
    1056               0 :     mUpdateSurface = nsnull;
    1057               0 :     mInUpdate = false;
    1058               0 :     mShaderType = mImages[0]->GetShaderProgramType();
    1059               0 :     mTextureState = Valid;
    1060                 : }
    1061                 : 
    1062               0 : void TiledTextureImage::BeginTileIteration()
    1063                 : {
    1064               0 :     mCurrentImage = 0;
    1065               0 : }
    1066                 : 
    1067               0 : bool TiledTextureImage::NextTile()
    1068                 : {
    1069               0 :     if (mCurrentImage + 1 < mImages.Length()) {
    1070               0 :         mCurrentImage++;
    1071               0 :         return true;
    1072                 :     }
    1073               0 :     return false;
    1074                 : }
    1075                 : 
    1076               0 : nsIntRect TiledTextureImage::GetTileRect()
    1077                 : {
    1078               0 :     nsIntRect rect = mImages[mCurrentImage]->GetTileRect();
    1079               0 :     unsigned int xPos = (mCurrentImage % mColumns) * mTileSize;
    1080               0 :     unsigned int yPos = (mCurrentImage / mColumns) * mTileSize;
    1081               0 :     rect.MoveBy(xPos, yPos);
    1082                 :     return rect;
    1083                 : }
    1084                 : 
    1085                 : void
    1086               0 : TiledTextureImage::BindTexture(GLenum aTextureUnit)
    1087                 : {
    1088               0 :     mImages[mCurrentImage]->BindTexture(aTextureUnit);
    1089               0 : }
    1090                 : 
    1091                 : void
    1092               0 : TiledTextureImage::ApplyFilter()
    1093                 : {
    1094               0 :    mGL->ApplyFilterToBoundTexture(mFilter);
    1095               0 : }
    1096                 : 
    1097                 : /*
    1098                 :  * simple resize, just discards everything. we can be more clever just
    1099                 :  * adding or discarding tiles, but do we want this?
    1100                 :  */
    1101               0 : void TiledTextureImage::Resize(const nsIntSize& aSize)
    1102                 : {
    1103               0 :     if (mSize == aSize && mTextureState != Created) {
    1104               0 :         return;
    1105                 :     }
    1106               0 :     mSize = aSize;
    1107               0 :     mImages.Clear();
    1108                 :     // calculate rows and columns, rounding up
    1109               0 :     mColumns = (aSize.width  + mTileSize - 1) / mTileSize;
    1110               0 :     mRows    = (aSize.height + mTileSize - 1) / mTileSize;
    1111                 : 
    1112               0 :     for (unsigned int row = 0; row < mRows; row++) {
    1113               0 :       for (unsigned int col = 0; col < mColumns; col++) {
    1114                 :           nsIntSize size( // use tilesize first, then the remainder
    1115                 :                   (col+1) * mTileSize > (unsigned int)aSize.width  ? aSize.width  % mTileSize : mTileSize,
    1116               0 :                   (row+1) * mTileSize > (unsigned int)aSize.height ? aSize.height % mTileSize : mTileSize);
    1117                 :           nsRefPtr<TextureImage> teximg =
    1118               0 :                   mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
    1119               0 :           mImages.AppendElement(teximg.forget());
    1120                 :       }
    1121                 :     }
    1122               0 :     mTextureState = Allocated;
    1123                 : }
    1124                 : 
    1125               0 : PRUint32 TiledTextureImage::GetTileCount()
    1126                 : {
    1127               0 :     return mImages.Length();
    1128                 : }
    1129                 : 
    1130                 : bool
    1131               0 : GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA)
    1132                 : {
    1133               0 :     if (!IsOffscreenSizeAllowed(aSize))
    1134               0 :         return false;
    1135                 : 
    1136               0 :     MakeCurrent();
    1137                 : 
    1138               0 :     const bool alpha = mCreationFormat.alpha > 0;
    1139               0 :     const int depth = mCreationFormat.depth;
    1140               0 :     const int stencil = mCreationFormat.stencil;
    1141               0 :     int samples = mCreationFormat.samples;
    1142                 : 
    1143               0 :     GLint maxSamples = 0;
    1144               0 :     if (SupportsFramebufferMultisample() && !aDisableAA)
    1145               0 :         fGetIntegerv(LOCAL_GL_MAX_SAMPLES, &maxSamples);
    1146                 : 
    1147               0 :     samples = NS_MIN(samples, maxSamples);
    1148                 : 
    1149               0 :     const bool useDrawMSFBO = (samples > 0);
    1150                 : 
    1151               0 :     if (!useDrawMSFBO && !aUseReadFBO) {
    1152                 :         // Early out, as no FBO resize work is necessary.
    1153               0 :         return true;
    1154                 :     }
    1155                 : 
    1156               0 :     GLuint curBoundFramebufferDraw = 0;
    1157               0 :     GLuint curBoundFramebufferRead = 0;
    1158               0 :     GLuint curBoundRenderbuffer = 0;
    1159               0 :     GLuint curBoundTexture = 0;
    1160                 : 
    1161                 :     GLint viewport[4];
    1162                 : 
    1163                 :     const bool useDepthStencil =
    1164               0 :             !mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
    1165                 : 
    1166                 :     // save a few things for later restoring
    1167               0 :     curBoundFramebufferDraw = GetUserBoundDrawFBO();
    1168               0 :     curBoundFramebufferRead = GetUserBoundReadFBO();
    1169               0 :     fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*) &curBoundRenderbuffer);
    1170               0 :     fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
    1171               0 :     fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
    1172                 : 
    1173                 :     // the context format of what we're defining
    1174                 :     // This becomes mActualFormat on success
    1175               0 :     ContextFormat cf(mCreationFormat);
    1176                 : 
    1177                 :     // Create everything we need for the resize, so if it fails, we haven't broken anything
    1178                 :     // If successful, these new resized objects will replace their associated member vars in GLContext
    1179               0 :     GLuint newOffscreenDrawFBO = 0;
    1180               0 :     GLuint newOffscreenReadFBO = 0;
    1181               0 :     GLuint newOffscreenTexture = 0;
    1182               0 :     GLuint newOffscreenColorRB = 0;
    1183               0 :     GLuint newOffscreenDepthRB = 0;
    1184               0 :     GLuint newOffscreenStencilRB = 0;
    1185                 : 
    1186                 :     // Create the buffers and texture
    1187               0 :     if (aUseReadFBO) {
    1188               0 :         fGenFramebuffers(1, &newOffscreenReadFBO);
    1189               0 :         fGenTextures(1, &newOffscreenTexture);
    1190                 :     }
    1191                 : 
    1192               0 :     if (useDrawMSFBO) {
    1193               0 :         fGenFramebuffers(1, &newOffscreenDrawFBO);
    1194               0 :         fGenRenderbuffers(1, &newOffscreenColorRB);
    1195                 :     } else {
    1196               0 :         newOffscreenDrawFBO = newOffscreenReadFBO;
    1197                 :     }
    1198                 : 
    1199               0 :     if (depth && stencil && useDepthStencil) {
    1200               0 :         fGenRenderbuffers(1, &newOffscreenDepthRB);
    1201                 :     } else {
    1202               0 :         if (depth) {
    1203               0 :             fGenRenderbuffers(1, &newOffscreenDepthRB);
    1204                 :         }
    1205                 : 
    1206               0 :         if (stencil) {
    1207               0 :             fGenRenderbuffers(1, &newOffscreenStencilRB);
    1208                 :         }
    1209                 :     }
    1210                 : 
    1211                 :    // Allocate texture
    1212               0 :     if (aUseReadFBO) {
    1213               0 :         fBindTexture(LOCAL_GL_TEXTURE_2D, newOffscreenTexture);
    1214               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
    1215               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
    1216               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
    1217               0 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
    1218                 : 
    1219               0 :         if (alpha) {
    1220                 :             fTexImage2D(LOCAL_GL_TEXTURE_2D,
    1221                 :                         0,
    1222                 :                         LOCAL_GL_RGBA,
    1223                 :                         aSize.width, aSize.height,
    1224                 :                         0,
    1225                 :                         LOCAL_GL_RGBA,
    1226                 :                         LOCAL_GL_UNSIGNED_BYTE,
    1227               0 :                         NULL);
    1228                 : 
    1229               0 :             cf.red = cf.green = cf.blue = cf.alpha = 8;
    1230                 :         } else {
    1231                 :             fTexImage2D(LOCAL_GL_TEXTURE_2D,
    1232                 :                         0,
    1233                 :                         LOCAL_GL_RGB,
    1234                 :                         aSize.width, aSize.height,
    1235                 :                         0,
    1236                 :                         LOCAL_GL_RGB,
    1237                 : #ifdef XP_WIN
    1238                 :                         LOCAL_GL_UNSIGNED_BYTE,
    1239                 : #else
    1240                 :                         mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
    1241                 :                                  : LOCAL_GL_UNSIGNED_BYTE,
    1242                 : #endif
    1243               0 :                         NULL);
    1244                 : 
    1245                 : #ifdef XP_WIN
    1246                 :             cf.red = cf.green = cf.blue = 8;
    1247                 : #else
    1248               0 :             cf.red = 5;
    1249               0 :             cf.green = 6;
    1250               0 :             cf.blue = 5;
    1251                 : #endif
    1252               0 :             cf.alpha = 0;
    1253                 :         }
    1254                 :     }
    1255               0 :     cf.samples = samples;
    1256                 : 
    1257                 :     // Allocate color buffer
    1258               0 :     if (useDrawMSFBO) {
    1259                 :         GLenum colorFormat;
    1260               0 :         if (!mIsGLES2 || IsExtensionSupported(OES_rgb8_rgba8))
    1261               0 :             colorFormat = alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
    1262                 :         else
    1263               0 :             colorFormat = alpha ? LOCAL_GL_RGBA4 : LOCAL_GL_RGB565;
    1264                 : 
    1265               0 :         fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenColorRB);
    1266                 :         fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
    1267                 :                                         samples,
    1268                 :                                         colorFormat,
    1269               0 :                                         aSize.width, aSize.height);
    1270                 :     }
    1271                 : 
    1272                 :     // Allocate depth and stencil buffers
    1273               0 :     if (depth && stencil && useDepthStencil) {
    1274               0 :         fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB);
    1275               0 :         if (useDrawMSFBO) {
    1276                 :             fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
    1277                 :                                             samples,
    1278                 :                                             LOCAL_GL_DEPTH24_STENCIL8,
    1279               0 :                                             aSize.width, aSize.height);
    1280                 :         } else {
    1281                 :             fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
    1282                 :                                  LOCAL_GL_DEPTH24_STENCIL8,
    1283               0 :                                  aSize.width, aSize.height);
    1284                 :         }
    1285               0 :         cf.depth = 24;
    1286               0 :         cf.stencil = 8;
    1287                 :     } else {
    1288               0 :         if (depth) {
    1289                 :             GLenum depthType;
    1290               0 :             if (mIsGLES2) {
    1291               0 :                 if (IsExtensionSupported(OES_depth32)) {
    1292               0 :                     depthType = LOCAL_GL_DEPTH_COMPONENT32;
    1293               0 :                     cf.depth = 32;
    1294               0 :                 } else if (IsExtensionSupported(OES_depth24)) {
    1295               0 :                     depthType = LOCAL_GL_DEPTH_COMPONENT24;
    1296               0 :                     cf.depth = 24;
    1297                 :                 } else {
    1298               0 :                     depthType = LOCAL_GL_DEPTH_COMPONENT16;
    1299               0 :                    cf.depth = 16;
    1300                 :                 }
    1301                 :             } else {
    1302               0 :                 depthType = LOCAL_GL_DEPTH_COMPONENT24;
    1303               0 :                 cf.depth = 24;
    1304                 :             }
    1305                 : 
    1306               0 :             fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB);
    1307               0 :             if (useDrawMSFBO) {
    1308                 :                 fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
    1309                 :                                                 samples,
    1310                 :                                                 depthType,
    1311               0 :                                                 aSize.width, aSize.height);
    1312                 :             } else {
    1313                 :                 fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
    1314                 :                                      depthType,
    1315               0 :                                      aSize.width, aSize.height);
    1316                 :             }
    1317                 :         }
    1318                 : 
    1319               0 :         if (stencil) {
    1320               0 :             fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenStencilRB);
    1321               0 :             if (useDrawMSFBO) {
    1322                 :                 fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
    1323                 :                                                 samples,
    1324                 :                                                 LOCAL_GL_STENCIL_INDEX8,
    1325               0 :                                                 aSize.width, aSize.height);
    1326                 :             } else {
    1327                 :                 fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
    1328                 :                                      LOCAL_GL_STENCIL_INDEX8,
    1329               0 :                                      aSize.width, aSize.height);
    1330                 :             }
    1331               0 :             cf.stencil = 8;
    1332                 :         }
    1333                 :     }
    1334                 : 
    1335                 :     // Now assemble the FBO
    1336               0 :     BindInternalFBO(newOffscreenDrawFBO);    // If we're not using a separate draw FBO, this will be the read FBO
    1337               0 :     if (useDrawMSFBO) {
    1338                 :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1339                 :                                  LOCAL_GL_COLOR_ATTACHMENT0,
    1340                 :                                  LOCAL_GL_RENDERBUFFER,
    1341               0 :                                  newOffscreenColorRB);
    1342                 :     }
    1343                 : 
    1344               0 :     if (depth && stencil && useDepthStencil) {
    1345                 :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1346                 :                                  LOCAL_GL_DEPTH_ATTACHMENT,
    1347                 :                                  LOCAL_GL_RENDERBUFFER,
    1348               0 :                                  newOffscreenDepthRB);
    1349                 :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1350                 :                                  LOCAL_GL_STENCIL_ATTACHMENT,
    1351                 :                                  LOCAL_GL_RENDERBUFFER,
    1352               0 :                                  newOffscreenDepthRB);
    1353                 :     } else {
    1354               0 :         if (depth) {
    1355                 :             fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1356                 :                                      LOCAL_GL_DEPTH_ATTACHMENT,
    1357                 :                                      LOCAL_GL_RENDERBUFFER,
    1358               0 :                                      newOffscreenDepthRB);
    1359                 :         }
    1360                 : 
    1361               0 :         if (stencil) {
    1362                 :             fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1363                 :                                      LOCAL_GL_STENCIL_ATTACHMENT,
    1364                 :                                      LOCAL_GL_RENDERBUFFER,
    1365               0 :                                      newOffscreenStencilRB);
    1366                 :         }
    1367                 :     }
    1368                 : 
    1369               0 :     if (aUseReadFBO) {
    1370               0 :         BindInternalFBO(newOffscreenReadFBO);
    1371                 :         fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    1372                 :                               LOCAL_GL_COLOR_ATTACHMENT0,
    1373                 :                               LOCAL_GL_TEXTURE_2D,
    1374                 :                               newOffscreenTexture,
    1375               0 :                               0);
    1376                 :     }
    1377                 : 
    1378                 :     // We should be all resized.  Check for framebuffer completeness.
    1379                 :     GLenum status;
    1380               0 :     bool framebuffersComplete = true;
    1381                 : 
    1382               0 :     BindInternalFBO(newOffscreenDrawFBO);
    1383               0 :     status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    1384               0 :     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
    1385               0 :         NS_WARNING("DrawFBO: Incomplete");
    1386                 : #ifdef DEBUG
    1387               0 :         printf_stderr("Framebuffer status: %X\n", status);
    1388                 : #endif
    1389               0 :         framebuffersComplete = false;
    1390                 :     }
    1391                 : 
    1392               0 :     BindInternalFBO(newOffscreenReadFBO);
    1393               0 :     status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    1394               0 :     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
    1395               0 :         NS_WARNING("ReadFBO: Incomplete");
    1396                 : #ifdef DEBUG
    1397               0 :         printf_stderr("Framebuffer status: %X\n", status);
    1398                 : #endif
    1399               0 :         framebuffersComplete = false;
    1400                 :     }
    1401                 : 
    1402               0 :     if (!framebuffersComplete) {
    1403               0 :         NS_WARNING("Error resizing offscreen framebuffer -- framebuffer(s) not complete");
    1404                 : 
    1405                 :         // Clean up the mess
    1406               0 :         fDeleteFramebuffers(1, &newOffscreenDrawFBO);
    1407               0 :         fDeleteFramebuffers(1, &newOffscreenReadFBO);
    1408               0 :         fDeleteTextures(1, &newOffscreenTexture);
    1409               0 :         fDeleteRenderbuffers(1, &newOffscreenColorRB);
    1410               0 :         fDeleteRenderbuffers(1, &newOffscreenDepthRB);
    1411               0 :         fDeleteRenderbuffers(1, &newOffscreenStencilRB);
    1412                 : 
    1413               0 :         BindUserDrawFBO(curBoundFramebufferDraw);
    1414               0 :         BindUserReadFBO(curBoundFramebufferRead);
    1415               0 :         fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
    1416               0 :         fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
    1417               0 :         fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
    1418                 : 
    1419               0 :         return false;
    1420                 :     }
    1421                 : 
    1422                 :     // Success, so delete the old and busted
    1423               0 :     fDeleteFramebuffers(1, &mOffscreenDrawFBO);
    1424               0 :     fDeleteFramebuffers(1, &mOffscreenReadFBO);
    1425               0 :     fDeleteTextures(1, &mOffscreenTexture);
    1426               0 :     fDeleteRenderbuffers(1, &mOffscreenColorRB);
    1427               0 :     fDeleteRenderbuffers(1, &mOffscreenDepthRB);
    1428               0 :     fDeleteRenderbuffers(1, &mOffscreenStencilRB);
    1429                 : 
    1430                 :     // Update currently bound references if we're changing what they were point to
    1431                 :     // This way we don't rebind to old buffers when we're done here
    1432               0 :     if (curBoundFramebufferDraw == mOffscreenDrawFBO)
    1433               0 :         curBoundFramebufferDraw = newOffscreenDrawFBO;
    1434               0 :     if (curBoundFramebufferRead == mOffscreenReadFBO)
    1435               0 :         curBoundFramebufferRead = newOffscreenReadFBO;
    1436               0 :     if (curBoundTexture == mOffscreenTexture)
    1437               0 :         curBoundTexture = newOffscreenTexture;
    1438               0 :     if (curBoundRenderbuffer == mOffscreenColorRB)
    1439               0 :         curBoundRenderbuffer = newOffscreenColorRB;
    1440               0 :     else if (curBoundRenderbuffer == mOffscreenDepthRB)
    1441               0 :         curBoundRenderbuffer = newOffscreenDepthRB;
    1442               0 :     else if (curBoundRenderbuffer == mOffscreenStencilRB)
    1443               0 :         curBoundRenderbuffer = newOffscreenStencilRB;
    1444                 : 
    1445                 :     // Replace with the new hotness
    1446               0 :     mOffscreenDrawFBO = newOffscreenDrawFBO;
    1447               0 :     mOffscreenReadFBO = newOffscreenReadFBO;
    1448               0 :     mOffscreenTexture = newOffscreenTexture;
    1449               0 :     mOffscreenColorRB = newOffscreenColorRB;
    1450               0 :     mOffscreenDepthRB = newOffscreenDepthRB;
    1451               0 :     mOffscreenStencilRB = newOffscreenStencilRB;
    1452                 : 
    1453               0 :     mOffscreenSize = aSize;
    1454               0 :     mOffscreenActualSize = aSize;
    1455                 : 
    1456               0 :     mActualFormat = cf;
    1457                 : 
    1458                 : #ifdef DEBUG
    1459               0 :     if (DebugMode()) {
    1460                 :         printf_stderr("Resized %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n",
    1461                 :                       mOffscreenActualSize.width, mOffscreenActualSize.height,
    1462                 :                       mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
    1463               0 :                       mActualFormat.depth, mActualFormat.stencil, mActualFormat.samples);
    1464                 :     }
    1465                 : #endif
    1466                 : 
    1467                 :     // We're good, and the framebuffer is already attached.
    1468                 :     // Now restore the GL state back to what it was before the resize took place.
    1469                 :     // If the user was using fb 0, this will bind the offscreen framebuffer we
    1470                 :     // just created.
    1471               0 :     BindUserDrawFBO(curBoundFramebufferDraw);
    1472               0 :     BindUserReadFBO(curBoundFramebufferRead);
    1473               0 :     fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture);
    1474               0 :     fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer);
    1475               0 :     fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
    1476                 : 
    1477                 :     // Make sure we know that the buffers are new and thus dirty:
    1478               0 :     ForceDirtyFBOs();
    1479                 : 
    1480               0 :     return true;
    1481                 : }
    1482                 : 
    1483                 : void
    1484               0 : GLContext::DeleteOffscreenFBO()
    1485                 : {
    1486               0 :     fDeleteFramebuffers(1, &mOffscreenDrawFBO);
    1487               0 :     fDeleteFramebuffers(1, &mOffscreenReadFBO);
    1488               0 :     fDeleteTextures(1, &mOffscreenTexture);
    1489               0 :     fDeleteRenderbuffers(1, &mOffscreenColorRB);
    1490               0 :     fDeleteRenderbuffers(1, &mOffscreenDepthRB);
    1491               0 :     fDeleteRenderbuffers(1, &mOffscreenStencilRB);
    1492                 : 
    1493               0 :     mOffscreenDrawFBO = 0;
    1494               0 :     mOffscreenReadFBO = 0;
    1495               0 :     mOffscreenTexture = 0;
    1496               0 :     mOffscreenColorRB = 0;
    1497               0 :     mOffscreenDepthRB = 0;
    1498               0 :     mOffscreenStencilRB = 0;
    1499               0 : }
    1500                 : 
    1501                 : void
    1502               0 : GLContext::ClearSafely()
    1503                 : {
    1504                 :     // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
    1505                 :     // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
    1506                 :     //
    1507                 :     // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
    1508                 :     // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
    1509                 :     // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
    1510                 :     // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
    1511                 :     // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
    1512                 : 
    1513                 :     realGLboolean scissorTestEnabled;
    1514                 :     realGLboolean ditherEnabled;
    1515                 :     realGLboolean colorWriteMask[4];
    1516                 :     realGLboolean depthWriteMask;
    1517                 :     GLint stencilWriteMaskFront, stencilWriteMaskBack;
    1518                 :     GLfloat colorClearValue[4];
    1519                 :     GLfloat depthClearValue;
    1520                 :     GLint stencilClearValue;
    1521                 : 
    1522                 :     // save current GL state
    1523               0 :     fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
    1524               0 :     fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
    1525               0 :     fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
    1526               0 :     fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
    1527               0 :     fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
    1528               0 :     fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
    1529               0 :     fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
    1530               0 :     fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
    1531               0 :     fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
    1532                 : 
    1533                 :     // prepare GL state for clearing
    1534               0 :     fDisable(LOCAL_GL_SCISSOR_TEST);
    1535               0 :     fDisable(LOCAL_GL_DITHER);
    1536               0 :     PushViewportRect(nsIntRect(0, 0, mOffscreenSize.width, mOffscreenSize.height));
    1537                 : 
    1538               0 :     fColorMask(1, 1, 1, 1);
    1539               0 :     fClearColor(0.f, 0.f, 0.f, 0.f);
    1540                 : 
    1541               0 :     fDepthMask(1);
    1542               0 :     fClearDepth(1.0f);
    1543                 : 
    1544               0 :     fStencilMask(0xffffffff);
    1545               0 :     fClearStencil(0);
    1546                 : 
    1547                 :     // do clear
    1548                 :     fClear(LOCAL_GL_COLOR_BUFFER_BIT |
    1549                 :            LOCAL_GL_DEPTH_BUFFER_BIT |
    1550               0 :            LOCAL_GL_STENCIL_BUFFER_BIT);
    1551                 : 
    1552                 :     // restore GL state after clearing
    1553               0 :     fColorMask(colorWriteMask[0],
    1554               0 :                colorWriteMask[1],
    1555               0 :                colorWriteMask[2],
    1556               0 :                colorWriteMask[3]);
    1557                 :     fClearColor(colorClearValue[0],
    1558                 :                 colorClearValue[1],
    1559                 :                 colorClearValue[2],
    1560               0 :                 colorClearValue[3]);
    1561                 : 
    1562               0 :     fDepthMask(depthWriteMask);
    1563               0 :     fClearDepth(depthClearValue);
    1564                 : 
    1565               0 :     fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
    1566               0 :     fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
    1567               0 :     fClearStencil(stencilClearValue);
    1568                 : 
    1569               0 :     PopViewportRect();
    1570                 : 
    1571               0 :     if (ditherEnabled)
    1572               0 :         fEnable(LOCAL_GL_DITHER);
    1573                 :     else
    1574               0 :         fDisable(LOCAL_GL_DITHER);
    1575                 : 
    1576               0 :     if (scissorTestEnabled)
    1577               0 :         fEnable(LOCAL_GL_SCISSOR_TEST);
    1578                 :     else
    1579               0 :         fDisable(LOCAL_GL_SCISSOR_TEST);
    1580                 : 
    1581               0 : }
    1582                 : 
    1583                 : void
    1584               0 : GLContext::UpdateActualFormat()
    1585                 : {
    1586               0 :     ContextFormat nf;
    1587                 : 
    1588               0 :     fGetIntegerv(LOCAL_GL_RED_BITS, (GLint*) &nf.red);
    1589               0 :     fGetIntegerv(LOCAL_GL_GREEN_BITS, (GLint*) &nf.green);
    1590               0 :     fGetIntegerv(LOCAL_GL_BLUE_BITS, (GLint*) &nf.blue);
    1591               0 :     fGetIntegerv(LOCAL_GL_ALPHA_BITS, (GLint*) &nf.alpha);
    1592               0 :     fGetIntegerv(LOCAL_GL_DEPTH_BITS, (GLint*) &nf.depth);
    1593               0 :     fGetIntegerv(LOCAL_GL_STENCIL_BITS, (GLint*) &nf.stencil);
    1594                 : 
    1595               0 :     mActualFormat = nf;
    1596               0 : }
    1597                 : 
    1598                 : void
    1599               0 : GLContext::MarkDestroyed()
    1600                 : {
    1601               0 :     if (IsDestroyed())
    1602               0 :         return;
    1603                 : 
    1604               0 :     MakeCurrent();
    1605               0 :     DeleteOffscreenFBO();
    1606                 : 
    1607               0 :     fDeleteProgram(mBlitProgram);
    1608               0 :     mBlitProgram = 0;
    1609               0 :     fDeleteFramebuffers(1, &mBlitFramebuffer);
    1610               0 :     mBlitFramebuffer = 0;
    1611                 : 
    1612               0 :     mSymbols.Zero();
    1613                 : }
    1614                 : 
    1615               0 : static void SwapRAndBComponents(gfxImageSurface* aSurf)
    1616                 : {
    1617               0 :   gfxIntSize size = aSurf->GetSize();
    1618               0 :   for (int j = 0; j < size.height; ++j) {
    1619               0 :     PRUint32 *row = (PRUint32*) (aSurf->Data() + aSurf->Stride() * j);
    1620               0 :     for (int i = 0; i < size.width; ++i) {
    1621               0 :       *row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
    1622               0 :       row++;
    1623                 :     }
    1624                 :   }
    1625               0 : }
    1626                 : 
    1627               0 : static already_AddRefed<gfxImageSurface> YInvertImageSurface(gfxImageSurface* aSurf)
    1628                 : {
    1629               0 :   gfxIntSize size = aSurf->GetSize();
    1630               0 :   nsRefPtr<gfxImageSurface> temp = new gfxImageSurface(size, aSurf->Format());
    1631               0 :   nsRefPtr<gfxContext> ctx = new gfxContext(temp);
    1632               0 :   ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
    1633               0 :   ctx->Scale(1.0, -1.0);
    1634               0 :   ctx->Translate(-gfxPoint(0.0, size.height));
    1635               0 :   ctx->SetSource(aSurf);
    1636               0 :   ctx->Paint();
    1637               0 :   return temp.forget();
    1638                 : }
    1639                 : 
    1640                 : already_AddRefed<gfxImageSurface>
    1641               0 : GLContext::GetTexImage(GLuint aTexture, bool aYInvert, ShaderProgramType aShader)
    1642                 : {
    1643               0 :     MakeCurrent();
    1644               0 :     fFinish();
    1645               0 :     fActiveTexture(LOCAL_GL_TEXTURE0);
    1646               0 :     fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
    1647                 : 
    1648               0 :     gfxIntSize size;
    1649               0 :     fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH, &size.width);
    1650               0 :     fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT, &size.height);
    1651                 :     
    1652               0 :     nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(size, gfxASurface::ImageFormatARGB32);
    1653               0 :     if (!surf || surf->CairoStatus()) {
    1654               0 :         return NULL;
    1655                 :     }
    1656                 : 
    1657               0 :     PRUint32 currentPackAlignment = 0;
    1658               0 :     fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
    1659               0 :     if (currentPackAlignment != 4) {
    1660               0 :         fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
    1661                 :     }
    1662               0 :     fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->Data());
    1663               0 :     if (currentPackAlignment != 4) {
    1664               0 :         fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
    1665                 :     }
    1666                 :    
    1667               0 :     if (aShader == RGBALayerProgramType || aShader == RGBXLayerProgramType) {
    1668               0 :       SwapRAndBComponents(surf);
    1669                 :     }
    1670                 : 
    1671               0 :     if (aYInvert) {
    1672               0 :       surf = YInvertImageSurface(surf);
    1673                 :     }
    1674               0 :     return surf.forget();
    1675                 : }
    1676                 : 
    1677                 : already_AddRefed<gfxImageSurface>
    1678               0 : GLContext::ReadTextureImage(GLuint aTexture,
    1679                 :                             const gfxIntSize& aSize,
    1680                 :                             GLenum aTextureFormat,
    1681                 :                             bool aYInvert)
    1682                 : {
    1683               0 :     MakeCurrent();
    1684                 : 
    1685               0 :     nsRefPtr<gfxImageSurface> isurf;
    1686                 : 
    1687                 :     GLint oldrb, oldfb, oldprog, oldPackAlignment;
    1688                 :     GLint success;
    1689                 : 
    1690               0 :     GLuint rb = 0, fb = 0;
    1691               0 :     GLuint vs = 0, fs = 0, prog = 0;
    1692                 : 
    1693                 :     const char *vShader =
    1694                 :         "attribute vec4 aVertex;\n"
    1695                 :         "attribute vec2 aTexCoord;\n"
    1696                 :         "varying vec2 vTexCoord;\n"
    1697               0 :         "void main() { gl_Position = aVertex; vTexCoord = aTexCoord; }";
    1698                 :     const char *fShader =
    1699                 :         "#ifdef GL_ES\n"
    1700                 :         "precision mediump float;\n"
    1701                 :         "#endif\n"
    1702                 :         "varying vec2 vTexCoord;\n"
    1703                 :         "uniform sampler2D uTexture;\n"
    1704               0 :         "void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
    1705                 : 
    1706                 :     float verts[4*4] = {
    1707                 :         -1.0f, -1.0f, 0.0f, 1.0f,
    1708                 :          1.0f, -1.0f, 0.0f, 1.0f,
    1709                 :         -1.0f,  1.0f, 0.0f, 1.0f,
    1710                 :          1.0f,  1.0f, 0.0f, 1.0f
    1711               0 :     };
    1712                 : 
    1713                 :     float texcoords[2*4] = {
    1714                 :         0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
    1715               0 :     };
    1716                 : 
    1717               0 :     fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
    1718               0 :     fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
    1719               0 :     fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
    1720               0 :     fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &oldPackAlignment);
    1721                 : 
    1722               0 :     PushViewportRect(nsIntRect(0, 0, aSize.width, aSize.height));
    1723                 : 
    1724               0 :     fGenRenderbuffers(1, &rb);
    1725               0 :     fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
    1726                 :     fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, LOCAL_GL_RGBA,
    1727               0 :                          aSize.width, aSize.height);
    1728                 : 
    1729               0 :     fGenFramebuffers(1, &fb);
    1730               0 :     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
    1731                 :     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
    1732               0 :                              LOCAL_GL_RENDERBUFFER, rb);
    1733                 : 
    1734               0 :     if (fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) !=
    1735                 :         LOCAL_GL_FRAMEBUFFER_COMPLETE)
    1736                 :     {
    1737               0 :         goto cleanup;
    1738                 :     }
    1739                 : 
    1740               0 :     vs = fCreateShader(LOCAL_GL_VERTEX_SHADER);
    1741               0 :     fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
    1742               0 :     fShaderSource(vs, 1, (const GLchar**) &vShader, NULL);
    1743               0 :     fShaderSource(fs, 1, (const GLchar**) &fShader, NULL);
    1744               0 :     fCompileShader(vs);
    1745               0 :     fCompileShader(fs);
    1746               0 :     prog = fCreateProgram();
    1747               0 :     fAttachShader(prog, vs);
    1748               0 :     fAttachShader(prog, fs);
    1749               0 :     fBindAttribLocation(prog, 0, "aVertex");
    1750               0 :     fBindAttribLocation(prog, 1, "aTexCoord");
    1751               0 :     fLinkProgram(prog);
    1752                 : 
    1753               0 :     fGetProgramiv(prog, LOCAL_GL_LINK_STATUS, &success);
    1754               0 :     if (!success) {
    1755               0 :         goto cleanup;
    1756                 :     }
    1757                 : 
    1758               0 :     fUseProgram(prog);
    1759                 : 
    1760               0 :     fEnableVertexAttribArray(0);
    1761               0 :     fEnableVertexAttribArray(1);
    1762                 : 
    1763               0 :     fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, verts);
    1764               0 :     fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, texcoords);
    1765                 : 
    1766               0 :     fActiveTexture(LOCAL_GL_TEXTURE0);
    1767               0 :     fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
    1768                 : 
    1769               0 :     fUniform1i(fGetUniformLocation(prog, "uTexture"), 0);
    1770                 : 
    1771               0 :     fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
    1772                 : 
    1773               0 :     fDisableVertexAttribArray(1);
    1774               0 :     fDisableVertexAttribArray(0);
    1775                 : 
    1776               0 :     isurf = new gfxImageSurface(aSize, gfxASurface::ImageFormatARGB32);
    1777               0 :     if (!isurf || isurf->CairoStatus()) {
    1778               0 :         isurf = nsnull;
    1779               0 :         goto cleanup;
    1780                 :     }
    1781                 : 
    1782               0 :     if (oldPackAlignment != 4)
    1783               0 :         fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
    1784                 : 
    1785                 :     fReadPixels(0, 0, aSize.width, aSize.height,
    1786                 :                 LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
    1787               0 :                 isurf->Data());
    1788                 : 
    1789               0 :     SwapRAndBComponents(isurf);
    1790                 : 
    1791               0 :     if (oldPackAlignment != 4)
    1792               0 :         fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
    1793                 : 
    1794               0 :     if (aYInvert) {
    1795               0 :       isurf = YInvertImageSurface(isurf);
    1796                 :     }
    1797                 : 
    1798                 :  cleanup:
    1799                 :     // note that deleting 0 has no effect in any of these calls
    1800               0 :     fDeleteRenderbuffers(1, &rb);
    1801               0 :     fDeleteFramebuffers(1, &fb);
    1802               0 :     fDeleteShader(vs);
    1803               0 :     fDeleteShader(fs);
    1804               0 :     fDeleteProgram(prog);
    1805                 : 
    1806               0 :     fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
    1807               0 :     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
    1808               0 :     fUseProgram(oldprog);
    1809                 : 
    1810               0 :     PopViewportRect();
    1811                 : 
    1812               0 :     return isurf.forget();
    1813                 : }
    1814                 : 
    1815                 : static void
    1816               0 : GetOptimalReadFormats(GLContext* gl, GLenum& format, GLenum& type) {
    1817               0 :     if (gl->IsGLES2()) {
    1818               0 :         bool has_BGRA_UByte = false;
    1819               0 :         if (gl->IsExtensionSupported(gl::GLContext::EXT_bgra)) {
    1820               0 :           has_BGRA_UByte = true;
    1821               0 :         } else if (gl->IsExtensionSupported(gl::GLContext::EXT_read_format_bgra) ||
    1822               0 :                    gl->IsExtensionSupported(gl::GLContext::IMG_read_format)) {
    1823                 :             // Note that these extensions are not required to query this value.
    1824                 :             // However, we should never get back BGRA unless one of these is supported.
    1825               0 :             GLint auxFormat = 0;
    1826               0 :             GLint auxType = 0;
    1827                 : 
    1828               0 :             gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &auxFormat);
    1829               0 :             gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &auxType);
    1830                 : 
    1831               0 :             if (auxFormat == LOCAL_GL_BGRA && auxType == LOCAL_GL_UNSIGNED_BYTE)
    1832               0 :               has_BGRA_UByte = true;
    1833                 :         }
    1834                 : 
    1835               0 :         format = has_BGRA_UByte ? LOCAL_GL_BGRA : LOCAL_GL_RGBA;
    1836               0 :         type = LOCAL_GL_UNSIGNED_BYTE;
    1837                 :     } else {
    1838                 :         // defaults for desktop
    1839               0 :         format = LOCAL_GL_BGRA;
    1840               0 :         type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
    1841                 :     }
    1842               0 : }
    1843                 : 
    1844                 : void
    1845               0 : GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
    1846                 :                                       GLsizei aWidth, GLsizei aHeight,
    1847                 :                                       gfxImageSurface *aDest)
    1848                 : {
    1849               0 :     MakeCurrent();
    1850                 : 
    1851               0 :     if (aDest->Format() != gfxASurface::ImageFormatARGB32 &&
    1852               0 :         aDest->Format() != gfxASurface::ImageFormatRGB24)
    1853                 :     {
    1854               0 :         NS_WARNING("ReadPixelsIntoImageSurface called with invalid image format");
    1855               0 :         return;
    1856                 :     }
    1857                 : 
    1858               0 :     if (aDest->Width() != aWidth ||
    1859               0 :         aDest->Height() != aHeight ||
    1860               0 :         aDest->Stride() != aWidth * 4)
    1861                 :     {
    1862               0 :         NS_WARNING("ReadPixelsIntoImageSurface called with wrong size or stride surface");
    1863               0 :         return;
    1864                 :     }
    1865                 : 
    1866               0 :     GLint currentPackAlignment = 0;
    1867               0 :     fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);
    1868                 : 
    1869               0 :     if (currentPackAlignment != 4)
    1870               0 :         fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
    1871                 : 
    1872                 :     GLenum format;
    1873                 :     GLenum datatype;
    1874                 : 
    1875               0 :     GetOptimalReadFormats(this, format, datatype);
    1876                 : 
    1877                 :     fReadPixels(0, 0, aWidth, aHeight,
    1878                 :                 format, datatype,
    1879               0 :                 aDest->Data());
    1880                 : 
    1881                 :     // Output should be in BGRA, so swap if RGBA
    1882               0 :     if (format == LOCAL_GL_RGBA) {
    1883                 :         // swap B and R bytes
    1884               0 :         for (int j = 0; j < aHeight; ++j) {
    1885               0 :             PRUint32 *row = (PRUint32*) (aDest->Data() + aDest->Stride() * j);
    1886               0 :             for (int i = 0; i < aWidth; ++i) {
    1887               0 :                 *row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
    1888               0 :                 row++;
    1889                 :             }
    1890                 :         }
    1891                 :     }
    1892                 : 
    1893               0 :     if (currentPackAlignment != 4)
    1894               0 :         fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
    1895                 : }
    1896                 : 
    1897                 : void
    1898               0 : GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
    1899                 :                             TextureImage *aDst, const nsIntRect& aDstRect)
    1900                 : {
    1901               0 :     NS_ASSERTION(!aSrc->InUpdate(), "Source texture is in update!");
    1902               0 :     NS_ASSERTION(!aDst->InUpdate(), "Destination texture is in update!");
    1903                 : 
    1904               0 :     if (aSrcRect.IsEmpty() || aDstRect.IsEmpty())
    1905               0 :         return;
    1906                 : 
    1907                 :     // only save/restore this stuff on Qualcomm Adreno, to work
    1908                 :     // around an apparent bug
    1909               0 :     int savedFb = 0;
    1910               0 :     if (mVendor == VendorQualcomm) {
    1911               0 :         fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
    1912                 :     }
    1913                 : 
    1914               0 :     fDisable(LOCAL_GL_SCISSOR_TEST);
    1915               0 :     fDisable(LOCAL_GL_BLEND);
    1916                 : 
    1917                 :     // 2.0 means scale up by two
    1918               0 :     float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
    1919               0 :     float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
    1920                 : 
    1921                 :     // We start iterating over all destination tiles
    1922               0 :     aDst->BeginTileIteration();
    1923               0 :     do {
    1924                 :         // calculate portion of the tile that is going to be painted to
    1925               0 :         nsIntRect dstSubRect;
    1926               0 :         nsIntRect dstTextureRect = aDst->GetTileRect();
    1927               0 :         dstSubRect.IntersectRect(aDstRect, dstTextureRect);
    1928                 : 
    1929                 :         // this tile is not part of the destination rectangle aDstRect
    1930               0 :         if (dstSubRect.IsEmpty())
    1931               0 :             continue;
    1932                 : 
    1933                 :         // (*) transform the rect of this tile into the rectangle defined by aSrcRect...
    1934               0 :         nsIntRect dstInSrcRect(dstSubRect);
    1935               0 :         dstInSrcRect.MoveBy(-aDstRect.TopLeft());
    1936                 :         // ...which might be of different size, hence scale accordingly
    1937               0 :         dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
    1938               0 :         dstInSrcRect.MoveBy(aSrcRect.TopLeft());
    1939                 : 
    1940               0 :         SetBlitFramebufferForDestTexture(aDst->GetTextureID());
    1941               0 :         UseBlitProgram();
    1942                 : 
    1943               0 :         aSrc->BeginTileIteration();
    1944                 :         // now iterate over all tiles in the source Image...
    1945               0 :         do {
    1946                 :             // calculate portion of the source tile that is in the source rect
    1947               0 :             nsIntRect srcSubRect;
    1948               0 :             nsIntRect srcTextureRect = aSrc->GetTileRect();
    1949               0 :             srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
    1950                 : 
    1951                 :             // this tile is not part of the source rect
    1952               0 :             if (srcSubRect.IsEmpty()) {
    1953               0 :                 continue;
    1954                 :             }
    1955                 :             // calculate intersection of source rect with destination rect
    1956               0 :             srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
    1957                 :             // this tile does not overlap the current destination tile
    1958               0 :             if (srcSubRect.IsEmpty()) {
    1959               0 :                 continue;
    1960                 :             }
    1961                 :             // We now have the intersection of 
    1962                 :             //     the current source tile 
    1963                 :             // and the desired source rectangle
    1964                 :             // and the destination tile
    1965                 :             // and the desired destination rectange
    1966                 :             // in destination space.
    1967                 :             // We need to transform this back into destination space, inverting the transform from (*)
    1968               0 :             nsIntRect srcSubInDstRect(srcSubRect);
    1969               0 :             srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
    1970               0 :             srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
    1971               0 :             srcSubInDstRect.MoveBy(aDstRect.TopLeft());
    1972                 : 
    1973                 :             // we transform these rectangles to be relative to the current src and dst tiles, respectively
    1974               0 :             nsIntSize srcSize = srcTextureRect.Size();
    1975               0 :             nsIntSize dstSize = dstTextureRect.Size();
    1976               0 :             srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
    1977               0 :             srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
    1978                 : 
    1979               0 :             float dx0 = 2.0 * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0;
    1980               0 :             float dy0 = 2.0 * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0;
    1981               0 :             float dx1 = 2.0 * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0;
    1982               0 :             float dy1 = 2.0 * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0;
    1983               0 :             PushViewportRect(nsIntRect(0, 0, dstSize.width, dstSize.height));
    1984                 : 
    1985               0 :             RectTriangles rects;
    1986               0 :             if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
    1987                 :                 rects.addRect(/* dest rectangle */
    1988                 :                         dx0, dy0, dx1, dy1,
    1989                 :                         /* tex coords */
    1990                 :                         srcSubRect.x / float(srcSize.width),
    1991                 :                         srcSubRect.y / float(srcSize.height),
    1992               0 :                         srcSubRect.XMost() / float(srcSize.width),
    1993               0 :                         srcSubRect.YMost() / float(srcSize.height));
    1994                 :             } else {
    1995               0 :                 DecomposeIntoNoRepeatTriangles(srcSubRect, srcSize, rects);
    1996                 : 
    1997                 :                 // now put the coords into the d[xy]0 .. d[xy]1 coordinate space
    1998                 :                 // from the 0..1 that it comes out of decompose
    1999               0 :                 RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
    2000                 : 
    2001               0 :                 for (unsigned int i = 0; i < rects.elements(); ++i) {
    2002               0 :                     v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
    2003               0 :                     v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
    2004                 :                 }
    2005                 :             }
    2006                 : 
    2007               0 :             TextureImage::ScopedBindTexture texBind(aSrc, LOCAL_GL_TEXTURE0);
    2008                 : 
    2009               0 :             fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
    2010                 : 
    2011               0 :             fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
    2012               0 :             fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
    2013                 : 
    2014               0 :             fEnableVertexAttribArray(0);
    2015               0 :             fEnableVertexAttribArray(1);
    2016                 : 
    2017               0 :             fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
    2018                 : 
    2019               0 :             fDisableVertexAttribArray(0);
    2020               0 :             fDisableVertexAttribArray(1);
    2021                 : 
    2022               0 :             PopViewportRect();
    2023               0 :         } while (aSrc->NextTile());
    2024               0 :     } while (aDst->NextTile());
    2025                 : 
    2026               0 :     fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, NULL);
    2027               0 :     fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, NULL);
    2028                 : 
    2029                 :     // unbind the previous texture from the framebuffer
    2030               0 :     SetBlitFramebufferForDestTexture(0);
    2031                 : 
    2032                 :     // then put back the previous framebuffer, and don't
    2033                 :     // enable stencil if it wasn't enabled on entry to work
    2034                 :     // around Adreno 200 bug that causes us to crash if
    2035                 :     // we enable scissor test while the current FBO is invalid
    2036                 :     // (which it will be, once we assign texture 0 to the color
    2037                 :     // attachment)
    2038               0 :     if (mVendor == VendorQualcomm) {
    2039               0 :         fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
    2040                 :     }
    2041                 : 
    2042               0 :     fEnable(LOCAL_GL_SCISSOR_TEST);
    2043               0 :     fEnable(LOCAL_GL_BLEND);
    2044                 : }
    2045                 : 
    2046                 : static unsigned int 
    2047               0 : DataOffset(gfxImageSurface *aSurf, const nsIntPoint &aPoint)
    2048                 : {
    2049               0 :   unsigned int data = aPoint.y * aSurf->Stride();
    2050               0 :   data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aSurf->Format());
    2051               0 :   return data;
    2052                 : }
    2053                 : 
    2054                 : ShaderProgramType 
    2055               0 : GLContext::UploadSurfaceToTexture(gfxASurface *aSurface, 
    2056                 :                                   const nsIntRegion& aDstRegion,
    2057                 :                                   GLuint& aTexture,
    2058                 :                                   bool aOverwrite,
    2059                 :                                   const nsIntPoint& aSrcPoint,
    2060                 :                                   bool aPixelBuffer)
    2061                 : {
    2062               0 :     bool textureInited = aOverwrite ? false : true;
    2063               0 :     MakeCurrent();
    2064               0 :     fActiveTexture(LOCAL_GL_TEXTURE0);
    2065                 :   
    2066               0 :     if (!aTexture) {
    2067               0 :         fGenTextures(1, &aTexture);
    2068               0 :         fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
    2069                 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, 
    2070                 :                        LOCAL_GL_TEXTURE_MIN_FILTER, 
    2071               0 :                        LOCAL_GL_LINEAR);
    2072                 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, 
    2073                 :                        LOCAL_GL_TEXTURE_MAG_FILTER, 
    2074               0 :                        LOCAL_GL_LINEAR);
    2075                 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, 
    2076                 :                        LOCAL_GL_TEXTURE_WRAP_S, 
    2077               0 :                        LOCAL_GL_CLAMP_TO_EDGE);
    2078                 :         fTexParameteri(LOCAL_GL_TEXTURE_2D, 
    2079                 :                        LOCAL_GL_TEXTURE_WRAP_T, 
    2080               0 :                        LOCAL_GL_CLAMP_TO_EDGE);
    2081               0 :         textureInited = false;
    2082                 :     } else {
    2083               0 :         fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
    2084                 :     }
    2085                 : 
    2086               0 :     nsIntRegion paintRegion;
    2087               0 :     if (!textureInited) {
    2088               0 :         paintRegion = nsIntRegion(aDstRegion.GetBounds());
    2089                 :     } else {
    2090               0 :         paintRegion = aDstRegion;
    2091                 :     }
    2092                 : 
    2093               0 :     nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
    2094               0 :     unsigned char* data = NULL;
    2095                 : 
    2096               0 :     if (!imageSurface || 
    2097               0 :         (imageSurface->Format() != gfxASurface::ImageFormatARGB32 &&
    2098               0 :          imageSurface->Format() != gfxASurface::ImageFormatRGB24 &&
    2099               0 :          imageSurface->Format() != gfxASurface::ImageFormatRGB16_565 &&
    2100               0 :          imageSurface->Format() != gfxASurface::ImageFormatA8)) {
    2101                 :         // We can't get suitable pixel data for the surface, make a copy
    2102               0 :         nsIntRect bounds = aDstRegion.GetBounds();
    2103                 :         imageSurface = 
    2104                 :           new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), 
    2105               0 :                               gfxASurface::ImageFormatARGB32);
    2106                 :   
    2107               0 :         nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
    2108                 : 
    2109               0 :         context->Translate(-gfxPoint(aSrcPoint.x, aSrcPoint.y));
    2110               0 :         context->SetSource(aSurface);
    2111               0 :         context->Paint();
    2112               0 :         data = imageSurface->Data();
    2113               0 :         NS_ASSERTION(!aPixelBuffer,
    2114                 :                      "Must be using an image compatible surface with pixel buffers!");
    2115                 :     } else {
    2116                 :         // If a pixel buffer is bound the data pointer parameter is relative
    2117                 :         // to the start of the data block.
    2118               0 :         if (!aPixelBuffer) {
    2119               0 :               data = imageSurface->Data();
    2120                 :         }
    2121               0 :         data += DataOffset(imageSurface, aSrcPoint);
    2122                 :     }
    2123                 : 
    2124                 :     GLenum format;
    2125                 :     GLenum internalformat;
    2126                 :     GLenum type;
    2127               0 :     PRInt32 pixelSize = gfxASurface::BytePerPixelFromFormat(imageSurface->Format());
    2128                 :     ShaderProgramType shader;
    2129                 : 
    2130               0 :     switch (imageSurface->Format()) {
    2131                 :         case gfxASurface::ImageFormatARGB32:
    2132               0 :             format = LOCAL_GL_RGBA;
    2133               0 :             type = LOCAL_GL_UNSIGNED_BYTE;
    2134               0 :             shader = BGRALayerProgramType;
    2135               0 :             break;
    2136                 :         case gfxASurface::ImageFormatRGB24:
    2137                 :             // Treat RGB24 surfaces as RGBA32 except for the shader
    2138                 :             // program used.
    2139               0 :             format = LOCAL_GL_RGBA;
    2140               0 :             type = LOCAL_GL_UNSIGNED_BYTE;
    2141               0 :             shader = BGRXLayerProgramType;
    2142               0 :             break;
    2143                 :         case gfxASurface::ImageFormatRGB16_565:
    2144               0 :             format = LOCAL_GL_RGB;
    2145               0 :             type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
    2146               0 :             shader = RGBALayerProgramType;
    2147               0 :             break;
    2148                 :         case gfxASurface::ImageFormatA8:
    2149               0 :             format = LOCAL_GL_LUMINANCE;
    2150               0 :             type = LOCAL_GL_UNSIGNED_BYTE;
    2151                 :             // We don't have a specific luminance shader
    2152               0 :             shader = ShaderProgramType(0);
    2153               0 :             break;
    2154                 :         default:
    2155               0 :             NS_ASSERTION(false, "Unhandled image surface format!");
    2156               0 :             format = 0;
    2157               0 :             type = 0;
    2158               0 :             shader = ShaderProgramType(0);
    2159                 :     }
    2160                 : 
    2161               0 :     PRInt32 stride = imageSurface->Stride();
    2162                 : 
    2163                 : #ifndef USE_GLES2
    2164               0 :     internalformat = LOCAL_GL_RGBA;
    2165                 : #else
    2166                 :     internalformat = format;
    2167                 : #endif
    2168                 : 
    2169               0 :     nsIntRegionRectIterator iter(paintRegion);
    2170                 :     const nsIntRect *iterRect;
    2171                 : 
    2172                 :     // Top left point of the region's bounding rectangle.
    2173               0 :     nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
    2174                 : 
    2175               0 :     while ((iterRect = iter.Next())) {
    2176                 :         // The inital data pointer is at the top left point of the region's
    2177                 :         // bounding rectangle. We need to find the offset of this rect
    2178                 :         // within the region and adjust the data pointer accordingly.
    2179                 :         unsigned char *rectData = 
    2180               0 :             data + DataOffset(imageSurface, iterRect->TopLeft() - topLeft);
    2181                 : 
    2182               0 :         NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0), 
    2183                 :                      "Must be uploading to the origin when we don't have an existing texture");
    2184                 : 
    2185               0 :         if (textureInited && CanUploadSubTextures()) {
    2186                 :             TexSubImage2D(LOCAL_GL_TEXTURE_2D,
    2187                 :                           0,
    2188                 :                           iterRect->x,
    2189                 :                           iterRect->y,
    2190                 :                           iterRect->width,
    2191                 :                           iterRect->height,
    2192                 :                           stride,
    2193                 :                           pixelSize,
    2194                 :                           format,
    2195                 :                           type,
    2196               0 :                           rectData);
    2197                 :         } else {
    2198                 :             TexImage2D(LOCAL_GL_TEXTURE_2D,
    2199                 :                        0,
    2200                 :                        internalformat,
    2201                 :                        iterRect->width,
    2202                 :                        iterRect->height,
    2203                 :                        stride,
    2204                 :                        pixelSize,
    2205                 :                        0,
    2206                 :                        format,
    2207                 :                        type,
    2208               0 :                        rectData);
    2209                 :         }
    2210                 : 
    2211                 :     }
    2212                 : 
    2213               0 :     return shader;
    2214                 : }
    2215                 : 
    2216               0 : static GLint GetAddressAlignment(ptrdiff_t aAddress)
    2217                 : {
    2218               0 :     if (!(aAddress & 0x7)) {
    2219               0 :        return 8;
    2220               0 :     } else if (!(aAddress & 0x3)) {
    2221               0 :         return 4;
    2222               0 :     } else if (!(aAddress & 0x1)) {
    2223               0 :         return 2;
    2224                 :     } else {
    2225               0 :         return 1;
    2226                 :     }
    2227                 : }
    2228                 : 
    2229                 : void
    2230               0 : GLContext::TexImage2D(GLenum target, GLint level, GLint internalformat,
    2231                 :                       GLsizei width, GLsizei height, GLsizei stride,
    2232                 :                       GLint pixelsize, GLint border, GLenum format,
    2233                 :                       GLenum type, const GLvoid *pixels)
    2234                 : {
    2235                 : #ifdef USE_GLES2
    2236                 : 
    2237                 :     NS_ASSERTION(format == internalformat,
    2238                 :                  "format and internalformat not the same for glTexImage2D on GLES2");
    2239                 : 
    2240                 :     if (stride == width * pixelsize) {
    2241                 :         fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
    2242                 :                  NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
    2243                 :                         GetAddressAlignment((ptrdiff_t)stride)));
    2244                 :         fTexImage2D(target,
    2245                 :                     border,
    2246                 :                     internalformat,
    2247                 :                     width,
    2248                 :                     height,
    2249                 :                     border,
    2250                 :                     format,
    2251                 :                     type,
    2252                 :                     pixels);
    2253                 :         fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
    2254                 :     } else {
    2255                 :         // Use GLES-specific workarounds for GL_UNPACK_ROW_LENGTH; these are
    2256                 :         // implemented in TexSubImage2D.
    2257                 :         fTexImage2D(target,
    2258                 :                     border,
    2259                 :                     internalformat,
    2260                 :                     width,
    2261                 :                     height,
    2262                 :                     border,
    2263                 :                     format,
    2264                 :                     type,
    2265                 :                     NULL);
    2266                 :         TexSubImage2D(target,
    2267                 :                       level,
    2268                 :                       0,
    2269                 :                       0,
    2270                 :                       width,
    2271                 :                       height,
    2272                 :                       stride,
    2273                 :                       pixelsize,
    2274                 :                       format,
    2275                 :                       type,
    2276                 :                       pixels);
    2277                 :     }
    2278                 : #else
    2279                 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
    2280               0 :                  NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
    2281               0 :                         GetAddressAlignment((ptrdiff_t)stride)));
    2282               0 :     int rowLength = stride/pixelsize;
    2283               0 :     fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
    2284                 :     fTexImage2D(target,
    2285                 :                 level,
    2286                 :                 internalformat,
    2287                 :                 width,
    2288                 :                 height,
    2289                 :                 border,
    2290                 :                 format,
    2291                 :                 type,
    2292               0 :                 pixels);
    2293               0 :     fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
    2294               0 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
    2295                 : #endif
    2296               0 : }
    2297                 : 
    2298                 : void
    2299               0 : GLContext::TexSubImage2D(GLenum target, GLint level,
    2300                 :                          GLint xoffset, GLint yoffset,
    2301                 :                          GLsizei width, GLsizei height, GLsizei stride,
    2302                 :                          GLint pixelsize, GLenum format,
    2303                 :                          GLenum type, const GLvoid* pixels)
    2304                 : {
    2305                 : #ifdef USE_GLES2
    2306                 :     if (stride == width * pixelsize) {
    2307                 :         fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
    2308                 :                  NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
    2309                 :                         GetAddressAlignment((ptrdiff_t)stride)));
    2310                 :         fTexSubImage2D(target,
    2311                 :                        level,
    2312                 :                        xoffset,
    2313                 :                        yoffset,
    2314                 :                        width,
    2315                 :                        height,
    2316                 :                        format,
    2317                 :                        type,
    2318                 :                        pixels);
    2319                 :         fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
    2320                 :     } else if (IsExtensionSupported(EXT_unpack_subimage)) {
    2321                 :         TexSubImage2DWithUnpackSubimageGLES(target, level, xoffset, yoffset,
    2322                 :                                             width, height, stride,
    2323                 :                                             pixelsize, format, type, pixels);
    2324                 : 
    2325                 :     } else {
    2326                 :         TexSubImage2DWithoutUnpackSubimage(target, level, xoffset, yoffset,
    2327                 :                                            width, height, stride,
    2328                 :                                            pixelsize, format, type, pixels);
    2329                 :     }
    2330                 : #else
    2331                 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
    2332               0 :                  NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
    2333               0 :                         GetAddressAlignment((ptrdiff_t)stride)));
    2334               0 :     int rowLength = stride/pixelsize;
    2335               0 :     fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
    2336                 :     fTexSubImage2D(target,
    2337                 :                    level,
    2338                 :                    xoffset,
    2339                 :                    yoffset,
    2340                 :                    width,
    2341                 :                    height,
    2342                 :                    format,
    2343                 :                    type,
    2344               0 :                    pixels);
    2345               0 :     fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
    2346               0 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
    2347                 : #endif
    2348               0 : }
    2349                 : 
    2350                 : void
    2351               0 : GLContext::TexSubImage2DWithUnpackSubimageGLES(GLenum target, GLint level,
    2352                 :                                                GLint xoffset, GLint yoffset,
    2353                 :                                                GLsizei width, GLsizei height,
    2354                 :                                                GLsizei stride, GLint pixelsize,
    2355                 :                                                GLenum format, GLenum type,
    2356                 :                                                const GLvoid* pixels)
    2357                 : {
    2358                 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
    2359               0 :                  NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
    2360               0 :                         GetAddressAlignment((ptrdiff_t)stride)));
    2361                 :     // When using GL_UNPACK_ROW_LENGTH, we need to work around a Tegra
    2362                 :     // driver crash where the driver apparently tries to read
    2363                 :     // (stride - width * pixelsize) bytes past the end of the last input
    2364                 :     // row. We only upload the first height-1 rows using GL_UNPACK_ROW_LENGTH,
    2365                 :     // and then we upload the final row separately. See bug 697990.
    2366               0 :     int rowLength = stride/pixelsize;
    2367               0 :     fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
    2368                 :     fTexSubImage2D(target,
    2369                 :                     level,
    2370                 :                     xoffset,
    2371                 :                     yoffset,
    2372                 :                     width,
    2373                 :                     height-1,
    2374                 :                     format,
    2375                 :                     type,
    2376               0 :                     pixels);
    2377               0 :     fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
    2378                 :     fTexSubImage2D(target,
    2379                 :                     level,
    2380                 :                     xoffset,
    2381                 :                     yoffset+height-1,
    2382                 :                     width,
    2383                 :                     1,
    2384                 :                     format,
    2385                 :                     type,
    2386               0 :                     (const unsigned char *)pixels+(height-1)*stride);
    2387               0 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
    2388               0 : }
    2389                 : 
    2390                 : void
    2391               0 : GLContext::TexSubImage2DWithoutUnpackSubimage(GLenum target, GLint level,
    2392                 :                                               GLint xoffset, GLint yoffset,
    2393                 :                                               GLsizei width, GLsizei height,
    2394                 :                                               GLsizei stride, GLint pixelsize,
    2395                 :                                               GLenum format, GLenum type,
    2396                 :                                               const GLvoid* pixels)
    2397                 : {
    2398                 :     // Not using the whole row of texture data and GL_UNPACK_ROW_LENGTH
    2399                 :     // isn't supported. We make a copy of the texture data we're using,
    2400                 :     // such that we're using the whole row of data in the copy. This turns
    2401                 :     // out to be more efficient than uploading row-by-row; see bug 698197.
    2402               0 :     unsigned char *newPixels = new unsigned char[width*height*pixelsize];
    2403               0 :     unsigned char *rowDest = newPixels;
    2404               0 :     const unsigned char *rowSource = (const unsigned char *)pixels;
    2405               0 :     for (int h = 0; h < height; h++) {
    2406               0 :             memcpy(rowDest, rowSource, width*pixelsize);
    2407               0 :             rowDest += width*pixelsize;
    2408               0 :             rowSource += stride;
    2409                 :     }
    2410                 : 
    2411               0 :     stride = width*pixelsize;
    2412                 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
    2413               0 :                     NS_MIN(GetAddressAlignment((ptrdiff_t)newPixels),
    2414               0 :                             GetAddressAlignment((ptrdiff_t)stride)));
    2415                 :     fTexSubImage2D(target,
    2416                 :                     level,
    2417                 :                     xoffset,
    2418                 :                     yoffset,
    2419                 :                     width,
    2420                 :                     height,
    2421                 :                     format,
    2422                 :                     type,
    2423               0 :                     newPixels);
    2424               0 :     delete [] newPixels;
    2425               0 :     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
    2426               0 : }
    2427                 : 
    2428                 : void
    2429               0 : GLContext::RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
    2430                 :                                   GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1)
    2431                 : {
    2432                 :     vert_coord v;
    2433               0 :     v.x = x0; v.y = y0;
    2434               0 :     vertexCoords.AppendElement(v);
    2435               0 :     v.x = x1; v.y = y0;
    2436               0 :     vertexCoords.AppendElement(v);
    2437               0 :     v.x = x0; v.y = y1;
    2438               0 :     vertexCoords.AppendElement(v);
    2439                 : 
    2440               0 :     v.x = x0; v.y = y1;
    2441               0 :     vertexCoords.AppendElement(v);
    2442               0 :     v.x = x1; v.y = y0;
    2443               0 :     vertexCoords.AppendElement(v);
    2444               0 :     v.x = x1; v.y = y1;
    2445               0 :     vertexCoords.AppendElement(v);
    2446                 : 
    2447                 :     tex_coord t;
    2448               0 :     t.u = tx0; t.v = ty0;
    2449               0 :     texCoords.AppendElement(t);
    2450               0 :     t.u = tx1; t.v = ty0;
    2451               0 :     texCoords.AppendElement(t);
    2452               0 :     t.u = tx0; t.v = ty1;
    2453               0 :     texCoords.AppendElement(t);
    2454                 : 
    2455               0 :     t.u = tx0; t.v = ty1;
    2456               0 :     texCoords.AppendElement(t);
    2457               0 :     t.u = tx1; t.v = ty0;
    2458               0 :     texCoords.AppendElement(t);
    2459               0 :     t.u = tx1; t.v = ty1;
    2460               0 :     texCoords.AppendElement(t);
    2461               0 : }
    2462                 : 
    2463                 : static GLfloat
    2464               0 : WrapTexCoord(GLfloat v)
    2465                 : {
    2466                 :     // fmodf gives negative results for negative numbers;
    2467                 :     // that is, fmodf(0.75, 1.0) == 0.75, but
    2468                 :     // fmodf(-0.75, 1.0) == -0.75.  For the negative case,
    2469                 :     // the result we need is 0.25, so we add 1.0f.
    2470               0 :     if (v < 0.0f) {
    2471               0 :         return 1.0f + fmodf(v, 1.0f);
    2472                 :     }
    2473                 : 
    2474               0 :     return fmodf(v, 1.0f);
    2475                 : }
    2476                 : 
    2477                 : void
    2478               0 : GLContext::DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
    2479                 :                                           const nsIntSize& aTexSize,
    2480                 :                                           RectTriangles& aRects)
    2481                 : {
    2482                 :     // normalize this
    2483               0 :     nsIntRect tcr(aTexCoordRect);
    2484               0 :     while (tcr.x > aTexSize.width)
    2485               0 :         tcr.x -= aTexSize.width;
    2486               0 :     while (tcr.y > aTexSize.height)
    2487               0 :         tcr.y -= aTexSize.height;
    2488                 : 
    2489                 :     // Compute top left and bottom right tex coordinates
    2490                 :     GLfloat tl[2] =
    2491                 :         { GLfloat(tcr.x) / GLfloat(aTexSize.width),
    2492               0 :           GLfloat(tcr.y) / GLfloat(aTexSize.height) };
    2493                 :     GLfloat br[2] =
    2494               0 :         { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width),
    2495               0 :           GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) };
    2496                 : 
    2497                 :     // then check if we wrap in either the x or y axis; if we do,
    2498                 :     // then also use fmod to figure out the "true" non-wrapping
    2499                 :     // texture coordinates.
    2500                 : 
    2501               0 :     bool xwrap = false, ywrap = false;
    2502               0 :     if (tcr.x < 0 || tcr.x > aTexSize.width ||
    2503               0 :         tcr.XMost() < 0 || tcr.XMost() > aTexSize.width)
    2504                 :     {
    2505               0 :         xwrap = true;
    2506               0 :         tl[0] = WrapTexCoord(tl[0]);
    2507               0 :         br[0] = WrapTexCoord(br[0]);
    2508                 :     }
    2509                 : 
    2510               0 :     if (tcr.y < 0 || tcr.y > aTexSize.height ||
    2511               0 :         tcr.YMost() < 0 || tcr.YMost() > aTexSize.height)
    2512                 :     {
    2513               0 :         ywrap = true;
    2514               0 :         tl[1] = WrapTexCoord(tl[1]);
    2515               0 :         br[1] = WrapTexCoord(br[1]);
    2516                 :     }
    2517                 : 
    2518               0 :     NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f &&
    2519                 :                  tl[1] >= 0.0f && tl[1] <= 1.0f &&
    2520                 :                  br[0] >= 0.0f && br[0] <= 1.0f &&
    2521                 :                  br[1] >= 0.0f && br[1] <= 1.0f,
    2522                 :                  "Somehow generated invalid texture coordinates");
    2523                 : 
    2524                 :     // If xwrap is false, the texture will be sampled from tl[0]
    2525                 :     // .. br[0].  If xwrap is true, then it will be split into tl[0]
    2526                 :     // .. 1.0, and 0.0 .. br[0].  Same for the Y axis.  The
    2527                 :     // destination rectangle is also split appropriately, according
    2528                 :     // to the calculated xmid/ymid values.
    2529                 : 
    2530                 :     // There isn't a 1:1 mapping between tex coords and destination coords;
    2531                 :     // when computing midpoints, we have to take that into account.  We
    2532                 :     // need to map the texture coords, which are (in the wrap case):
    2533                 :     // |tl->1| and |0->br| to the |0->1| range of the vertex coords.  So
    2534                 :     // we have the length (1-tl)+(br) that needs to map into 0->1.
    2535                 :     // These are only valid if there is wrap involved, they won't be used
    2536                 :     // otherwise.
    2537               0 :     GLfloat xlen = (1.0f - tl[0]) + br[0];
    2538               0 :     GLfloat ylen = (1.0f - tl[1]) + br[1];
    2539                 : 
    2540               0 :     NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?");
    2541               0 :     NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?");
    2542               0 :     NS_ASSERTION(aTexCoordRect.width <= aTexSize.width &&
    2543                 :                  aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!");
    2544                 : 
    2545               0 :     if (!xwrap && !ywrap) {
    2546                 :         aRects.addRect(0.0f, 0.0f, 1.0f, 1.0f,
    2547               0 :                        tl[0], tl[1], br[0], br[1]);
    2548               0 :     } else if (!xwrap && ywrap) {
    2549               0 :         GLfloat ymid = (1.0f - tl[1]) / ylen;
    2550                 :         aRects.addRect(0.0f, 0.0f,
    2551                 :                        1.0f, ymid,
    2552                 :                        tl[0], tl[1],
    2553               0 :                        br[0], 1.0f);
    2554                 :         aRects.addRect(0.0f, ymid,
    2555                 :                        1.0f, 1.0f,
    2556                 :                        tl[0], 0.0f,
    2557               0 :                        br[0], br[1]);
    2558               0 :     } else if (xwrap && !ywrap) {
    2559               0 :         GLfloat xmid = (1.0f - tl[0]) / xlen;
    2560                 :         aRects.addRect(0.0f, 0.0f,
    2561                 :                        xmid, 1.0f,
    2562                 :                        tl[0], tl[1],
    2563               0 :                        1.0f, br[1]);
    2564                 :         aRects.addRect(xmid, 0.0f,
    2565                 :                        1.0f, 1.0f,
    2566                 :                        0.0f, tl[1],
    2567               0 :                        br[0], br[1]);
    2568                 :     } else {
    2569               0 :         GLfloat xmid = (1.0f - tl[0]) / xlen;
    2570               0 :         GLfloat ymid = (1.0f - tl[1]) / ylen;
    2571                 :         aRects.addRect(0.0f, 0.0f,
    2572                 :                        xmid, ymid,
    2573                 :                        tl[0], tl[1],
    2574               0 :                        1.0f, 1.0f);
    2575                 :         aRects.addRect(xmid, 0.0f,
    2576                 :                        1.0f, ymid,
    2577                 :                        0.0f, tl[1],
    2578               0 :                        br[0], 1.0f);
    2579                 :         aRects.addRect(0.0f, ymid,
    2580                 :                        xmid, 1.0f,
    2581                 :                        tl[0], 0.0f,
    2582               0 :                        1.0f, br[1]);
    2583                 :         aRects.addRect(xmid, ymid,
    2584                 :                        1.0f, 1.0f,
    2585                 :                        0.0f, 0.0f,
    2586               0 :                        br[0], br[1]);
    2587                 :     }
    2588               0 : }
    2589                 : 
    2590                 : void
    2591               0 : GLContext::UseBlitProgram()
    2592                 : {
    2593               0 :     if (mBlitProgram) {
    2594               0 :         fUseProgram(mBlitProgram);
    2595               0 :         return;
    2596                 :     }
    2597                 : 
    2598               0 :     mBlitProgram = fCreateProgram();
    2599                 : 
    2600                 :     GLuint shaders[2];
    2601               0 :     shaders[0] = fCreateShader(LOCAL_GL_VERTEX_SHADER);
    2602               0 :     shaders[1] = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
    2603                 : 
    2604                 :     const char *blitVSSrc = 
    2605                 :         "attribute vec2 aVertex;"
    2606                 :         "attribute vec2 aTexCoord;"
    2607                 :         "varying vec2 vTexCoord;"
    2608                 :         "void main() {"
    2609                 :         "  vTexCoord = aTexCoord;"
    2610                 :         "  gl_Position = vec4(aVertex, 0.0, 1.0);"
    2611               0 :         "}";
    2612                 :     const char *blitFSSrc = "#ifdef GL_ES\nprecision mediump float;\n#endif\n"
    2613                 :         "uniform sampler2D uSrcTexture;"
    2614                 :         "varying vec2 vTexCoord;"
    2615                 :         "void main() {"
    2616                 :         "  gl_FragColor = texture2D(uSrcTexture, vTexCoord);"
    2617               0 :         "}";
    2618                 : 
    2619               0 :     fShaderSource(shaders[0], 1, (const GLchar**) &blitVSSrc, NULL);
    2620               0 :     fShaderSource(shaders[1], 1, (const GLchar**) &blitFSSrc, NULL);
    2621                 : 
    2622               0 :     for (int i = 0; i < 2; ++i) {
    2623               0 :         GLint success, len = 0;
    2624                 : 
    2625               0 :         fCompileShader(shaders[i]);
    2626               0 :         fGetShaderiv(shaders[i], LOCAL_GL_COMPILE_STATUS, &success);
    2627               0 :         NS_ASSERTION(success, "Shader compilation failed!");
    2628                 : 
    2629               0 :         if (!success) {
    2630               0 :             nsCAutoString log;
    2631               0 :             fGetShaderiv(shaders[i], LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
    2632               0 :             log.SetCapacity(len);
    2633               0 :             fGetShaderInfoLog(shaders[i], len, (GLint*) &len, (char*) log.BeginWriting());
    2634               0 :             log.SetLength(len);
    2635                 : 
    2636               0 :             printf_stderr("Shader %d compilation failed:\n%s\n", log.get());
    2637                 :             return;
    2638                 :         }
    2639                 : 
    2640               0 :         fAttachShader(mBlitProgram, shaders[i]);
    2641               0 :         fDeleteShader(shaders[i]);
    2642                 :     }
    2643                 : 
    2644               0 :     fBindAttribLocation(mBlitProgram, 0, "aVertex");
    2645               0 :     fBindAttribLocation(mBlitProgram, 1, "aTexCoord");
    2646                 : 
    2647               0 :     fLinkProgram(mBlitProgram);
    2648                 : 
    2649               0 :     GLint success, len = 0;
    2650               0 :     fGetProgramiv(mBlitProgram, LOCAL_GL_LINK_STATUS, &success);
    2651               0 :     NS_ASSERTION(success, "Shader linking failed!");
    2652                 : 
    2653               0 :     if (!success) {
    2654               0 :         nsCAutoString log;
    2655               0 :         fGetProgramiv(mBlitProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
    2656               0 :         log.SetCapacity(len);
    2657               0 :         fGetProgramInfoLog(mBlitProgram, len, (GLint*) &len, (char*) log.BeginWriting());
    2658               0 :         log.SetLength(len);
    2659                 : 
    2660               0 :         printf_stderr("Program linking failed:\n%s\n", log.get());
    2661                 :         return;
    2662                 :     }
    2663                 : 
    2664               0 :     fUseProgram(mBlitProgram);
    2665               0 :     fUniform1i(fGetUniformLocation(mBlitProgram, "uSrcTexture"), 0);
    2666                 : }
    2667                 : 
    2668                 : void
    2669               0 : GLContext::SetBlitFramebufferForDestTexture(GLuint aTexture)
    2670                 : {
    2671               0 :     if (!mBlitFramebuffer) {
    2672               0 :         fGenFramebuffers(1, &mBlitFramebuffer);
    2673                 :     }
    2674                 : 
    2675               0 :     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBlitFramebuffer);
    2676                 :     fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    2677                 :                           LOCAL_GL_COLOR_ATTACHMENT0,
    2678                 :                           LOCAL_GL_TEXTURE_2D,
    2679                 :                           aTexture,
    2680               0 :                           0);
    2681                 : 
    2682               0 :     GLenum result = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    2683               0 :     if (aTexture && (result != LOCAL_GL_FRAMEBUFFER_COMPLETE)) {
    2684               0 :         nsCAutoString msg;
    2685               0 :         msg.Append("Framebuffer not complete -- error 0x");
    2686               0 :         msg.AppendInt(result, 16);
    2687                 :         // Note: if you are hitting this, it is likely that
    2688                 :         // your texture is not texture complete -- that is, you
    2689                 :         // allocated a texture name, but didn't actually define its
    2690                 :         // size via a call to TexImage2D.
    2691               0 :         NS_RUNTIMEABORT(msg.get());
    2692                 :     }
    2693               0 : }
    2694                 : 
    2695                 : #ifdef DEBUG
    2696                 : 
    2697                 : void
    2698               0 : GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
    2699                 : {
    2700               0 :     mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
    2701               0 : }
    2702                 : 
    2703                 : void
    2704               0 : GLContext::CreatedShader(GLContext *aOrigin, GLuint aName)
    2705                 : {
    2706               0 :     mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
    2707               0 : }
    2708                 : 
    2709                 : void
    2710               0 : GLContext::CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2711                 : {
    2712               0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2713               0 :         mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
    2714                 :     }
    2715               0 : }
    2716                 : 
    2717                 : void
    2718               0 : GLContext::CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2719                 : {
    2720               0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2721               0 :         mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
    2722                 :     }
    2723               0 : }
    2724                 : 
    2725                 : void
    2726               0 : GLContext::CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2727                 : {
    2728               0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2729               0 :         mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
    2730                 :     }
    2731               0 : }
    2732                 : 
    2733                 : void
    2734               0 : GLContext::CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2735                 : {
    2736               0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2737               0 :         mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
    2738                 :     }
    2739               0 : }
    2740                 : 
    2741                 : static void
    2742               0 : RemoveNamesFromArray(GLContext *aOrigin, GLsizei aCount, GLuint *aNames, nsTArray<GLContext::NamedResource>& aArray)
    2743                 : {
    2744               0 :     for (GLsizei j = 0; j < aCount; ++j) {
    2745               0 :         GLuint name = aNames[j];
    2746                 :         // name 0 can be ignored
    2747               0 :         if (name == 0)
    2748               0 :             continue;
    2749                 : 
    2750               0 :         bool found = false;
    2751               0 :         for (PRUint32 i = 0; i < aArray.Length(); ++i) {
    2752               0 :             if (aArray[i].name == name) {
    2753               0 :                 aArray.RemoveElementAt(i);
    2754               0 :                 found = true;
    2755               0 :                 break;
    2756                 :             }
    2757                 :         }
    2758                 :     }
    2759               0 : }
    2760                 : 
    2761                 : void
    2762               0 : GLContext::DeletedProgram(GLContext *aOrigin, GLuint aName)
    2763                 : {
    2764               0 :     RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
    2765               0 : }
    2766                 : 
    2767                 : void
    2768               0 : GLContext::DeletedShader(GLContext *aOrigin, GLuint aName)
    2769                 : {
    2770               0 :     RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
    2771               0 : }
    2772                 : 
    2773                 : void
    2774               0 : GLContext::DeletedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2775                 : {
    2776               0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
    2777               0 : }
    2778                 : 
    2779                 : void
    2780               0 : GLContext::DeletedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2781                 : {
    2782               0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
    2783               0 : }
    2784                 : 
    2785                 : void
    2786               0 : GLContext::DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2787                 : {
    2788               0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
    2789               0 : }
    2790                 : 
    2791                 : void
    2792               0 : GLContext::DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
    2793                 : {
    2794               0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
    2795               0 : }
    2796                 : 
    2797                 : static void
    2798               0 : MarkContextDestroyedInArray(GLContext *aContext, nsTArray<GLContext::NamedResource>& aArray)
    2799                 : {
    2800               0 :     for (PRUint32 i = 0; i < aArray.Length(); ++i) {
    2801               0 :         if (aArray[i].origin == aContext)
    2802               0 :             aArray[i].originDeleted = true;
    2803                 :     }
    2804               0 : }
    2805                 : 
    2806                 : void
    2807               0 : GLContext::SharedContextDestroyed(GLContext *aChild)
    2808                 : {
    2809               0 :     MarkContextDestroyedInArray(aChild, mTrackedPrograms);
    2810               0 :     MarkContextDestroyedInArray(aChild, mTrackedShaders);
    2811               0 :     MarkContextDestroyedInArray(aChild, mTrackedTextures);
    2812               0 :     MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
    2813               0 :     MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
    2814               0 :     MarkContextDestroyedInArray(aChild, mTrackedBuffers);
    2815               0 : }
    2816                 : 
    2817                 : static void
    2818               0 : ReportArrayContents(const nsTArray<GLContext::NamedResource>& aArray)
    2819                 : {
    2820               0 :     nsTArray<GLContext::NamedResource> copy(aArray);
    2821               0 :     copy.Sort();
    2822                 : 
    2823               0 :     GLContext *lastContext = NULL;
    2824               0 :     for (PRUint32 i = 0; i < copy.Length(); ++i) {
    2825               0 :         if (lastContext != copy[i].origin) {
    2826               0 :             if (lastContext)
    2827               0 :                 printf_stderr("\n");
    2828               0 :             printf_stderr("  [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
    2829               0 :             lastContext = copy[i].origin;
    2830                 :         }
    2831               0 :         printf_stderr("%d ", copy[i].name);
    2832                 :     }
    2833               0 :     printf_stderr("\n");
    2834               0 : }
    2835                 : 
    2836                 : void
    2837               0 : GLContext::ReportOutstandingNames()
    2838                 : {
    2839               0 :     printf_stderr("== GLContext %p ==\n", this);
    2840               0 :     printf_stderr("Outstanding Textures:\n");
    2841               0 :     ReportArrayContents(mTrackedTextures);
    2842               0 :     printf_stderr("Outstanding Buffers:\n");
    2843               0 :     ReportArrayContents(mTrackedBuffers);
    2844               0 :     printf_stderr("Outstanding Programs:\n");
    2845               0 :     ReportArrayContents(mTrackedPrograms);
    2846               0 :     printf_stderr("Outstanding Shaders:\n");
    2847               0 :     ReportArrayContents(mTrackedShaders);
    2848               0 :     printf_stderr("Outstanding Framebuffers:\n");
    2849               0 :     ReportArrayContents(mTrackedFramebuffers);
    2850               0 :     printf_stderr("Outstanding Renderbuffers:\n");
    2851               0 :     ReportArrayContents(mTrackedRenderbuffers);
    2852               0 : }
    2853                 : 
    2854                 : #endif /* DEBUG */
    2855                 : 
    2856                 : } /* namespace gl */
    2857            4392 : } /* namespace mozilla */

Generated by: LCOV version 1.7