LCOV - code coverage report
Current view: directory - gfx/layers/opengl - ContainerLayerOGL.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 188 0 0.0 %
Date: 2012-06-02 Functions: 29 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                 :  *
      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 "ContainerLayerOGL.h"
      39                 : #include "gfxUtils.h"
      40                 : 
      41                 : namespace mozilla {
      42                 : namespace layers {
      43                 : 
      44                 : template<class Container>
      45                 : static void
      46               0 : ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter)
      47                 : {
      48               0 :   aChild->SetParent(aContainer);
      49               0 :   if (!aAfter) {
      50               0 :     Layer *oldFirstChild = aContainer->GetFirstChild();
      51               0 :     aContainer->mFirstChild = aChild;
      52               0 :     aChild->SetNextSibling(oldFirstChild);
      53               0 :     aChild->SetPrevSibling(nsnull);
      54               0 :     if (oldFirstChild) {
      55               0 :       oldFirstChild->SetPrevSibling(aChild);
      56                 :     } else {
      57               0 :       aContainer->mLastChild = aChild;
      58                 :     }
      59               0 :     NS_ADDREF(aChild);
      60               0 :     aContainer->DidInsertChild(aChild);
      61               0 :     return;
      62                 :   }
      63               0 :   for (Layer *child = aContainer->GetFirstChild(); 
      64                 :        child; child = child->GetNextSibling()) {
      65               0 :     if (aAfter == child) {
      66               0 :       Layer *oldNextSibling = child->GetNextSibling();
      67               0 :       child->SetNextSibling(aChild);
      68               0 :       aChild->SetNextSibling(oldNextSibling);
      69               0 :       if (oldNextSibling) {
      70               0 :         oldNextSibling->SetPrevSibling(aChild);
      71                 :       } else {
      72               0 :         aContainer->mLastChild = aChild;
      73                 :       }
      74               0 :       aChild->SetPrevSibling(child);
      75               0 :       NS_ADDREF(aChild);
      76               0 :       aContainer->DidInsertChild(aChild);
      77               0 :       return;
      78                 :     }
      79                 :   }
      80               0 :   NS_WARNING("Failed to find aAfter layer!");
      81                 : }
      82                 : 
      83                 : template<class Container>
      84                 : static void
      85               0 : ContainerRemoveChild(Container* aContainer, Layer* aChild)
      86                 : {
      87               0 :   if (aContainer->GetFirstChild() == aChild) {
      88               0 :     aContainer->mFirstChild = aContainer->GetFirstChild()->GetNextSibling();
      89               0 :     if (aContainer->mFirstChild) {
      90               0 :       aContainer->mFirstChild->SetPrevSibling(nsnull);
      91                 :     } else {
      92               0 :       aContainer->mLastChild = nsnull;
      93                 :     }
      94               0 :     aChild->SetNextSibling(nsnull);
      95               0 :     aChild->SetPrevSibling(nsnull);
      96               0 :     aChild->SetParent(nsnull);
      97               0 :     aContainer->DidRemoveChild(aChild);
      98               0 :     NS_RELEASE(aChild);
      99               0 :     return;
     100                 :   }
     101               0 :   Layer *lastChild = nsnull;
     102               0 :   for (Layer *child = aContainer->GetFirstChild(); child; 
     103                 :        child = child->GetNextSibling()) {
     104               0 :     if (child == aChild) {
     105                 :       // We're sure this is not our first child. So lastChild != NULL.
     106               0 :       lastChild->SetNextSibling(child->GetNextSibling());
     107               0 :       if (child->GetNextSibling()) {
     108               0 :         child->GetNextSibling()->SetPrevSibling(lastChild);
     109                 :       } else {
     110               0 :         aContainer->mLastChild = lastChild;
     111                 :       }
     112               0 :       child->SetNextSibling(nsnull);
     113               0 :       child->SetPrevSibling(nsnull);
     114               0 :       child->SetParent(nsnull);
     115               0 :       aContainer->DidRemoveChild(aChild);
     116               0 :       NS_RELEASE(aChild);
     117               0 :       return;
     118                 :     }
     119               0 :     lastChild = child;
     120                 :   }
     121                 : }
     122                 : 
     123                 : template<class Container>
     124                 : static void
     125               0 : ContainerDestroy(Container* aContainer)
     126                 :  {
     127               0 :   if (!aContainer->mDestroyed) {
     128               0 :     while (aContainer->mFirstChild) {
     129               0 :       aContainer->GetFirstChildOGL()->Destroy();
     130               0 :       aContainer->RemoveChild(aContainer->mFirstChild);
     131                 :     }
     132               0 :     aContainer->mDestroyed = true;
     133                 :   }
     134               0 : }
     135                 : 
     136                 : template<class Container>
     137                 : static void
     138               0 : ContainerCleanupResources(Container* aContainer)
     139                 : {
     140               0 :   for (Layer* l = aContainer->GetFirstChild(); l; l = l->GetNextSibling()) {
     141               0 :     LayerOGL* layerToRender = static_cast<LayerOGL*>(l->ImplData());
     142               0 :     layerToRender->CleanupResources();
     143                 :   }
     144               0 : }
     145                 : 
     146                 : static inline LayerOGL*
     147                 : GetNextSibling(LayerOGL* aLayer)
     148                 : {
     149                 :    Layer* layer = aLayer->GetLayer()->GetNextSibling();
     150                 :    return layer ? static_cast<LayerOGL*>(layer->
     151                 :                                          ImplData())
     152                 :                  : nsnull;
     153                 : }
     154                 : 
     155                 : static bool
     156               0 : HasOpaqueAncestorLayer(Layer* aLayer)
     157                 : {
     158               0 :   for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
     159               0 :     if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
     160               0 :       return true;
     161                 :   }
     162               0 :   return false;
     163                 : }
     164                 : 
     165                 : template<class Container>
     166                 : static void
     167                 : ContainerRender(Container* aContainer,
     168                 :                 int aPreviousFrameBuffer,
     169                 :                 const nsIntPoint& aOffset,
     170               0 :                 LayerManagerOGL* aManager)
     171                 : {
     172                 :   /**
     173                 :    * Setup our temporary texture for rendering the contents of this container.
     174                 :    */
     175                 :   GLuint containerSurface;
     176                 :   GLuint frameBuffer;
     177                 : 
     178               0 :   nsIntPoint childOffset(aOffset);
     179               0 :   nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
     180                 : 
     181               0 :   nsIntRect cachedScissor = aContainer->gl()->ScissorRect();
     182               0 :   aContainer->gl()->PushScissorRect();
     183               0 :   aContainer->mSupportsComponentAlphaChildren = false;
     184                 : 
     185               0 :   float opacity = aContainer->GetEffectiveOpacity();
     186               0 :   const gfx3DMatrix& transform = aContainer->GetEffectiveTransform();
     187               0 :   bool needsFramebuffer = aContainer->UseIntermediateSurface();
     188               0 :   if (needsFramebuffer) {
     189               0 :     LayerManagerOGL::InitMode mode = LayerManagerOGL::InitModeClear;
     190               0 :     nsIntRect framebufferRect = visibleRect;
     191               0 :     if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 && 
     192                 :         (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
     193                 :     {
     194                 :       // don't need a background, we're going to paint all opaque stuff
     195               0 :       aContainer->mSupportsComponentAlphaChildren = true;
     196               0 :       mode = LayerManagerOGL::InitModeNone;
     197                 :     } else {
     198               0 :       const gfx3DMatrix& transform3D = aContainer->GetEffectiveTransform();
     199               0 :       gfxMatrix transform;
     200                 :       // If we have an opaque ancestor layer, then we can be sure that
     201                 :       // all the pixels we draw into are either opaque already or will be
     202                 :       // covered by something opaque. Otherwise copying up the background is
     203                 :       // not safe.
     204               0 :       if (HasOpaqueAncestorLayer(aContainer) &&
     205                 :           transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
     206               0 :         mode = LayerManagerOGL::InitModeCopy;
     207               0 :         framebufferRect.x += transform.x0;
     208               0 :         framebufferRect.y += transform.y0;
     209               0 :         aContainer->mSupportsComponentAlphaChildren = true;
     210                 :       }
     211                 :     }
     212                 : 
     213               0 :     aContainer->gl()->PushViewportRect();
     214               0 :     framebufferRect -= childOffset; 
     215               0 :     aManager->CreateFBOWithTexture(framebufferRect,
     216                 :                                    mode,
     217                 :                                    aPreviousFrameBuffer,
     218                 :                                    &frameBuffer,
     219                 :                                    &containerSurface);
     220               0 :     childOffset.x = visibleRect.x;
     221               0 :     childOffset.y = visibleRect.y;
     222                 :   } else {
     223               0 :     frameBuffer = aPreviousFrameBuffer;
     224               0 :     aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) ||
     225                 :       (aContainer->GetParent() && aContainer->GetParent()->SupportsComponentAlphaChildren());
     226                 :   }
     227                 : 
     228               0 :   nsAutoTArray<Layer*, 12> children;
     229               0 :   aContainer->SortChildrenBy3DZOrder(children);
     230                 : 
     231                 :   /**
     232                 :    * Render this container's contents.
     233                 :    */
     234               0 :   for (PRUint32 i = 0; i < children.Length(); i++) {
     235               0 :     LayerOGL* layerToRender = static_cast<LayerOGL*>(children.ElementAt(i)->ImplData());
     236                 : 
     237               0 :     if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
     238               0 :       continue;
     239                 :     }
     240                 : 
     241                 :     nsIntRect scissorRect = layerToRender->GetLayer()->
     242               0 :         CalculateScissorRect(cachedScissor, &aManager->GetWorldTransform());
     243               0 :     if (scissorRect.IsEmpty()) {
     244               0 :       continue;
     245                 :     }
     246                 : 
     247               0 :     aContainer->gl()->fScissor(scissorRect.x, 
     248                 :                                scissorRect.y, 
     249                 :                                scissorRect.width, 
     250                 :                                scissorRect.height);
     251                 : 
     252               0 :     layerToRender->RenderLayer(frameBuffer, childOffset);
     253               0 :     aContainer->gl()->MakeCurrent();
     254                 :   }
     255                 : 
     256                 : 
     257               0 :   if (needsFramebuffer) {
     258                 :     // Unbind the current framebuffer and rebind the previous one.
     259                 : #ifdef MOZ_DUMP_PAINTING
     260               0 :     if (gfxUtils::sDumpPainting) {
     261                 :       nsRefPtr<gfxImageSurface> surf = 
     262               0 :         aContainer->gl()->GetTexImage(containerSurface, true, aManager->GetFBOLayerProgramType());
     263                 : 
     264               0 :       WriteSnapshotToDumpFile(aContainer, surf);
     265                 :     }
     266                 : #endif
     267                 :     
     268                 :     // Restore the viewport
     269               0 :     aContainer->gl()->PopViewportRect();
     270               0 :     nsIntRect viewport = aContainer->gl()->ViewportRect();
     271               0 :     aManager->SetupPipeline(viewport.width, viewport.height,
     272                 :                             LayerManagerOGL::ApplyWorldTransform);
     273               0 :     aContainer->gl()->PopScissorRect();
     274                 : 
     275               0 :     aContainer->gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
     276               0 :     aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer);
     277                 : 
     278               0 :     aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
     279                 : 
     280               0 :     aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface);
     281                 : 
     282               0 :     ColorTextureLayerProgram *rgb = aManager->GetFBOLayerProgram();
     283                 : 
     284               0 :     rgb->Activate();
     285               0 :     rgb->SetLayerQuadRect(visibleRect);
     286               0 :     rgb->SetLayerTransform(transform);
     287               0 :     rgb->SetLayerOpacity(opacity);
     288               0 :     rgb->SetRenderOffset(aOffset);
     289               0 :     rgb->SetTextureUnit(0);
     290                 : 
     291               0 :     if (rgb->GetTexCoordMultiplierUniformLocation() != -1) {
     292                 :       // 2DRect case, get the multiplier right for a sampler2DRect
     293               0 :       float f[] = { float(visibleRect.width), float(visibleRect.height) };
     294               0 :       rgb->SetUniform(rgb->GetTexCoordMultiplierUniformLocation(),
     295                 :                       2, f);
     296                 :     }
     297                 : 
     298                 :     // Drawing is always flipped, but when copying between surfaces we want to avoid
     299                 :     // this. Pass true for the flip parameter to introduce a second flip
     300                 :     // that cancels the other one out.
     301               0 :     aManager->BindAndDrawQuad(rgb, true);
     302                 : 
     303                 :     // Clean up resources.  This also unbinds the texture.
     304               0 :     aContainer->gl()->fDeleteTextures(1, &containerSurface);
     305                 :   } else {
     306               0 :     aContainer->gl()->PopScissorRect();
     307                 :   }
     308               0 : }
     309                 : 
     310               0 : ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *aManager)
     311                 :   : ContainerLayer(aManager, NULL)
     312               0 :   , LayerOGL(aManager)
     313                 : {
     314               0 :   mImplData = static_cast<LayerOGL*>(this);
     315               0 : }
     316                 : 
     317               0 : ContainerLayerOGL::~ContainerLayerOGL()
     318                 : {
     319               0 :   Destroy();
     320               0 : }
     321                 : 
     322                 : void
     323               0 : ContainerLayerOGL::InsertAfter(Layer* aChild, Layer* aAfter)
     324                 : {
     325               0 :   ContainerInsertAfter(this, aChild, aAfter);
     326               0 : }
     327                 : 
     328                 : void
     329               0 : ContainerLayerOGL::RemoveChild(Layer *aChild)
     330                 : {
     331               0 :   ContainerRemoveChild(this, aChild);
     332               0 : }
     333                 : 
     334                 : void
     335               0 : ContainerLayerOGL::Destroy()
     336                 : {
     337               0 :   ContainerDestroy(this);
     338               0 : }
     339                 : 
     340                 : LayerOGL*
     341               0 : ContainerLayerOGL::GetFirstChildOGL()
     342                 : {
     343               0 :   if (!mFirstChild) {
     344               0 :     return nsnull;
     345                 :   }
     346               0 :   return static_cast<LayerOGL*>(mFirstChild->ImplData());
     347                 : }
     348                 : 
     349                 : void
     350               0 : ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
     351                 :                                const nsIntPoint& aOffset)
     352                 : {
     353               0 :   ContainerRender(this, aPreviousFrameBuffer, aOffset, mOGLManager);
     354               0 : }
     355                 : 
     356                 : void
     357               0 : ContainerLayerOGL::CleanupResources()
     358                 : {
     359               0 :   ContainerCleanupResources(this);
     360               0 : }
     361                 : 
     362               0 : ShadowContainerLayerOGL::ShadowContainerLayerOGL(LayerManagerOGL *aManager)
     363                 :   : ShadowContainerLayer(aManager, NULL)
     364               0 :   , LayerOGL(aManager)
     365                 : {
     366               0 :   mImplData = static_cast<LayerOGL*>(this);
     367               0 : }
     368                 :  
     369               0 : ShadowContainerLayerOGL::~ShadowContainerLayerOGL()
     370                 : {
     371               0 :   Destroy();
     372               0 : }
     373                 : 
     374                 : void
     375               0 : ShadowContainerLayerOGL::InsertAfter(Layer* aChild, Layer* aAfter)
     376                 : {
     377               0 :   ContainerInsertAfter(this, aChild, aAfter);
     378               0 : }
     379                 : 
     380                 : void
     381               0 : ShadowContainerLayerOGL::RemoveChild(Layer *aChild)
     382                 : {
     383               0 :   ContainerRemoveChild(this, aChild);
     384               0 : }
     385                 : 
     386                 : void
     387               0 : ShadowContainerLayerOGL::Destroy()
     388                 : {
     389               0 :   ContainerDestroy(this);
     390               0 : }
     391                 : 
     392                 : LayerOGL*
     393               0 : ShadowContainerLayerOGL::GetFirstChildOGL()
     394                 : {
     395               0 :   if (!mFirstChild) {
     396               0 :     return nsnull;
     397                 :    }
     398               0 :   return static_cast<LayerOGL*>(mFirstChild->ImplData());
     399                 : }
     400                 :  
     401                 : void
     402               0 : ShadowContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
     403                 :                                      const nsIntPoint& aOffset)
     404                 : {
     405               0 :   ContainerRender(this, aPreviousFrameBuffer, aOffset, mOGLManager);
     406               0 : }
     407                 : 
     408                 : void
     409               0 : ShadowContainerLayerOGL::CleanupResources()
     410                 : {
     411               0 :   ContainerCleanupResources(this);
     412               0 : }
     413                 : 
     414                 : } /* layers */
     415                 : } /* mozilla */

Generated by: LCOV version 1.7