LCOV - app.info - gfx/layers/opengl/LayerManagerOGL.cpp

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-07-07 | 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