LCOV - code coverage report
Current view: directory - gfx/layers/opengl - CanvasLayerOGL.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 178 0 0.0 %
Date: 2012-06-02 Functions: 18 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) 2010
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "mozilla/layers/PLayers.h"
      39                 : #include "mozilla/layers/ShadowLayers.h"
      40                 : 
      41                 : #include "gfxSharedImageSurface.h"
      42                 : 
      43                 : #include "CanvasLayerOGL.h"
      44                 : 
      45                 : #include "gfxImageSurface.h"
      46                 : #include "gfxContext.h"
      47                 : #include "GLContextProvider.h"
      48                 : #include "gfxPlatform.h"
      49                 : 
      50                 : #ifdef XP_WIN
      51                 : #include "gfxWindowsSurface.h"
      52                 : #include "WGLLibrary.h"
      53                 : #endif
      54                 : 
      55                 : #ifdef XP_MACOSX
      56                 : #include <OpenGL/OpenGL.h>
      57                 : #endif
      58                 : 
      59                 : #ifdef MOZ_X11
      60                 : #include "gfxXlibSurface.h"
      61                 : #endif
      62                 : 
      63                 : using namespace mozilla;
      64                 : using namespace mozilla::layers;
      65                 : using namespace mozilla::gl;
      66                 : 
      67                 : void
      68               0 : CanvasLayerOGL::Destroy()
      69                 : {
      70               0 :   if (!mDestroyed) {
      71               0 :     CleanupResources();
      72               0 :     mDestroyed = true;
      73                 :   }
      74               0 : }
      75                 : 
      76                 : void
      77               0 : CanvasLayerOGL::Initialize(const Data& aData)
      78                 : {
      79               0 :   NS_ASSERTION(mCanvasSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
      80                 : 
      81               0 :   if (aData.mGLContext != nsnull &&
      82                 :       aData.mSurface != nsnull)
      83                 :   {
      84               0 :     NS_WARNING("CanvasLayerOGL can't have both surface and GLContext");
      85               0 :     return;
      86                 :   }
      87                 : 
      88               0 :   mOGLManager->MakeCurrent();
      89                 : 
      90               0 :   if (aData.mDrawTarget) {
      91               0 :     mDrawTarget = aData.mDrawTarget;
      92               0 :     mNeedsYFlip = false;
      93               0 :   } else if (aData.mSurface) {
      94               0 :     mCanvasSurface = aData.mSurface;
      95               0 :     mNeedsYFlip = false;
      96                 : #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
      97               0 :     if (aData.mSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
      98               0 :         gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(aData.mSurface);
      99               0 :         mPixmap = xsurf->GetGLXPixmap();
     100               0 :         if (mPixmap) {
     101               0 :             if (aData.mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
     102               0 :                 mLayerProgram = gl::RGBALayerProgramType;
     103                 :             } else {
     104               0 :                 mLayerProgram = gl::RGBXLayerProgramType;
     105                 :             }
     106               0 :             MakeTexture();
     107                 :         }
     108                 :     }
     109                 : #endif
     110               0 :   } else if (aData.mGLContext) {
     111               0 :     if (!aData.mGLContext->IsOffscreen()) {
     112               0 :       NS_WARNING("CanvasLayerOGL with a non-offscreen GL context given");
     113               0 :       return;
     114                 :     }
     115                 : 
     116               0 :     mCanvasGLContext = aData.mGLContext;
     117               0 :     mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
     118                 : 
     119               0 :     mNeedsYFlip = true;
     120                 :   } else {
     121               0 :     NS_WARNING("CanvasLayerOGL::Initialize called without surface or GL context!");
     122               0 :     return;
     123                 :   }
     124                 : 
     125               0 :   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
     126                 :       
     127                 :   // Check the maximum texture size supported by GL. glTexImage2D supports
     128                 :   // images of up to 2 + GL_MAX_TEXTURE_SIZE
     129               0 :   GLint texSize = gl()->GetMaxTextureSize();
     130               0 :   if (mBounds.width > (2 + texSize) || mBounds.height > (2 + texSize)) {
     131               0 :     mDelayedUpdates = true;
     132               0 :     MakeTexture();
     133                 :     // This should only ever occur with 2d canvas, WebGL can't already have a texture
     134                 :     // of this size can it?
     135               0 :     NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, 
     136                 :                       "Invalid texture size when WebGL surface already exists at that size?");
     137                 :   }
     138                 : }
     139                 : 
     140                 : void
     141               0 : CanvasLayerOGL::MakeTexture()
     142                 : {
     143               0 :   if (mTexture != 0)
     144               0 :     return;
     145                 : 
     146               0 :   gl()->fGenTextures(1, &mTexture);
     147                 : 
     148               0 :   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
     149               0 :   gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     150                 : 
     151               0 :   gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
     152               0 :   gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
     153               0 :   gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
     154               0 :   gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
     155                 : }
     156                 : 
     157                 : /**
     158                 :  * Following UpdateSurface(), mTexture on context this->gl() should contain the data we want,
     159                 :  * unless mDelayedUpdates is true because of a too-large surface.
     160                 :  */
     161                 : void
     162               0 : CanvasLayerOGL::UpdateSurface()
     163                 : {
     164               0 :   if (!mDirty)
     165               0 :     return;
     166               0 :   mDirty = false;
     167                 : 
     168               0 :   if (mDestroyed || mDelayedUpdates) {
     169               0 :     return;
     170                 :   }
     171                 : 
     172                 : #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     173               0 :   if (mPixmap) {
     174               0 :     return;
     175                 :   }
     176                 : #endif
     177                 : 
     178               0 :   if (mCanvasGLContext &&
     179               0 :       mCanvasGLContext->GetContextType() == gl()->GetContextType())
     180                 :   {
     181                 :     // Can texture share, just make sure it's resolved first
     182               0 :     mCanvasGLContext->MakeCurrent();
     183               0 :     mCanvasGLContext->GuaranteeResolve();
     184                 : 
     185               0 :     if (gl()->BindOffscreenNeedsTexture(mCanvasGLContext) &&
     186                 :         mTexture == 0)
     187                 :     {
     188               0 :       mOGLManager->MakeCurrent();
     189               0 :       MakeTexture();
     190                 :     }
     191                 :   } else {
     192               0 :     nsRefPtr<gfxASurface> updatedAreaSurface;
     193               0 :     if (mDrawTarget) {
     194                 :       // TODO: This is suboptimal - We should have direct handling for the surface types instead of
     195                 :       // going via a gfxASurface.
     196               0 :       updatedAreaSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     197               0 :     } else if (mCanvasSurface) {
     198               0 :       updatedAreaSurface = mCanvasSurface;
     199               0 :     } else if (mCanvasGLContext) {
     200                 :       nsRefPtr<gfxImageSurface> updatedAreaImageSurface =
     201                 :         new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
     202               0 :                             gfxASurface::ImageFormatARGB32);
     203                 :       mCanvasGLContext->ReadPixelsIntoImageSurface(0, 0,
     204                 :                                                    mBounds.width,
     205                 :                                                    mBounds.height,
     206               0 :                                                    updatedAreaImageSurface);
     207               0 :       updatedAreaSurface = updatedAreaImageSurface;
     208                 :     }
     209                 : 
     210               0 :     mOGLManager->MakeCurrent();
     211                 :     mLayerProgram =
     212                 :       gl()->UploadSurfaceToTexture(updatedAreaSurface,
     213                 :                                    mBounds,
     214                 :                                    mTexture,
     215                 :                                    false,
     216               0 :                                    nsIntPoint(0, 0));
     217                 :   }
     218                 : }
     219                 : 
     220                 : void
     221               0 : CanvasLayerOGL::RenderLayer(int aPreviousDestination,
     222                 :                             const nsIntPoint& aOffset)
     223                 : {
     224               0 :   UpdateSurface();
     225               0 :   FireDidTransactionCallback();
     226                 : 
     227               0 :   mOGLManager->MakeCurrent();
     228                 : 
     229                 :   // XXX We're going to need a different program depending on if
     230                 :   // mGLBufferIsPremultiplied is TRUE or not.  The RGBLayerProgram
     231                 :   // assumes that it's true.
     232                 : 
     233               0 :   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
     234                 : 
     235               0 :   if (mTexture) {
     236               0 :     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     237                 :   }
     238                 : 
     239               0 :   ColorTextureLayerProgram *program = nsnull;
     240                 : 
     241                 :   bool useGLContext = mCanvasGLContext &&
     242               0 :     mCanvasGLContext->GetContextType() == gl()->GetContextType();
     243                 : 
     244               0 :   nsIntRect drawRect = mBounds;
     245                 : 
     246               0 :   if (useGLContext) {
     247               0 :     gl()->BindTex2DOffscreen(mCanvasGLContext);
     248               0 :     program = mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(), true);
     249               0 :   } else if (mDelayedUpdates) {
     250               0 :     NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "WebGL canvases should always be using full texture upload");
     251                 :     
     252               0 :     drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds());
     253                 : 
     254               0 :     nsRefPtr<gfxASurface> surf = mCanvasSurface;
     255               0 :     if (mDrawTarget) {
     256               0 :       surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     257                 :     }
     258                 : 
     259                 :     mLayerProgram =
     260                 :       gl()->UploadSurfaceToTexture(surf,
     261                 :                                    nsIntRect(0, 0, drawRect.width, drawRect.height),
     262                 :                                    mTexture,
     263                 :                                    true,
     264               0 :                                    drawRect.TopLeft());
     265                 :   }
     266                 : 
     267               0 :   if (!program) {
     268               0 :     program = mOGLManager->GetColorTextureLayerProgram(mLayerProgram);
     269                 :   }
     270                 : 
     271                 : #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     272               0 :   if (mPixmap && !mDelayedUpdates) {
     273               0 :     sGLXLibrary.BindTexImage(mPixmap);
     274                 :   }
     275                 : #endif
     276                 : 
     277               0 :   gl()->ApplyFilterToBoundTexture(mFilter);
     278                 : 
     279               0 :   program->Activate();
     280               0 :   program->SetLayerQuadRect(drawRect);
     281               0 :   program->SetLayerTransform(GetEffectiveTransform());
     282               0 :   program->SetLayerOpacity(GetEffectiveOpacity());
     283               0 :   program->SetRenderOffset(aOffset);
     284               0 :   program->SetTextureUnit(0);
     285                 : 
     286               0 :   mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false);
     287                 : 
     288                 : #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     289               0 :   if (mPixmap && !mDelayedUpdates) {
     290               0 :     sGLXLibrary.ReleaseTexImage(mPixmap);
     291                 :   }
     292                 : #endif
     293                 : 
     294               0 :   if (useGLContext) {
     295               0 :     gl()->UnbindTex2DOffscreen(mCanvasGLContext);
     296                 :   }
     297               0 : }
     298                 : 
     299                 : void
     300               0 : CanvasLayerOGL::CleanupResources()
     301                 : {
     302               0 :   if (mTexture) {
     303               0 :     GLContext* cx = mOGLManager->glForResources();
     304               0 :     cx->MakeCurrent();
     305               0 :     cx->fDeleteTextures(1, &mTexture);
     306                 :   }
     307               0 : }
     308                 : 
     309                 : 
     310               0 : ShadowCanvasLayerOGL::ShadowCanvasLayerOGL(LayerManagerOGL* aManager)
     311                 :   : ShadowCanvasLayer(aManager, nsnull)
     312                 :   , LayerOGL(aManager)
     313               0 :   , mNeedsYFlip(false)
     314                 : {
     315               0 :   mImplData = static_cast<LayerOGL*>(this);
     316               0 : }
     317                 :  
     318               0 : ShadowCanvasLayerOGL::~ShadowCanvasLayerOGL()
     319               0 : {}
     320                 : 
     321                 : void
     322               0 : ShadowCanvasLayerOGL::Initialize(const Data& aData)
     323                 : {
     324               0 :   NS_RUNTIMEABORT("Incompatibe surface type");
     325               0 : }
     326                 : 
     327                 : void
     328               0 : ShadowCanvasLayerOGL::Init(const CanvasSurface& aNewFront, bool needYFlip)
     329                 : {
     330               0 :   nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
     331                 : 
     332               0 :   mTexImage = gl()->CreateTextureImage(surf->GetSize(),
     333                 :                                        surf->GetContentType(),
     334               0 :                                        LOCAL_GL_CLAMP_TO_EDGE);
     335               0 :   mNeedsYFlip = needYFlip;
     336               0 : }
     337                 : 
     338                 : void
     339               0 : ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
     340                 :                            bool needYFlip,
     341                 :                            CanvasSurface* aNewBack)
     342                 : {
     343               0 :   if (!mDestroyed) {
     344               0 :     nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
     345               0 :     gfxIntSize sz = surf->GetSize();
     346               0 :     if (!mTexImage || mTexImage->GetSize() != sz ||
     347               0 :         mTexImage->GetContentType() != surf->GetContentType()) {
     348               0 :       Init(aNewFront, needYFlip);
     349                 :     }
     350               0 :     nsIntRegion updateRegion(nsIntRect(0, 0, sz.width, sz.height));
     351               0 :     mTexImage->DirectUpdate(surf, updateRegion);
     352                 :   }
     353                 : 
     354               0 :   *aNewBack = aNewFront;
     355               0 : }
     356                 : 
     357                 : void
     358               0 : ShadowCanvasLayerOGL::DestroyFrontBuffer()
     359                 : {
     360               0 :   mTexImage = nsnull;
     361               0 : }
     362                 : 
     363                 : void
     364               0 : ShadowCanvasLayerOGL::Disconnect()
     365                 : {
     366               0 :   Destroy();
     367               0 : }
     368                 : 
     369                 : void
     370               0 : ShadowCanvasLayerOGL::Destroy()
     371                 : {
     372               0 :   if (!mDestroyed) {
     373               0 :     mDestroyed = true;
     374               0 :     mTexImage = nsnull;
     375                 :   }
     376               0 : }
     377                 : 
     378                 : Layer*
     379               0 : ShadowCanvasLayerOGL::GetLayer()
     380                 : {
     381               0 :   return this;
     382                 : }
     383                 : 
     384                 : void
     385               0 : ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
     386                 :                                   const nsIntPoint& aOffset)
     387                 : {
     388               0 :   mOGLManager->MakeCurrent();
     389                 : 
     390                 :   ColorTextureLayerProgram *program =
     391               0 :     mOGLManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
     392                 : 
     393                 : 
     394               0 :   gfx3DMatrix effectiveTransform = GetEffectiveTransform();
     395                 : #ifdef ANDROID
     396                 :   // Bug 691354
     397                 :   // Using the LINEAR filter we get unexplained artifacts.
     398                 :   // Use NEAREST when no scaling is required.
     399                 :   gfxMatrix matrix;
     400                 :   bool is2D = GetEffectiveTransform().Is2D(&matrix);
     401                 :   if (is2D && !matrix.HasNonTranslationOrFlip()) {
     402                 :     mTexImage->SetFilter(gfxPattern::FILTER_NEAREST);
     403                 :   } else {
     404                 :     mTexImage->SetFilter(mFilter);
     405                 :   }
     406                 : #else
     407               0 :   mTexImage->SetFilter(mFilter);
     408                 : #endif
     409                 : 
     410                 : 
     411               0 :   program->Activate();
     412               0 :   program->SetLayerTransform(effectiveTransform);
     413               0 :   program->SetLayerOpacity(GetEffectiveOpacity());
     414               0 :   program->SetRenderOffset(aOffset);
     415               0 :   program->SetTextureUnit(0);
     416                 : 
     417               0 :   mTexImage->BeginTileIteration();
     418               0 :   do {
     419               0 :     TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0);
     420               0 :     program->SetLayerQuadRect(mTexImage->GetTileRect());
     421               0 :     mOGLManager->BindAndDrawQuad(program, mNeedsYFlip); // FIXME flip order of tiles?
     422               0 :   } while (mTexImage->NextTile());
     423               0 : }
     424                 : 
     425                 : void
     426               0 : ShadowCanvasLayerOGL::CleanupResources()
     427                 : {
     428               0 :   DestroyFrontBuffer();
     429               0 : }

Generated by: LCOV version 1.7