LCOV - code coverage report
Current view: directory - gfx/layers/opengl - LayerManagerOGL.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 489 0 0.0 %
Date: 2012-06-02 Functions: 40 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       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 Corporation code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Bas Schouten <bschouten@mozilla.org>
      23                 :  *   Frederic Plourde <frederic.plourde@collabora.co.uk>
      24                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "mozilla/layers/PLayers.h"
      41                 : 
      42                 : /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
      43                 : #include "mozilla/Util.h"
      44                 : 
      45                 : #include "LayerManagerOGL.h"
      46                 : #include "ThebesLayerOGL.h"
      47                 : #include "ContainerLayerOGL.h"
      48                 : #include "ImageLayerOGL.h"
      49                 : #include "ColorLayerOGL.h"
      50                 : #include "CanvasLayerOGL.h"
      51                 : #include "mozilla/TimeStamp.h"
      52                 : #include "mozilla/Preferences.h"
      53                 : 
      54                 : #include "LayerManagerOGLShaders.h"
      55                 : 
      56                 : #include "gfxContext.h"
      57                 : #include "gfxUtils.h"
      58                 : #include "gfxPlatform.h"
      59                 : #include "nsIWidget.h"
      60                 : 
      61                 : #include "GLContext.h"
      62                 : #include "GLContextProvider.h"
      63                 : 
      64                 : #include "nsIServiceManager.h"
      65                 : #include "nsIConsoleService.h"
      66                 : 
      67                 : #include "gfxCrashReporterUtils.h"
      68                 : 
      69                 : #include "sampler.h"
      70                 : 
      71                 : namespace mozilla {
      72                 : namespace layers {
      73                 : 
      74                 : using namespace mozilla::gl;
      75                 : 
      76                 : #ifdef CHECK_CURRENT_PROGRAM
      77                 : int LayerManagerOGLProgram::sCurrentProgramKey = 0;
      78                 : #endif
      79                 : 
      80                 : /**
      81                 :  * LayerManagerOGL
      82                 :  */
      83               0 : LayerManagerOGL::LayerManagerOGL(nsIWidget *aWidget)
      84                 :   : mWidget(aWidget)
      85                 :   , mWidgetSize(-1, -1)
      86                 :   , mBackBufferFBO(0)
      87                 :   , mBackBufferTexture(0)
      88                 :   , mBackBufferSize(-1, -1)
      89               0 :   , mHasBGRA(0)
      90                 : {
      91               0 : }
      92                 : 
      93               0 : LayerManagerOGL::~LayerManagerOGL()
      94                 : {
      95               0 :   Destroy();
      96               0 : }
      97                 : 
      98                 : void
      99               0 : LayerManagerOGL::Destroy()
     100                 : {
     101               0 :   if (!mDestroyed) {
     102               0 :     if (mRoot) {
     103               0 :       RootLayer()->Destroy();
     104                 :     }
     105               0 :     mRoot = nsnull;
     106                 : 
     107               0 :     CleanupResources();
     108                 : 
     109               0 :     mDestroyed = true;
     110                 :   }
     111               0 : }
     112                 : 
     113                 : void
     114               0 : LayerManagerOGL::CleanupResources()
     115                 : {
     116               0 :   if (!mGLContext)
     117               0 :     return;
     118                 : 
     119               0 :   if (mRoot) {
     120               0 :     RootLayer()->CleanupResources();
     121                 :   }
     122                 : 
     123               0 :   nsRefPtr<GLContext> ctx = mGLContext->GetSharedContext();
     124               0 :   if (!ctx) {
     125               0 :     ctx = mGLContext;
     126                 :   }
     127                 : 
     128               0 :   ctx->MakeCurrent();
     129                 : 
     130               0 :   for (unsigned int i = 0; i < mPrograms.Length(); ++i)
     131               0 :     delete mPrograms[i];
     132               0 :   mPrograms.Clear();
     133                 : 
     134               0 :   ctx->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
     135                 : 
     136               0 :   if (mBackBufferFBO) {
     137               0 :     ctx->fDeleteFramebuffers(1, &mBackBufferFBO);
     138               0 :     mBackBufferFBO = 0;
     139                 :   }
     140                 : 
     141               0 :   if (mBackBufferTexture) {
     142               0 :     ctx->fDeleteTextures(1, &mBackBufferTexture);
     143               0 :     mBackBufferTexture = 0;
     144                 :   }
     145                 : 
     146               0 :   if (mQuadVBO) {
     147               0 :     ctx->fDeleteBuffers(1, &mQuadVBO);
     148               0 :     mQuadVBO = 0;
     149                 :   }
     150                 : 
     151               0 :   mGLContext = nsnull;
     152                 : }
     153                 : 
     154                 : already_AddRefed<mozilla::gl::GLContext>
     155               0 : LayerManagerOGL::CreateContext()
     156                 : {
     157               0 :   nsRefPtr<GLContext> context;
     158                 : 
     159                 : #ifdef XP_WIN
     160                 :   if (PR_GetEnv("MOZ_LAYERS_PREFER_EGL")) {
     161                 :     printf_stderr("Trying GL layers...\n");
     162                 :     context = gl::GLContextProviderEGL::CreateForWindow(mWidget);
     163                 :   }
     164                 : #endif
     165                 : 
     166               0 :   if (!context)
     167               0 :     context = gl::GLContextProvider::CreateForWindow(mWidget);
     168                 : 
     169               0 :   if (!context) {
     170               0 :     NS_WARNING("Failed to create LayerManagerOGL context");
     171                 :   }
     172               0 :   return context.forget();
     173                 : }
     174                 : 
     175                 : bool
     176               0 : LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext, bool force)
     177                 : {
     178               0 :   ScopedGfxFeatureReporter reporter("GL Layers", force);
     179                 : 
     180                 :   // Do not allow double intiailization
     181               0 :   NS_ABORT_IF_FALSE(mGLContext == nsnull, "Don't reiniailize layer managers");
     182                 : 
     183               0 :   if (!aContext)
     184               0 :     return false;
     185                 : 
     186               0 :   mGLContext = aContext;
     187               0 :   mGLContext->SetFlipped(true);
     188                 : 
     189               0 :   MakeCurrent();
     190                 : 
     191                 :   mHasBGRA =
     192               0 :     mGLContext->IsExtensionSupported(gl::GLContext::EXT_texture_format_BGRA8888) ||
     193               0 :     mGLContext->IsExtensionSupported(gl::GLContext::EXT_bgra);
     194                 : 
     195                 :   mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
     196               0 :                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
     197               0 :   mGLContext->fEnable(LOCAL_GL_BLEND);
     198                 : 
     199                 :   // We unfortunately can't do generic initialization here, since the
     200                 :   // concrete type actually matters.  This macro generates the
     201                 :   // initialization using a concrete type and index.
     202                 : #define SHADER_PROGRAM(penum, ptype, vsstr, fsstr) do {                           \
     203                 :     NS_ASSERTION(programIndex++ == penum, "out of order shader initialization!"); \
     204                 :     ptype *p = new ptype(mGLContext);                                             \
     205                 :     if (!p->Initialize(vsstr, fsstr)) {                                           \
     206                 :       delete p;                                                                   \
     207                 :       return false;                                                            \
     208                 :     }                                                                             \
     209                 :     mPrograms.AppendElement(p);                                                   \
     210                 :   } while (0)
     211                 : 
     212                 : 
     213                 :   // NOTE: Order matters here, and should be in the same order as the
     214                 :   // ProgramType enum!
     215                 : #ifdef DEBUG
     216               0 :   GLint programIndex = 0;
     217                 : #endif
     218                 : 
     219                 :   /* Layer programs */
     220               0 :   SHADER_PROGRAM(RGBALayerProgramType, ColorTextureLayerProgram,
     221                 :                  sLayerVS, sRGBATextureLayerFS);
     222               0 :   SHADER_PROGRAM(BGRALayerProgramType, ColorTextureLayerProgram,
     223                 :                  sLayerVS, sBGRATextureLayerFS);
     224               0 :   SHADER_PROGRAM(RGBXLayerProgramType, ColorTextureLayerProgram,
     225                 :                  sLayerVS, sRGBXTextureLayerFS);
     226               0 :   SHADER_PROGRAM(BGRXLayerProgramType, ColorTextureLayerProgram,
     227                 :                  sLayerVS, sBGRXTextureLayerFS);
     228               0 :   SHADER_PROGRAM(RGBARectLayerProgramType, ColorTextureLayerProgram,
     229                 :                  sLayerVS, sRGBARectTextureLayerFS);
     230               0 :   SHADER_PROGRAM(ColorLayerProgramType, SolidColorLayerProgram,
     231                 :                  sLayerVS, sSolidColorLayerFS);
     232               0 :   SHADER_PROGRAM(YCbCrLayerProgramType, YCbCrTextureLayerProgram,
     233                 :                  sLayerVS, sYCbCrTextureLayerFS);
     234               0 :   SHADER_PROGRAM(ComponentAlphaPass1ProgramType, ComponentAlphaTextureLayerProgram,
     235                 :                  sLayerVS, sComponentPass1FS);
     236               0 :   SHADER_PROGRAM(ComponentAlphaPass2ProgramType, ComponentAlphaTextureLayerProgram,
     237                 :                  sLayerVS, sComponentPass2FS);
     238                 :   /* Copy programs (used for final framebuffer blit) */
     239               0 :   SHADER_PROGRAM(Copy2DProgramType, CopyProgram,
     240                 :                  sCopyVS, sCopy2DFS);
     241               0 :   SHADER_PROGRAM(Copy2DRectProgramType, CopyProgram,
     242                 :                  sCopyVS, sCopy2DRectFS);
     243                 : 
     244                 : #undef SHADER_PROGRAM
     245                 : 
     246               0 :   NS_ASSERTION(programIndex == NumProgramTypes,
     247                 :                "not all programs were initialized!");
     248                 : 
     249                 :   /**
     250                 :    * We'll test the ability here to bind NPOT textures to a framebuffer, if
     251                 :    * this fails we'll try ARB_texture_rectangle.
     252                 :    */
     253               0 :   mGLContext->fGenFramebuffers(1, &mBackBufferFBO);
     254                 : 
     255                 :   GLenum textureTargets[] = {
     256                 :     LOCAL_GL_TEXTURE_2D,
     257                 : #ifndef USE_GLES2
     258                 :     LOCAL_GL_TEXTURE_RECTANGLE_ARB
     259                 : #endif
     260               0 :   };
     261                 : 
     262               0 :   mFBOTextureTarget = LOCAL_GL_NONE;
     263                 : 
     264               0 :   for (PRUint32 i = 0; i < ArrayLength(textureTargets); i++) {
     265               0 :     GLenum target = textureTargets[i];
     266               0 :     mGLContext->fGenTextures(1, &mBackBufferTexture);
     267               0 :     mGLContext->fBindTexture(target, mBackBufferTexture);
     268                 :     mGLContext->fTexParameteri(target,
     269                 :                                LOCAL_GL_TEXTURE_MIN_FILTER,
     270               0 :                                LOCAL_GL_NEAREST);
     271                 :     mGLContext->fTexParameteri(target,
     272                 :                                LOCAL_GL_TEXTURE_MAG_FILTER,
     273               0 :                                LOCAL_GL_NEAREST);
     274                 :     mGLContext->fTexImage2D(target,
     275                 :                             0,
     276                 :                             LOCAL_GL_RGBA,
     277                 :                             5, 3, /* sufficiently NPOT */
     278                 :                             0,
     279                 :                             LOCAL_GL_RGBA,
     280                 :                             LOCAL_GL_UNSIGNED_BYTE,
     281               0 :                             NULL);
     282                 : 
     283                 :     // unbind this texture, in preparation for binding it to the FBO
     284               0 :     mGLContext->fBindTexture(target, 0);
     285                 : 
     286               0 :     mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO);
     287                 :     mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
     288                 :                                       LOCAL_GL_COLOR_ATTACHMENT0,
     289                 :                                       target,
     290                 :                                       mBackBufferTexture,
     291               0 :                                       0);
     292                 : 
     293               0 :     if (mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) ==
     294                 :         LOCAL_GL_FRAMEBUFFER_COMPLETE)
     295                 :     {
     296               0 :       mFBOTextureTarget = target;
     297               0 :       break;
     298                 :     }
     299                 : 
     300                 :     // We weren't succesful with this texture, so we don't need it
     301                 :     // any more.
     302               0 :     mGLContext->fDeleteTextures(1, &mBackBufferTexture);
     303                 :   }
     304                 : 
     305               0 :   if (mFBOTextureTarget == LOCAL_GL_NONE) {
     306                 :     /* Unable to find a texture target that works with FBOs and NPOT textures */
     307               0 :     return false;
     308                 :   }
     309                 : 
     310               0 :   mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
     311                 : 
     312               0 :   if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
     313                 :     /* If we're using TEXTURE_RECTANGLE, then we must have the ARB
     314                 :      * extension -- the EXT variant does not provide support for
     315                 :      * texture rectangle access inside GLSL (sampler2DRect,
     316                 :      * texture2DRect).
     317                 :      */
     318               0 :     if (!mGLContext->IsExtensionSupported(gl::GLContext::ARB_texture_rectangle))
     319               0 :       return false;
     320                 :   }
     321                 : 
     322                 :   // If we're double-buffered, we don't need this fbo anymore.
     323               0 :   if (mGLContext->IsDoubleBuffered()) {
     324               0 :     mGLContext->fDeleteFramebuffers(1, &mBackBufferFBO);
     325               0 :     mBackBufferFBO = 0;
     326                 :   }
     327                 : 
     328                 :   // back to default framebuffer, to avoid confusion
     329               0 :   mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
     330                 : 
     331                 :   /* Create a simple quad VBO */
     332                 : 
     333               0 :   mGLContext->fGenBuffers(1, &mQuadVBO);
     334               0 :   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
     335                 : 
     336                 :   GLfloat vertices[] = {
     337                 :     /* First quad vertices */
     338                 :     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
     339                 :     /* Then quad texcoords */
     340                 :     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
     341                 :     /* Then flipped quad texcoords */
     342                 :     0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
     343               0 :   };
     344               0 :   mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(vertices), vertices, LOCAL_GL_STATIC_DRAW);
     345               0 :   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     346                 : 
     347                 :   nsCOMPtr<nsIConsoleService>
     348               0 :     console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
     349                 : 
     350               0 :   if (console) {
     351               0 :     nsString msg;
     352                 :     msg +=
     353               0 :       NS_LITERAL_STRING("OpenGL LayerManager Initialized Succesfully.\nVersion: ");
     354                 :     msg += NS_ConvertUTF8toUTF16(
     355               0 :       nsDependentCString((const char*)mGLContext->fGetString(LOCAL_GL_VERSION)));
     356               0 :     msg += NS_LITERAL_STRING("\nVendor: ");
     357                 :     msg += NS_ConvertUTF8toUTF16(
     358               0 :       nsDependentCString((const char*)mGLContext->fGetString(LOCAL_GL_VENDOR)));
     359               0 :     msg += NS_LITERAL_STRING("\nRenderer: ");
     360                 :     msg += NS_ConvertUTF8toUTF16(
     361               0 :       nsDependentCString((const char*)mGLContext->fGetString(LOCAL_GL_RENDERER)));
     362               0 :     msg += NS_LITERAL_STRING("\nFBO Texture Target: ");
     363               0 :     if (mFBOTextureTarget == LOCAL_GL_TEXTURE_2D)
     364               0 :       msg += NS_LITERAL_STRING("TEXTURE_2D");
     365                 :     else
     366               0 :       msg += NS_LITERAL_STRING("TEXTURE_RECTANGLE");
     367               0 :     console->LogStringMessage(msg.get());
     368                 :   }
     369                 : 
     370               0 :   if (NS_IsMainThread()) {
     371               0 :     Preferences::AddBoolVarCache(&sDrawFPS, "layers.acceleration.draw-fps");
     372                 :   } else {
     373                 :     // We have to dispatch an event to the main thread to read the pref.
     374               0 :     class ReadDrawFPSPref : public nsRunnable {
     375                 :     public:
     376               0 :       NS_IMETHOD Run()
     377                 :       {
     378               0 :         Preferences::AddBoolVarCache(&sDrawFPS, "layers.acceleration.draw-fps");
     379               0 :         return NS_OK;
     380                 :       }
     381                 :     };
     382               0 :     NS_DispatchToMainThread(new ReadDrawFPSPref());
     383                 :   }
     384                 : 
     385               0 :   reporter.SetSuccessful();
     386               0 :   return true;
     387                 : }
     388                 : 
     389                 : void
     390               0 : LayerManagerOGL::SetClippingRegion(const nsIntRegion& aClippingRegion)
     391                 : {
     392               0 :   mClippingRegion = aClippingRegion;
     393               0 : }
     394                 : 
     395                 : void
     396               0 : LayerManagerOGL::BeginTransaction()
     397                 : {
     398               0 : }
     399                 : 
     400                 : void
     401               0 : LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget)
     402                 : {
     403                 : #ifdef MOZ_LAYERS_HAVE_LOG
     404               0 :   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
     405               0 :   Log();
     406                 : #endif
     407                 : 
     408               0 :   if (mDestroyed) {
     409               0 :     NS_WARNING("Call on destroyed layer manager");
     410               0 :     return;
     411                 :   }
     412                 : 
     413               0 :   mTarget = aTarget;
     414                 : }
     415                 : 
     416                 : bool
     417               0 : LayerManagerOGL::EndEmptyTransaction()
     418                 : {
     419               0 :   if (!mRoot)
     420               0 :     return false;
     421                 : 
     422               0 :   EndTransaction(nsnull, nsnull);
     423               0 :   return true;
     424                 : }
     425                 : 
     426                 : void
     427               0 : LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
     428                 :                                 void* aCallbackData,
     429                 :                                 EndTransactionFlags aFlags)
     430                 : {
     431                 : #ifdef MOZ_LAYERS_HAVE_LOG
     432               0 :   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
     433               0 :   Log();
     434                 : #endif
     435                 : 
     436               0 :   if (mDestroyed) {
     437               0 :     NS_WARNING("Call on destroyed layer manager");
     438               0 :     return;
     439                 :   }
     440                 : 
     441               0 :   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     442                 :     // The results of our drawing always go directly into a pixel buffer,
     443                 :     // so we don't need to pass any global transform here.
     444               0 :     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
     445                 : 
     446               0 :     mThebesLayerCallback = aCallback;
     447               0 :     mThebesLayerCallbackData = aCallbackData;
     448                 : 
     449               0 :     Render();
     450                 : 
     451               0 :     mThebesLayerCallback = nsnull;
     452               0 :     mThebesLayerCallbackData = nsnull;
     453                 :   }
     454                 : 
     455               0 :   mTarget = NULL;
     456                 : 
     457                 : #ifdef MOZ_LAYERS_HAVE_LOG
     458               0 :   Log();
     459               0 :   MOZ_LAYERS_LOG(("]----- EndTransaction"));
     460                 : #endif
     461                 : }
     462                 : 
     463                 : already_AddRefed<ThebesLayer>
     464               0 : LayerManagerOGL::CreateThebesLayer()
     465                 : {
     466               0 :   if (mDestroyed) {
     467               0 :     NS_WARNING("Call on destroyed layer manager");
     468               0 :     return nsnull;
     469                 :   }
     470                 : 
     471               0 :   nsRefPtr<ThebesLayer> layer = new ThebesLayerOGL(this);
     472               0 :   return layer.forget();
     473                 : }
     474                 : 
     475                 : already_AddRefed<ContainerLayer>
     476               0 : LayerManagerOGL::CreateContainerLayer()
     477                 : {
     478               0 :   if (mDestroyed) {
     479               0 :     NS_WARNING("Call on destroyed layer manager");
     480               0 :     return nsnull;
     481                 :   }
     482                 : 
     483               0 :   nsRefPtr<ContainerLayer> layer = new ContainerLayerOGL(this);
     484               0 :   return layer.forget();
     485                 : }
     486                 : 
     487                 : already_AddRefed<ImageLayer>
     488               0 : LayerManagerOGL::CreateImageLayer()
     489                 : {
     490               0 :   if (mDestroyed) {
     491               0 :     NS_WARNING("Call on destroyed layer manager");
     492               0 :     return nsnull;
     493                 :   }
     494                 : 
     495               0 :   nsRefPtr<ImageLayer> layer = new ImageLayerOGL(this);
     496               0 :   return layer.forget();
     497                 : }
     498                 : 
     499                 : already_AddRefed<ColorLayer>
     500               0 : LayerManagerOGL::CreateColorLayer()
     501                 : {
     502               0 :   if (mDestroyed) {
     503               0 :     NS_WARNING("Call on destroyed layer manager");
     504               0 :     return nsnull;
     505                 :   }
     506                 : 
     507               0 :   nsRefPtr<ColorLayer> layer = new ColorLayerOGL(this);
     508               0 :   return layer.forget();
     509                 : }
     510                 : 
     511                 : already_AddRefed<CanvasLayer>
     512               0 : LayerManagerOGL::CreateCanvasLayer()
     513                 : {
     514               0 :   if (mDestroyed) {
     515               0 :     NS_WARNING("Call on destroyed layer manager");
     516               0 :     return nsnull;
     517                 :   }
     518                 : 
     519               0 :   nsRefPtr<CanvasLayer> layer = new CanvasLayerOGL(this);
     520               0 :   return layer.forget();
     521                 : }
     522                 : 
     523                 : LayerOGL*
     524               0 : LayerManagerOGL::RootLayer() const
     525                 : {
     526               0 :   if (mDestroyed) {
     527               0 :     NS_WARNING("Call on destroyed layer manager");
     528               0 :     return nsnull;
     529                 :   }
     530                 : 
     531               0 :   return static_cast<LayerOGL*>(mRoot->ImplData());
     532                 : }
     533                 : 
     534                 : bool LayerManagerOGL::sDrawFPS = false;
     535                 : 
     536                 : /* This function tries to stick to portable C89 as much as possible
     537                 :  * so that it can be easily copied into other applications */
     538                 : void
     539               0 : LayerManagerOGL::FPSState::DrawFPS(GLContext* context, CopyProgram* copyprog)
     540                 : {
     541               0 :   fcount++;
     542                 : 
     543               0 :   int rate = 30;
     544               0 :   if (fcount >= rate) {
     545               0 :     TimeStamp now = TimeStamp::Now();
     546               0 :     TimeDuration duration = now - last;
     547               0 :     last = now;
     548               0 :     fps = rate / duration.ToSeconds() + .5;
     549               0 :     fcount = 0;
     550                 :   }
     551                 : 
     552                 :   GLint viewport[4];
     553               0 :   context->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
     554                 : 
     555                 :   static GLuint texture;
     556               0 :   if (!initialized) {
     557                 :     // Bind the number of textures we need, in this case one.
     558               0 :     context->fGenTextures(1, &texture);
     559               0 :     context->fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
     560               0 :     context->fTexParameteri(LOCAL_GL_TEXTURE_2D,LOCAL_GL_TEXTURE_MIN_FILTER,LOCAL_GL_NEAREST);
     561               0 :     context->fTexParameteri(LOCAL_GL_TEXTURE_2D,LOCAL_GL_TEXTURE_MAG_FILTER,LOCAL_GL_NEAREST);
     562                 : 
     563                 :     unsigned char text[] = {
     564                 :       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
     565                 :       0, 255, 255, 255,   0, 255, 255,   0,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255,   0, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0,
     566                 :       0, 255,   0, 255,   0,   0, 255,   0,   0,   0,   0, 255,   0,   0,   0, 255,   0, 255,   0, 255,   0, 255,   0,   0,   0, 255,   0,   0,   0,   0,   0, 255,   0, 255,   0, 255,   0, 255,   0, 255,   0,
     567                 :       0, 255,   0, 255,   0,   0, 255,   0,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0,   0,   0, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0,
     568                 :       0, 255,   0, 255,   0,   0, 255,   0,   0, 255,   0,   0,   0,   0,   0, 255,   0,   0,   0, 255,   0,   0,   0, 255,   0, 255,   0, 255,   0,   0,   0, 255,   0, 255,   0, 255,   0,   0,   0, 255,   0,
     569                 :       0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0,   0,   0, 255,   0, 255, 255, 255,   0, 255, 255, 255,   0,   0,   0, 255,   0, 255, 255, 255,   0,   0,   0, 255,   0,
     570                 :       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
     571               0 :     };
     572                 : 
     573                 :     // convert from 8 bit to 32 bit so that don't have to write the text above out in 32 bit format
     574                 :     // we rely on int being 32 bits
     575               0 :     unsigned int* buf = (unsigned int*)malloc(64 * 8 * 4);
     576               0 :     for (int i = 0; i < 7; i++) {
     577               0 :       for (int j = 0; j < 41; j++) {
     578               0 :         unsigned int purple = 0xfff000ff;
     579               0 :         unsigned int white  = 0xffffffff;
     580               0 :         buf[i * 64 + j] = (text[i * 41 + j] == 0) ? purple : white;
     581                 :       }
     582                 :     }
     583               0 :     context->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 64, 8, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf);
     584               0 :     free(buf);
     585               0 :     initialized = true;
     586                 :   }
     587                 : 
     588                 :   struct Vertex2D {
     589                 :     float x,y;
     590                 :   };
     591                 :   const Vertex2D vertices[] = {
     592               0 :     { -1.0f, 1.0f - 42.f / viewport[3] },
     593                 :     { -1.0f, 1.0f},
     594               0 :     { -1.0f + 22.f / viewport[2], 1.0f - 42.f / viewport[3] },
     595               0 :     { -1.0f + 22.f / viewport[2], 1.0f },
     596                 : 
     597               0 :     {  -1.0f + 22.f / viewport[2], 1.0f - 42.f / viewport[3] },
     598               0 :     {  -1.0f + 22.f / viewport[2], 1.0f },
     599               0 :     {  -1.0f + 44.f / viewport[2], 1.0f - 42.f / viewport[3] },
     600               0 :     {  -1.0f + 44.f / viewport[2], 1.0f },
     601                 : 
     602               0 :     { -1.0f + 44.f / viewport[2], 1.0f - 42.f / viewport[3] },
     603               0 :     { -1.0f + 44.f / viewport[2], 1.0f },
     604               0 :     { -1.0f + 66.f / viewport[2], 1.0f - 42.f / viewport[3] },
     605               0 :     { -1.0f + 66.f / viewport[2], 1.0f }
     606               0 :   };
     607                 : 
     608               0 :   int v1   = fps % 10;
     609               0 :   int v10  = (fps % 100) / 10;
     610               0 :   int v100 = (fps % 1000) / 100;
     611                 : 
     612                 :   // Feel free to comment these texture coordinates out and use one
     613                 :   // of the ones below instead, or play around with your own values.
     614                 :   const GLfloat texCoords[] = {
     615                 :     (v100 * 4.f) / 64, 7.f / 8,
     616                 :     (v100 * 4.f) / 64, 0.0f,
     617                 :     (v100 * 4.f + 4) / 64, 7.f / 8,
     618                 :     (v100 * 4.f + 4) / 64, 0.0f,
     619                 : 
     620                 :     (v10 * 4.f) / 64, 7.f / 8,
     621                 :     (v10 * 4.f) / 64, 0.0f,
     622                 :     (v10 * 4.f + 4) / 64, 7.f / 8,
     623                 :     (v10 * 4.f + 4) / 64, 0.0f,
     624                 : 
     625                 :     (v1 * 4.f) / 64, 7.f / 8,
     626                 :     (v1 * 4.f) / 64, 0.0f,
     627                 :     (v1 * 4.f + 4) / 64, 7.f / 8,
     628                 :     (v1 * 4.f + 4) / 64, 0.0f,
     629               0 :   };
     630                 : 
     631                 :   // Turn necessary features on
     632               0 :   context->fEnable(LOCAL_GL_BLEND);
     633               0 :   context->fBlendFunc(LOCAL_GL_ONE, LOCAL_GL_SRC_COLOR);
     634                 : 
     635               0 :   context->fActiveTexture(LOCAL_GL_TEXTURE0);
     636               0 :   context->fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
     637                 : 
     638               0 :   copyprog->Activate();
     639               0 :   copyprog->SetTextureUnit(0);
     640                 : 
     641                 :   // we're going to use client-side vertex arrays for this.
     642               0 :   context->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     643                 : 
     644                 :   // "COPY"
     645                 :   context->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO,
     646               0 :                               LOCAL_GL_ONE, LOCAL_GL_ZERO);
     647                 : 
     648                 :   // enable our vertex attribs; we'll call glVertexPointer below
     649                 :   // to fill with the correct data.
     650               0 :   GLint vcattr = copyprog->AttribLocation(CopyProgram::VertexCoordAttrib);
     651               0 :   GLint tcattr = copyprog->AttribLocation(CopyProgram::TexCoordAttrib);
     652                 : 
     653               0 :   context->fEnableVertexAttribArray(vcattr);
     654               0 :   context->fEnableVertexAttribArray(tcattr);
     655                 : 
     656                 :   context->fVertexAttribPointer(vcattr,
     657                 :                                 2, LOCAL_GL_FLOAT,
     658                 :                                 LOCAL_GL_FALSE,
     659               0 :                                 0, vertices);
     660                 : 
     661                 :   context->fVertexAttribPointer(tcattr,
     662                 :                                 2, LOCAL_GL_FLOAT,
     663                 :                                 LOCAL_GL_FALSE,
     664               0 :                                 0, texCoords);
     665                 : 
     666               0 :   context->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 12);
     667               0 : }
     668                 : 
     669                 : // |aTexCoordRect| is the rectangle from the texture that we want to
     670                 : // draw using the given program.  The program already has a necessary
     671                 : // offset and scale, so the geometry that needs to be drawn is a unit
     672                 : // square from 0,0 to 1,1.
     673                 : //
     674                 : // |aTexSize| is the actual size of the texture, as it can be larger
     675                 : // than the rectangle given by |aTexCoordRect|.
     676                 : void 
     677               0 : LayerManagerOGL::BindAndDrawQuadWithTextureRect(LayerProgram *aProg,
     678                 :                                                 const nsIntRect& aTexCoordRect,
     679                 :                                                 const nsIntSize& aTexSize,
     680                 :                                                 GLenum aWrapMode)
     681                 : {
     682                 :   GLuint vertAttribIndex =
     683               0 :     aProg->AttribLocation(LayerProgram::VertexAttrib);
     684                 :   GLuint texCoordAttribIndex =
     685               0 :     aProg->AttribLocation(LayerProgram::TexCoordAttrib);
     686               0 :   NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?");
     687                 : 
     688                 :   // clear any bound VBO so that glVertexAttribPointer() goes back to
     689                 :   // "pointer mode"
     690               0 :   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     691                 : 
     692                 :   // Given what we know about these textures and coordinates, we can
     693                 :   // compute fmod(t, 1.0f) to get the same texture coordinate out.  If
     694                 :   // the texCoordRect dimension is < 0 or > width/height, then we have
     695                 :   // wraparound that we need to deal with by drawing multiple quads,
     696                 :   // because we can't rely on full non-power-of-two texture support
     697                 :   // (which is required for the REPEAT wrap mode).
     698                 : 
     699               0 :   GLContext::RectTriangles rects;
     700                 : 
     701               0 :   if (aWrapMode == LOCAL_GL_REPEAT) {
     702                 :     rects.addRect(/* dest rectangle */
     703                 :                   0.0f, 0.0f, 1.0f, 1.0f,
     704                 :                   /* tex coords */
     705                 :                   aTexCoordRect.x / GLfloat(aTexSize.width),
     706                 :                   aTexCoordRect.y / GLfloat(aTexSize.height),
     707               0 :                   aTexCoordRect.XMost() / GLfloat(aTexSize.width),
     708               0 :                   aTexCoordRect.YMost() / GLfloat(aTexSize.height));
     709                 :   } else {
     710               0 :     GLContext::DecomposeIntoNoRepeatTriangles(aTexCoordRect, aTexSize, rects);
     711                 :   }
     712                 : 
     713                 :   mGLContext->fVertexAttribPointer(vertAttribIndex, 2,
     714                 :                                    LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
     715               0 :                                    rects.vertexPointer());
     716                 : 
     717                 :   mGLContext->fVertexAttribPointer(texCoordAttribIndex, 2,
     718                 :                                    LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
     719               0 :                                    rects.texCoordPointer());
     720                 : 
     721                 :   {
     722               0 :     mGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
     723                 :     {
     724               0 :       mGLContext->fEnableVertexAttribArray(vertAttribIndex);
     725                 : 
     726               0 :       mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
     727                 : 
     728               0 :       mGLContext->fDisableVertexAttribArray(vertAttribIndex);
     729                 :     }
     730               0 :     mGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
     731                 :   }
     732               0 : }
     733                 : 
     734                 : void
     735               0 : LayerManagerOGL::Render()
     736                 : {
     737               0 :   SAMPLE_LABEL("LayerManagerOGL", "Render");
     738               0 :   if (mDestroyed) {
     739               0 :     NS_WARNING("Call on destroyed layer manager");
     740                 :     return;
     741                 :   }
     742                 : 
     743               0 :   nsIntRect rect;
     744               0 :   mWidget->GetClientBounds(rect);
     745               0 :   WorldTransformRect(rect);
     746                 : 
     747               0 :   GLint width = rect.width;
     748               0 :   GLint height = rect.height;
     749                 : 
     750                 :   // We can't draw anything to something with no area
     751                 :   // so just return
     752               0 :   if (width == 0 || height == 0)
     753                 :     return;
     754                 : 
     755                 :   // If the widget size changed, we have to force a MakeCurrent
     756                 :   // to make sure that GL sees the updated widget size.
     757               0 :   if (mWidgetSize.width != width ||
     758                 :       mWidgetSize.height != height)
     759                 :   {
     760               0 :     MakeCurrent(true);
     761                 : 
     762               0 :     mWidgetSize.width = width;
     763               0 :     mWidgetSize.height = height;
     764                 :   } else {
     765               0 :     MakeCurrent();
     766                 :   }
     767                 : 
     768               0 :   SetupBackBuffer(width, height);
     769               0 :   SetupPipeline(width, height, ApplyWorldTransform);
     770                 : 
     771                 :   // Default blend function implements "OVER"
     772                 :   mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
     773               0 :                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
     774               0 :   mGLContext->fEnable(LOCAL_GL_BLEND);
     775                 : 
     776               0 :   const nsIntRect *clipRect = mRoot->GetClipRect();
     777                 : 
     778               0 :   if (clipRect) {
     779               0 :     nsIntRect r = *clipRect;
     780               0 :     WorldTransformRect(r);
     781               0 :     mGLContext->fScissor(r.x, r.y, r.width, r.height);
     782                 :   } else {
     783               0 :     mGLContext->fScissor(0, 0, width, height);
     784                 :   }
     785                 : 
     786               0 :   mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
     787                 : 
     788               0 :   mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
     789               0 :   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
     790                 : 
     791                 :   // Render our layers.
     792               0 :   RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
     793               0 :                            nsIntPoint(0, 0));
     794                 : 
     795               0 :   mWidget->DrawWindowOverlay(this, rect);
     796                 : 
     797                 : #ifdef MOZ_DUMP_PAINTING
     798               0 :   if (gfxUtils::sDumpPainting) {
     799               0 :     nsIntRect rect;
     800               0 :     mWidget->GetBounds(rect);
     801               0 :     nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(rect.Size(), gfxASurface::CONTENT_COLOR_ALPHA);
     802               0 :     nsRefPtr<gfxContext> ctx = new gfxContext(surf);
     803               0 :     CopyToTarget(ctx);
     804                 : 
     805               0 :     WriteSnapshotToDumpFile(this, surf);
     806                 :   }
     807                 : #endif
     808                 : 
     809               0 :   if (mTarget) {
     810               0 :     CopyToTarget(mTarget);
     811               0 :     mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     812                 :     return;
     813                 :   }
     814                 : 
     815               0 :   if (sDrawFPS) {
     816               0 :     mFPS.DrawFPS(mGLContext, GetCopy2DProgram());
     817                 :   }
     818                 : 
     819               0 :   if (mGLContext->IsDoubleBuffered()) {
     820               0 :     mGLContext->SwapBuffers();
     821               0 :     LayerManager::PostPresent();
     822               0 :     mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     823                 :     return;
     824                 :   }
     825                 : 
     826               0 :   mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
     827                 : 
     828               0 :   mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
     829                 : 
     830               0 :   CopyProgram *copyprog = GetCopy2DProgram();
     831                 : 
     832               0 :   if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
     833               0 :     copyprog = GetCopy2DRectProgram();
     834                 :   }
     835                 : 
     836               0 :   mGLContext->fBindTexture(mFBOTextureTarget, mBackBufferTexture);
     837                 : 
     838               0 :   copyprog->Activate();
     839               0 :   copyprog->SetTextureUnit(0);
     840                 : 
     841               0 :   if (copyprog->GetTexCoordMultiplierUniformLocation() != -1) {
     842               0 :     float f[] = { float(width), float(height) };
     843               0 :     copyprog->SetUniform(copyprog->GetTexCoordMultiplierUniformLocation(),
     844               0 :                          2, f);
     845                 :   }
     846                 : 
     847                 :   // we're going to use client-side vertex arrays for this.
     848               0 :   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     849                 : 
     850                 :   // "COPY"
     851                 :   mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO,
     852               0 :                                  LOCAL_GL_ONE, LOCAL_GL_ZERO);
     853                 : 
     854                 :   // enable our vertex attribs; we'll call glVertexPointer below
     855                 :   // to fill with the correct data.
     856               0 :   GLint vcattr = copyprog->AttribLocation(CopyProgram::VertexCoordAttrib);
     857               0 :   GLint tcattr = copyprog->AttribLocation(CopyProgram::TexCoordAttrib);
     858                 : 
     859               0 :   mGLContext->fEnableVertexAttribArray(vcattr);
     860               0 :   mGLContext->fEnableVertexAttribArray(tcattr);
     861                 : 
     862                 :   const nsIntRect *r;
     863               0 :   nsIntRegionRectIterator iter(mClippingRegion);
     864                 : 
     865               0 :   while ((r = iter.Next()) != nsnull) {
     866               0 :     nsIntRect cRect = *r; r = &cRect;
     867               0 :     WorldTransformRect(cRect);
     868               0 :     float left = (GLfloat)r->x / width;
     869               0 :     float right = (GLfloat)r->XMost() / width;
     870               0 :     float top = (GLfloat)r->y / height;
     871               0 :     float bottom = (GLfloat)r->YMost() / height;
     872                 : 
     873                 :     float vertices[] = { left * 2.0f - 1.0f,
     874                 :                          -(top * 2.0f - 1.0f),
     875                 :                          right * 2.0f - 1.0f,
     876                 :                          -(top * 2.0f - 1.0f),
     877                 :                          left * 2.0f - 1.0f,
     878                 :                          -(bottom * 2.0f - 1.0f),
     879                 :                          right * 2.0f - 1.0f,
     880               0 :                          -(bottom * 2.0f - 1.0f) };
     881                 : 
     882                 :     // Use flipped texture coordinates since our
     883                 :     // projection matrix also has a flip and we
     884                 :     // need to cancel that out.
     885                 :     float coords[] = { left, bottom,
     886                 :                        right, bottom,
     887                 :                        left, top,
     888               0 :                        right, top };
     889                 : 
     890                 :     mGLContext->fVertexAttribPointer(vcattr,
     891                 :                                      2, LOCAL_GL_FLOAT,
     892                 :                                      LOCAL_GL_FALSE,
     893               0 :                                      0, vertices);
     894                 : 
     895                 :     mGLContext->fVertexAttribPointer(tcattr,
     896                 :                                      2, LOCAL_GL_FLOAT,
     897                 :                                      LOCAL_GL_FALSE,
     898               0 :                                      0, coords);
     899                 : 
     900               0 :     mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
     901                 :   }
     902                 : 
     903               0 :   mGLContext->fDisableVertexAttribArray(vcattr);
     904               0 :   mGLContext->fDisableVertexAttribArray(tcattr);
     905                 : 
     906               0 :   mGLContext->fFlush();
     907               0 :   mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     908                 : }
     909                 : 
     910                 : void
     911               0 : LayerManagerOGL::SetWorldTransform(const gfxMatrix& aMatrix)
     912                 : {
     913               0 :   NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(),
     914                 :                "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles");
     915               0 :   NS_ASSERTION(!aMatrix.HasNonIntegerScale(),
     916                 :                "SetWorldTransform only accepts matrices with integer scale");
     917                 : 
     918               0 :   mWorldMatrix = aMatrix;
     919               0 : }
     920                 : 
     921                 : gfxMatrix&
     922               0 : LayerManagerOGL::GetWorldTransform(void)
     923                 : {
     924               0 :   return mWorldMatrix;
     925                 : }
     926                 : 
     927                 : void
     928               0 : LayerManagerOGL::WorldTransformRect(nsIntRect& aRect)
     929                 : {
     930               0 :   gfxRect grect(aRect.x, aRect.y, aRect.width, aRect.height);
     931               0 :   grect = mWorldMatrix.TransformBounds(grect);
     932               0 :   aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height());
     933               0 : }
     934                 : 
     935                 : void
     936               0 : LayerManagerOGL::SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy)
     937                 : {
     938                 :   // Set the viewport correctly. 
     939               0 :   mGLContext->fViewport(0, 0, aWidth, aHeight);
     940                 : 
     941                 :   // We flip the view matrix around so that everything is right-side up; we're
     942                 :   // drawing directly into the window's back buffer, so this keeps things
     943                 :   // looking correct.
     944                 :   //
     945                 :   // XXX: We keep track of whether the window size changed, so we could skip
     946                 :   // this update if it hadn't changed since the last call. We will need to
     947                 :   // track changes to aTransformPolicy and mWorldMatrix for this to work
     948                 :   // though.
     949                 : 
     950                 :   // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0,
     951                 :   // 2, 2) and flip the contents.
     952               0 :   gfxMatrix viewMatrix; 
     953               0 :   viewMatrix.Translate(-gfxPoint(1.0, -1.0));
     954               0 :   viewMatrix.Scale(2.0f / float(aWidth), 2.0f / float(aHeight));
     955               0 :   viewMatrix.Scale(1.0f, -1.0f);
     956                 : 
     957               0 :   if (aTransformPolicy == ApplyWorldTransform) {
     958               0 :     viewMatrix = mWorldMatrix * viewMatrix;
     959                 :   }
     960                 : 
     961               0 :   gfx3DMatrix matrix3d = gfx3DMatrix::From2D(viewMatrix);
     962               0 :   matrix3d._33 = 0.0f;
     963                 : 
     964               0 :   SetLayerProgramProjectionMatrix(matrix3d);
     965               0 : }
     966                 : 
     967                 : void
     968               0 : LayerManagerOGL::SetupBackBuffer(int aWidth, int aHeight)
     969                 : {
     970               0 :   if (mGLContext->IsDoubleBuffered()) {
     971               0 :     mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
     972               0 :     return;
     973                 :   }
     974                 : 
     975                 :   // Do we have a FBO of the right size already?
     976               0 :   if (mBackBufferSize.width == aWidth &&
     977                 :       mBackBufferSize.height == aHeight)
     978                 :   {
     979               0 :     mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO);
     980               0 :     return;
     981                 :   }
     982                 : 
     983                 :   // we already have a FBO, but we need to resize its texture.
     984               0 :   mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
     985               0 :   mGLContext->fBindTexture(mFBOTextureTarget, mBackBufferTexture);
     986                 :   mGLContext->fTexImage2D(mFBOTextureTarget,
     987                 :                           0,
     988                 :                           LOCAL_GL_RGBA,
     989                 :                           aWidth, aHeight,
     990                 :                           0,
     991                 :                           LOCAL_GL_RGBA,
     992                 :                           LOCAL_GL_UNSIGNED_BYTE,
     993               0 :                           NULL);
     994               0 :   mGLContext->fBindTexture(mFBOTextureTarget, 0);
     995                 : 
     996               0 :   mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackBufferFBO);
     997                 :   mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
     998                 :                                     LOCAL_GL_COLOR_ATTACHMENT0,
     999                 :                                     mFBOTextureTarget,
    1000                 :                                     mBackBufferTexture,
    1001               0 :                                     0);
    1002                 : 
    1003               0 :   GLenum result = mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    1004               0 :   if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
    1005               0 :     nsCAutoString msg;
    1006               0 :     msg.Append("Framebuffer not complete -- error 0x");
    1007               0 :     msg.AppendInt(result, 16);
    1008               0 :     NS_RUNTIMEABORT(msg.get());
    1009                 :   }
    1010                 : 
    1011               0 :   mBackBufferSize.width = aWidth;
    1012               0 :   mBackBufferSize.height = aHeight;
    1013                 : }
    1014                 : 
    1015                 : void
    1016               0 : LayerManagerOGL::CopyToTarget(gfxContext *aTarget)
    1017                 : {
    1018               0 :   nsIntRect rect;
    1019               0 :   mWidget->GetBounds(rect);
    1020               0 :   GLint width = rect.width;
    1021               0 :   GLint height = rect.height;
    1022                 : 
    1023               0 :   if ((PRInt64(width) * PRInt64(height) * PRInt64(4)) > PR_INT32_MAX) {
    1024               0 :     NS_ERROR("Widget size too big - integer overflow!");
    1025               0 :     return;
    1026                 :   }
    1027                 : 
    1028                 :   nsRefPtr<gfxImageSurface> imageSurface =
    1029                 :     new gfxImageSurface(gfxIntSize(width, height),
    1030               0 :                         gfxASurface::ImageFormatARGB32);
    1031                 : 
    1032                 :   mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER,
    1033               0 :                                mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO);
    1034                 : 
    1035                 : #ifndef USE_GLES2
    1036                 :   // GLES2 promises that binding to any custom FBO will attach
    1037                 :   // to GL_COLOR_ATTACHMENT0 attachment point.
    1038               0 :   if (mGLContext->IsDoubleBuffered()) {
    1039               0 :     mGLContext->fReadBuffer(LOCAL_GL_BACK);
    1040                 :   }
    1041                 :   else {
    1042               0 :     mGLContext->fReadBuffer(LOCAL_GL_COLOR_ATTACHMENT0);
    1043                 :   }
    1044                 : #endif
    1045                 : 
    1046               0 :   NS_ASSERTION(imageSurface->Stride() == width * 4,
    1047                 :                "Image Surfaces being created with weird stride!");
    1048                 : 
    1049               0 :   mGLContext->ReadPixelsIntoImageSurface(0, 0, width, height, imageSurface);
    1050                 : 
    1051               0 :   aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
    1052               0 :   aTarget->Scale(1.0, -1.0);
    1053               0 :   aTarget->Translate(-gfxPoint(0.0, height));
    1054               0 :   aTarget->SetSource(imageSurface);
    1055               0 :   aTarget->Paint();
    1056                 : }
    1057                 : 
    1058                 : LayerManagerOGL::ProgramType LayerManagerOGL::sLayerProgramTypes[] = {
    1059                 :   gl::RGBALayerProgramType,
    1060                 :   gl::BGRALayerProgramType,
    1061                 :   gl::RGBXLayerProgramType,
    1062                 :   gl::BGRXLayerProgramType,
    1063                 :   gl::RGBARectLayerProgramType,
    1064                 :   gl::ColorLayerProgramType,
    1065                 :   gl::YCbCrLayerProgramType,
    1066                 :   gl::ComponentAlphaPass1ProgramType,
    1067                 :   gl::ComponentAlphaPass2ProgramType
    1068                 : };
    1069                 : 
    1070                 : #define FOR_EACH_LAYER_PROGRAM(vname)                       \
    1071                 :   for (size_t lpindex = 0;                                  \
    1072                 :        lpindex < ArrayLength(sLayerProgramTypes);           \
    1073                 :        ++lpindex)                                           \
    1074                 :   {                                                         \
    1075                 :     LayerProgram *vname = static_cast<LayerProgram*>        \
    1076                 :       (mPrograms[sLayerProgramTypes[lpindex]]);             \
    1077                 :     do
    1078                 : 
    1079                 : #define FOR_EACH_LAYER_PROGRAM_END              \
    1080                 :     while (0);                                  \
    1081                 :   }                                             \
    1082                 : 
    1083                 : void
    1084               0 : LayerManagerOGL::SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix)
    1085                 : {
    1086               0 :   FOR_EACH_LAYER_PROGRAM(lp) {
    1087               0 :     lp->Activate();
    1088               0 :     lp->SetProjectionMatrix(aMatrix);
    1089                 :   } FOR_EACH_LAYER_PROGRAM_END
    1090               0 : }
    1091                 : 
    1092                 : static GLenum
    1093               0 : GetFrameBufferInternalFormat(GLContext* gl,
    1094                 :                              GLuint aCurrentFrameBuffer,
    1095                 :                              nsIWidget* aWidget)
    1096                 : {
    1097               0 :   if (aCurrentFrameBuffer == 0) { // default framebuffer
    1098               0 :     return aWidget->GetGLFrameBufferFormat();
    1099                 :   }
    1100               0 :   return LOCAL_GL_RGBA;
    1101                 : }
    1102                 : 
    1103                 : static bool
    1104               0 : AreFormatsCompatibleForCopyTexImage2D(GLenum aF1, GLenum aF2)
    1105                 : {
    1106                 :   // GL requires that the implementation has to handle copies between
    1107                 :   // different formats, so all are "compatible".  GLES does not
    1108                 :   // require that.
    1109                 : #ifdef USE_GLES2
    1110                 :   return (aF1 == aF2);
    1111                 : #else
    1112               0 :   return true;
    1113                 : #endif
    1114                 : }
    1115                 : 
    1116                 : void
    1117               0 : LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
    1118                 :                                       GLuint aCurrentFrameBuffer,
    1119                 :                                       GLuint *aFBO, GLuint *aTexture)
    1120                 : {
    1121                 :   GLuint tex, fbo;
    1122                 : 
    1123               0 :   mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
    1124               0 :   mGLContext->fGenTextures(1, &tex);
    1125               0 :   mGLContext->fBindTexture(mFBOTextureTarget, tex);
    1126               0 :   if (aInit == InitModeCopy) {
    1127                 :     // We're going to create an RGBA temporary fbo.  But to
    1128                 :     // CopyTexImage() from the current framebuffer, the framebuffer's
    1129                 :     // format has to be compatible with the new texture's.  So we
    1130                 :     // check the format of the framebuffer here and take a slow path
    1131                 :     // if it's incompatible.
    1132                 :     GLenum format =
    1133               0 :       GetFrameBufferInternalFormat(gl(), aCurrentFrameBuffer, mWidget);
    1134               0 :     if (AreFormatsCompatibleForCopyTexImage2D(format, LOCAL_GL_RGBA)) {
    1135                 :       mGLContext->fCopyTexImage2D(mFBOTextureTarget,
    1136                 :                                   0,
    1137                 :                                   LOCAL_GL_RGBA,
    1138                 :                                   aRect.x, aRect.y,
    1139                 :                                   aRect.width, aRect.height,
    1140               0 :                                   0);
    1141                 :     } else {
    1142                 :       // Curses, incompatible formats.  Take a slow path.
    1143                 :       //
    1144                 :       // XXX Technically CopyTexSubImage2D also has the requirement of
    1145                 :       // matching formats, but it doesn't seem to affect us in the
    1146                 :       // real world.
    1147                 :       mGLContext->fTexImage2D(mFBOTextureTarget,
    1148                 :                               0,
    1149                 :                               LOCAL_GL_RGBA,
    1150                 :                               aRect.width, aRect.height,
    1151                 :                               0,
    1152                 :                               LOCAL_GL_RGBA,
    1153                 :                               LOCAL_GL_UNSIGNED_BYTE,
    1154               0 :                               NULL);
    1155                 :       mGLContext->fCopyTexSubImage2D(mFBOTextureTarget,
    1156                 :                                      0,    // level
    1157                 :                                      0, 0, // offset
    1158                 :                                      aRect.x, aRect.y,
    1159               0 :                                      aRect.width, aRect.height);
    1160                 :     }
    1161                 :   } else {
    1162                 :     mGLContext->fTexImage2D(mFBOTextureTarget,
    1163                 :                             0,
    1164                 :                             LOCAL_GL_RGBA,
    1165                 :                             aRect.width, aRect.height,
    1166                 :                             0,
    1167                 :                             LOCAL_GL_RGBA,
    1168                 :                             LOCAL_GL_UNSIGNED_BYTE,
    1169               0 :                             NULL);
    1170                 :   }
    1171                 :   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MIN_FILTER,
    1172               0 :                              LOCAL_GL_LINEAR);
    1173                 :   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MAG_FILTER,
    1174               0 :                              LOCAL_GL_LINEAR);
    1175                 :   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_S, 
    1176               0 :                              LOCAL_GL_CLAMP_TO_EDGE);
    1177                 :   mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_T, 
    1178               0 :                              LOCAL_GL_CLAMP_TO_EDGE);
    1179               0 :   mGLContext->fBindTexture(mFBOTextureTarget, 0);
    1180                 : 
    1181               0 :   mGLContext->fGenFramebuffers(1, &fbo);
    1182               0 :   mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
    1183                 :   mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    1184                 :                                     LOCAL_GL_COLOR_ATTACHMENT0,
    1185                 :                                     mFBOTextureTarget,
    1186                 :                                     tex,
    1187               0 :                                     0);
    1188                 : 
    1189                 :   // Making this call to fCheckFramebufferStatus prevents a crash on
    1190                 :   // PowerVR. See bug 695246.
    1191               0 :   GLenum result = mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    1192               0 :   if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
    1193               0 :     nsCAutoString msg;
    1194               0 :     msg.Append("Framebuffer not complete -- error 0x");
    1195               0 :     msg.AppendInt(result, 16);
    1196               0 :     msg.Append(", mFBOTextureTarget 0x");
    1197               0 :     msg.AppendInt(mFBOTextureTarget, 16);
    1198               0 :     msg.Append(", aRect.width ");
    1199               0 :     msg.AppendInt(aRect.width);
    1200               0 :     msg.Append(", aRect.height ");
    1201               0 :     msg.AppendInt(aRect.height);
    1202               0 :     NS_RUNTIMEABORT(msg.get());
    1203                 :   }
    1204                 : 
    1205               0 :   SetupPipeline(aRect.width, aRect.height, DontApplyWorldTransform);
    1206               0 :   mGLContext->fScissor(0, 0, aRect.width, aRect.height);
    1207                 : 
    1208               0 :   if (aInit == InitModeClear) {
    1209               0 :     mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
    1210               0 :     mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
    1211                 :   }
    1212                 : 
    1213               0 :   *aFBO = fbo;
    1214               0 :   *aTexture = tex;
    1215               0 : }
    1216                 : 
    1217                 : already_AddRefed<ShadowThebesLayer>
    1218               0 : LayerManagerOGL::CreateShadowThebesLayer()
    1219                 : {
    1220               0 :   if (LayerManagerOGL::mDestroyed) {
    1221               0 :     NS_WARNING("Call on destroyed layer manager");
    1222               0 :     return nsnull;
    1223                 :   }
    1224               0 :   return nsRefPtr<ShadowThebesLayerOGL>(new ShadowThebesLayerOGL(this)).forget();
    1225                 : }
    1226                 : 
    1227                 : already_AddRefed<ShadowContainerLayer>
    1228               0 : LayerManagerOGL::CreateShadowContainerLayer()
    1229                 : {
    1230               0 :   if (LayerManagerOGL::mDestroyed) {
    1231               0 :     NS_WARNING("Call on destroyed layer manager");
    1232               0 :     return nsnull;
    1233                 :   }
    1234               0 :   return nsRefPtr<ShadowContainerLayerOGL>(new ShadowContainerLayerOGL(this)).forget();
    1235                 : }
    1236                 : 
    1237                 : already_AddRefed<ShadowImageLayer>
    1238               0 : LayerManagerOGL::CreateShadowImageLayer()
    1239                 : {
    1240               0 :   if (LayerManagerOGL::mDestroyed) {
    1241               0 :     NS_WARNING("Call on destroyed layer manager");
    1242               0 :     return nsnull;
    1243                 :   }
    1244               0 :   return nsRefPtr<ShadowImageLayerOGL>(new ShadowImageLayerOGL(this)).forget();
    1245                 : }
    1246                 : 
    1247                 : already_AddRefed<ShadowColorLayer>
    1248               0 : LayerManagerOGL::CreateShadowColorLayer()
    1249                 : {
    1250               0 :   if (LayerManagerOGL::mDestroyed) {
    1251               0 :     NS_WARNING("Call on destroyed layer manager");
    1252               0 :     return nsnull;
    1253                 :   }
    1254               0 :   return nsRefPtr<ShadowColorLayerOGL>(new ShadowColorLayerOGL(this)).forget();
    1255                 : }
    1256                 : 
    1257                 : already_AddRefed<ShadowCanvasLayer>
    1258               0 : LayerManagerOGL::CreateShadowCanvasLayer()
    1259                 : {
    1260               0 :   if (LayerManagerOGL::mDestroyed) {
    1261               0 :     NS_WARNING("Call on destroyed layer manager");
    1262               0 :     return nsnull;
    1263                 :   }
    1264               0 :   return nsRefPtr<ShadowCanvasLayerOGL>(new ShadowCanvasLayerOGL(this)).forget();
    1265                 : }
    1266                 : 
    1267                 : 
    1268                 : } /* layers */
    1269                 : } /* mozilla */

Generated by: LCOV version 1.7