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

LCOV - code coverage report
| Current view: | directory - gfx/layers/opengl - ThebesLayerOGL.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 428 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 52 | 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                 :  *   Vladimir Vukicevic <vladimir@pobox.com>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "mozilla/layers/PLayers.h"
          40                 :
          41                 : /* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
          42                 : #include "mozilla/Util.h"
          43                 :
          44                 : #include "mozilla/layers/ShadowLayers.h"
          45                 :
          46                 : #include "ThebesLayerBuffer.h"
          47                 : #include "ThebesLayerOGL.h"
          48                 : #include "gfxUtils.h"
          49                 : #include "gfxTeeSurface.h"
          50                 :
          51                 : namespace mozilla {
          52                 : namespace layers {
          53                 :
          54                 : using gl::GLContext;
          55                 : using gl::TextureImage;
          56                 :
          57                 : static const int ALLOW_REPEAT = ThebesLayerBuffer::ALLOW_REPEAT;
          58                 :
          59                 : // BindAndDrawQuadWithTextureRect can work with either GL_REPEAT (preferred)
          60                 : // or GL_CLAMP_TO_EDGE textures. If ALLOW_REPEAT is set in aFlags, we
          61                 : // select based on whether REPEAT is valid for non-power-of-two textures --
          62                 : // if we have NPOT support we use it, otherwise we stick with CLAMP_TO_EDGE and
          63                 : // decompose.
          64                 : // If ALLOW_REPEAT is not set, we always use GL_CLAMP_TO_EDGE.
          65                 : static already_AddRefed<TextureImage>
          66               0 : CreateClampOrRepeatTextureImage(GLContext *aGl,
          67                 :                                 const nsIntSize& aSize,
          68                 :                                 TextureImage::ContentType aContentType,
          69                 :                                 PRUint32 aFlags)
          70                 : {
          71               0 :   GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
          72               0 :   if ((aFlags & ALLOW_REPEAT) &&
          73               0 :       (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
          74               0 :        aGl->IsExtensionSupported(GLContext::OES_texture_npot)))
          75                 :   {
          76               0 :     wrapMode = LOCAL_GL_REPEAT;
          77                 :   }
          78                 :
          79               0 :   return aGl->CreateTextureImage(aSize, aContentType, wrapMode);
          80                 : }
          81                 :
          82                 : static void
          83               0 : SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
          84                 : {
          85               0 :   nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
          86               0 :   if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
          87                 :     // Destination doesn't have alpha channel; no need to set any special flags
          88                 :     return;
          89                 :   }
          90                 :
          91                 :   surface->SetSubpixelAntialiasingEnabled(
          92               0 :       !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA));
          93                 : }
          94                 :
          95                 : class ThebesLayerBufferOGL
          96                 : {
          97               0 :   NS_INLINE_DECL_REFCOUNTING(ThebesLayerBufferOGL)
          98                 : public:
          99                 :   typedef TextureImage::ContentType ContentType;
         100                 :   typedef ThebesLayerBuffer::PaintState PaintState;
         101                 :
         102               0 :   ThebesLayerBufferOGL(ThebesLayer* aLayer, LayerOGL* aOGLLayer)
         103                 :     : mLayer(aLayer)
         104               0 :     , mOGLLayer(aOGLLayer)
         105               0 :   {}
         106               0 :   virtual ~ThebesLayerBufferOGL() {}
         107                 :
         108                 :   enum { PAINT_WILL_RESAMPLE = ThebesLayerBuffer::PAINT_WILL_RESAMPLE };
         109                 :   virtual PaintState BeginPaint(ContentType aContentType,
         110                 :                                 PRUint32 aFlags) = 0;
         111                 :
         112                 :   void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager,
         113                 :                 PRUint32 aFlags);
         114                 :
         115               0 :   nsIntSize GetSize() {
         116               0 :     if (mTexImage)
         117               0 :       return mTexImage->GetSize();
         118               0 :     return nsIntSize(0, 0);
         119                 :   }
         120                 :
         121                 : protected:
         122                 :   virtual nsIntPoint GetOriginOffset() = 0;
         123                 :
         124               0 :   GLContext* gl() const { return mOGLLayer->gl(); }
         125                 :
         126                 :   ThebesLayer* mLayer;
         127                 :   LayerOGL* mOGLLayer;
         128                 :   nsRefPtr<TextureImage> mTexImage;
         129                 :   nsRefPtr<TextureImage> mTexImageOnWhite;
         130                 : };
         131                 :
         132                 : void
         133               0 : ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
         134                 :                                LayerManagerOGL* aManager,
         135                 :                                PRUint32 aFlags)
         136                 : {
         137               0 :   if (!mTexImage)
         138               0 :     return;
         139                 :
         140               0 :   if (mTexImage->InUpdate()) {
         141               0 :     mTexImage->EndUpdate();
         142                 :   }
         143                 :
         144               0 :   if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) {
         145               0 :     mTexImageOnWhite->EndUpdate();
         146                 :   }
         147                 :
         148                 : #ifdef MOZ_DUMP_PAINTING
         149               0 :   if (gfxUtils::sDumpPainting) {
         150                 :     nsRefPtr<gfxImageSurface> surf =
         151               0 :       gl()->GetTexImage(mTexImage->GetTextureID(), false, mTexImage->GetShaderProgramType());
         152                 :
         153               0 :     WriteSnapshotToDumpFile(mLayer, surf);
         154                 :   }
         155                 : #endif
         156                 :
         157               0 :   PRInt32 passes = mTexImageOnWhite ? 2 : 1;
         158               0 :   for (PRInt32 pass = 1; pass <= passes; ++pass) {
         159                 :     LayerProgram *program;
         160                 :
         161               0 :     if (passes == 2) {
         162                 :       ComponentAlphaTextureLayerProgram *alphaProgram;
         163               0 :       if (pass == 1) {
         164               0 :         alphaProgram = aManager->GetComponentAlphaPass1LayerProgram();
         165                 :         gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_ONE_MINUS_SRC_COLOR,
         166               0 :                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
         167                 :       } else {
         168               0 :         alphaProgram = aManager->GetComponentAlphaPass2LayerProgram();
         169                 :         gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE,
         170               0 :                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
         171                 :       }
         172                 :
         173               0 :       alphaProgram->Activate();
         174               0 :       alphaProgram->SetBlackTextureUnit(0);
         175               0 :       alphaProgram->SetWhiteTextureUnit(1);
         176               0 :       program = alphaProgram;
         177                 :     } else {
         178                 :       // Note BGR: Cairo's image surfaces are always in what
         179                 :       // OpenGL and our shaders consider BGR format.
         180                 :       ColorTextureLayerProgram *basicProgram =
         181               0 :         aManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
         182                 :
         183               0 :       basicProgram->Activate();
         184               0 :       basicProgram->SetTextureUnit(0);
         185               0 :       program = basicProgram;
         186                 :     }
         187                 :
         188               0 :     program->SetLayerOpacity(mLayer->GetEffectiveOpacity());
         189               0 :     program->SetLayerTransform(mLayer->GetEffectiveTransform());
         190               0 :     program->SetRenderOffset(aOffset);
         191                 :
         192               0 :     const nsIntRegion& visibleRegion = mLayer->GetEffectiveVisibleRegion();
         193               0 :     nsIntRegion tmpRegion;
         194                 :     const nsIntRegion* renderRegion;
         195               0 :     if (aFlags & PAINT_WILL_RESAMPLE) {
         196                 :       // If we're resampling, then the texture image will contain exactly the
         197                 :       // entire visible region's bounds, and we should draw it all in one quad
         198                 :       // to avoid unexpected aliasing.
         199               0 :       tmpRegion = visibleRegion.GetBounds();
         200               0 :       renderRegion = &tmpRegion;
         201                 :     } else {
         202               0 :       renderRegion = &visibleRegion;
         203                 :     }
         204                 :
         205               0 :     nsIntRegion region(*renderRegion);
         206               0 :     nsIntPoint origin = GetOriginOffset();
         207               0 :     region.MoveBy(-origin);           // translate into TexImage space, buffer origin might not be at texture (0,0)
         208                 :
         209                 :     // Figure out the intersecting draw region
         210               0 :     nsIntSize texSize = mTexImage->GetSize();
         211               0 :     nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
         212               0 :     textureRect.MoveBy(region.GetBounds().TopLeft());
         213               0 :     nsIntRegion subregion;
         214               0 :     subregion.And(region, textureRect);
         215               0 :     if (subregion.IsEmpty())  // Region is empty, nothing to draw
         216                 :       return;
         217                 :
         218               0 :     nsIntRegion screenRects;
         219               0 :     nsIntRegion regionRects;
         220                 :
         221                 :     // Collect texture/screen coordinates for drawing
         222               0 :     nsIntRegionRectIterator iter(subregion);
         223               0 :     while (const nsIntRect* iterRect = iter.Next()) {
         224               0 :         nsIntRect regionRect = *iterRect;
         225               0 :         nsIntRect screenRect = regionRect;
         226               0 :         screenRect.MoveBy(origin);
         227                 :
         228               0 :         screenRects.Or(screenRects, screenRect);
         229               0 :         regionRects.Or(regionRects, regionRect);
         230                 :     }
         231                 :
         232               0 :     mTexImage->BeginTileIteration();
         233               0 :     if (mTexImageOnWhite) {
         234               0 :       NS_ASSERTION(mTexImage->GetTileCount() == mTexImageOnWhite->GetTileCount(),
         235                 :                    "Tile count mismatch on component alpha texture");
         236               0 :       mTexImageOnWhite->BeginTileIteration();
         237                 :     }
         238                 :
         239               0 :     bool usingTiles = (mTexImage->GetTileCount() > 1);
         240               0 :     do {
         241               0 :       if (mTexImageOnWhite) {
         242               0 :         NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
         243                 :       }
         244                 :
         245               0 :       nsIntRect tileRect = mTexImage->GetTileRect();
         246                 :
         247                 :       // Bind textures.
         248               0 :       TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
         249               0 :       TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
         250                 :
         251                 :       // Draw texture. If we're using tiles, we do repeating manually, as texture
         252                 :       // repeat would cause each individual tile to repeat instead of the
         253                 :       // compound texture as a whole. This involves drawing at most 4 sections,
         254                 :       // 2 for each axis that has texture repeat.
         255               0 :       for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
         256               0 :         for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
         257               0 :           nsIntRect currentTileRect(tileRect);
         258               0 :           currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
         259                 :
         260               0 :           nsIntRegionRectIterator screenIter(screenRects);
         261               0 :           nsIntRegionRectIterator regionIter(regionRects);
         262                 :
         263                 :           const nsIntRect* screenRect;
         264                 :           const nsIntRect* regionRect;
         265               0 :           while ((screenRect = screenIter.Next()) &&
         266                 :                  (regionRect = regionIter.Next())) {
         267               0 :               nsIntRect tileScreenRect(*screenRect);
         268               0 :               nsIntRect tileRegionRect(*regionRect);
         269                 :
         270                 :               // When we're using tiles, find the intersection between the tile
         271                 :               // rect and this region rect. Tiling is then handled by the
         272                 :               // outer for-loops and modifying the tile rect.
         273               0 :               if (usingTiles) {
         274               0 :                   tileScreenRect.MoveBy(-origin);
         275               0 :                   tileScreenRect = tileScreenRect.Intersect(currentTileRect);
         276               0 :                   tileScreenRect.MoveBy(origin);
         277                 :
         278               0 :                   if (tileScreenRect.IsEmpty())
         279               0 :                     continue;
         280                 :
         281               0 :                   tileRegionRect = regionRect->Intersect(currentTileRect);
         282               0 :                   tileRegionRect.MoveBy(-currentTileRect.TopLeft());
         283                 :               }
         284                 :
         285                 : #ifdef ANDROID
         286                 :               // Bug 691354
         287                 :               // Using the LINEAR filter we get unexplained artifacts.
         288                 :               // Use NEAREST when no scaling is required.
         289                 :               gfxMatrix matrix;
         290                 :               bool is2D = mLayer->GetEffectiveTransform().Is2D(&matrix);
         291                 :               if (is2D && !matrix.HasNonTranslationOrFlip()) {
         292                 :                 gl()->ApplyFilterToBoundTexture(gfxPattern::FILTER_NEAREST);
         293                 :               } else {
         294                 :                 mTexImage->ApplyFilter();
         295                 :               }
         296                 : #endif
         297               0 :               program->SetLayerQuadRect(tileScreenRect);
         298                 :               aManager->BindAndDrawQuadWithTextureRect(program, tileRegionRect,
         299                 :                                                        tileRect.Size(),
         300               0 :                                                        mTexImage->GetWrapMode());
         301                 :           }
         302                 :         }
         303                 :       }
         304                 :
         305               0 :       if (mTexImageOnWhite)
         306               0 :           mTexImageOnWhite->NextTile();
         307               0 :     } while (mTexImage->NextTile());
         308                 :   }
         309                 :
         310               0 :   if (mTexImageOnWhite) {
         311                 :     // Restore defaults
         312                 :     gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
         313               0 :                              LOCAL_GL_ONE, LOCAL_GL_ONE);
         314                 :   }
         315                 : }
         316                 :
         317                 :
         318                 : // This implementation is the fast-path for when our TextureImage is
         319                 : // permanently backed with a server-side ASurface.  We can simply
         320                 : // reuse the ThebesLayerBuffer logic in its entirety and profit.
         321                 : class SurfaceBufferOGL : public ThebesLayerBufferOGL, private ThebesLayerBuffer
         322                 : {
         323                 : public:
         324                 :   typedef ThebesLayerBufferOGL::ContentType ContentType;
         325                 :   typedef ThebesLayerBufferOGL::PaintState PaintState;
         326                 :
         327               0 :   SurfaceBufferOGL(ThebesLayerOGL* aLayer)
         328                 :     : ThebesLayerBufferOGL(aLayer, aLayer)
         329               0 :     , ThebesLayerBuffer(SizedToVisibleBounds)
         330                 :   {
         331               0 :   }
         332               0 :   virtual ~SurfaceBufferOGL() {}
         333                 :
         334                 :   // ThebesLayerBufferOGL interface
         335               0 :   virtual PaintState BeginPaint(ContentType aContentType,
         336                 :                                 PRUint32 aFlags)
         337                 :   {
         338                 :     // Let ThebesLayerBuffer do all the hard work for us! :D
         339                 :     return ThebesLayerBuffer::BeginPaint(mLayer,
         340                 :                                          aContentType,
         341               0 :                                          aFlags);
         342                 :   }
         343                 :
         344                 :   // ThebesLayerBuffer interface
         345                 :   virtual already_AddRefed<gfxASurface>
         346               0 :   CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags)
         347                 :   {
         348               0 :     NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");
         349                 :
         350               0 :     mTexImage = CreateClampOrRepeatTextureImage(gl(), aSize, aType, aFlags);
         351               0 :     return mTexImage ? mTexImage->GetBackingSurface() : nsnull;
         352                 :   }
         353                 :
         354                 : protected:
         355               0 :   virtual nsIntPoint GetOriginOffset() {
         356               0 :     return BufferRect().TopLeft() - BufferRotation();
         357                 :   }
         358                 : };
         359                 :
         360                 :
         361                 : // This implementation is (currently) the slow-path for when we can't
         362                 : // implement pixel retaining using thebes.  This implementation and
         363                 : // the above could be unified by abstracting buffer-copy operations
         364                 : // and implementing them here using GL hacketry.
         365                 : class BasicBufferOGL : public ThebesLayerBufferOGL
         366                 : {
         367                 : public:
         368               0 :   BasicBufferOGL(ThebesLayerOGL* aLayer)
         369                 :     : ThebesLayerBufferOGL(aLayer, aLayer)
         370                 :     , mBufferRect(0,0,0,0)
         371               0 :     , mBufferRotation(0,0)
         372               0 :   {}
         373               0 :   virtual ~BasicBufferOGL() {}
         374                 :
         375                 :   virtual PaintState BeginPaint(ContentType aContentType,
         376                 :                                 PRUint32 aFlags);
         377                 :
         378                 : protected:
         379                 :   enum XSide {
         380                 :     LEFT, RIGHT
         381                 :   };
         382                 :   enum YSide {
         383                 :     TOP, BOTTOM
         384                 :   };
         385                 :   nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide);
         386                 :
         387               0 :   virtual nsIntPoint GetOriginOffset() {
         388               0 :     return mBufferRect.TopLeft() - mBufferRotation;
         389                 :   }
         390                 :
         391                 : private:
         392                 :   nsIntRect mBufferRect;
         393                 :   nsIntPoint mBufferRotation;
         394                 : };
         395                 :
         396                 : static void
         397               0 : WrapRotationAxis(PRInt32* aRotationPoint, PRInt32 aSize)
         398                 : {
         399               0 :   if (*aRotationPoint < 0) {
         400               0 :     *aRotationPoint += aSize;
         401               0 :   } else if (*aRotationPoint >= aSize) {
         402               0 :     *aRotationPoint -= aSize;
         403                 :   }
         404               0 : }
         405                 :
         406                 : nsIntRect
         407               0 : BasicBufferOGL::GetQuadrantRectangle(XSide aXSide, YSide aYSide)
         408                 : {
         409                 :   // quadrantTranslation is the amount we translate the top-left
         410                 :   // of the quadrant by to get coordinates relative to the layer
         411               0 :   nsIntPoint quadrantTranslation = -mBufferRotation;
         412               0 :   quadrantTranslation.x += aXSide == LEFT ? mBufferRect.width : 0;
         413               0 :   quadrantTranslation.y += aYSide == TOP ? mBufferRect.height : 0;
         414               0 :   return mBufferRect + quadrantTranslation;
         415                 : }
         416                 :
         417                 : static void
         418               0 : FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
         419                 :             const nsIntPoint& aOffset, const gfxRGBA& aColor)
         420                 : {
         421               0 :   nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
         422               0 :   ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
         423               0 :   gfxUtils::ClipToRegion(ctx, aRegion);
         424               0 :   ctx->SetColor(aColor);
         425               0 :   ctx->Paint();
         426               0 : }
         427                 :
         428                 : BasicBufferOGL::PaintState
         429               0 : BasicBufferOGL::BeginPaint(ContentType aContentType,
         430                 :                            PRUint32 aFlags)
         431                 : {
         432               0 :   PaintState result;
         433                 :   // We need to disable rotation if we're going to be resampled when
         434                 :   // drawing, because we might sample across the rotation boundary.
         435               0 :   bool canHaveRotation =  !(aFlags & PAINT_WILL_RESAMPLE);
         436                 :
         437               0 :   nsIntRegion validRegion = mLayer->GetValidRegion();
         438                 :
         439                 :   Layer::SurfaceMode mode;
         440                 :   ContentType contentType;
         441               0 :   nsIntRegion neededRegion;
         442                 :   bool canReuseBuffer;
         443               0 :   nsIntRect destBufferRect;
         444                 :
         445               0 :   while (true) {
         446               0 :     mode = mLayer->GetSurfaceMode();
         447               0 :     contentType = aContentType;
         448               0 :     neededRegion = mLayer->GetVisibleRegion();
         449                 :     // If we're going to resample, we need a buffer that's in clamp mode.
         450               0 :     canReuseBuffer = neededRegion.GetBounds().Size() <= mBufferRect.Size() &&
         451               0 :       mTexImage &&
         452               0 :       (!(aFlags & PAINT_WILL_RESAMPLE) ||
         453               0 :        mTexImage->GetWrapMode() == LOCAL_GL_CLAMP_TO_EDGE);
         454                 :
         455               0 :     if (canReuseBuffer) {
         456               0 :       if (mBufferRect.Contains(neededRegion.GetBounds())) {
         457                 :         // We don't need to adjust mBufferRect.
         458               0 :         destBufferRect = mBufferRect;
         459                 :       } else {
         460                 :         // The buffer's big enough but doesn't contain everything that's
         461                 :         // going to be visible. We'll move it.
         462               0 :         destBufferRect = nsIntRect(neededRegion.GetBounds().TopLeft(), mBufferRect.Size());
         463                 :       }
         464                 :     } else {
         465               0 :       destBufferRect = neededRegion.GetBounds();
         466                 :     }
         467                 :
         468               0 :     if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         469                 : #ifdef MOZ_GFX_OPTIMIZE_MOBILE
         470                 :       mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
         471                 : #else
         472               0 :       if (!mLayer->GetParent() || !mLayer->GetParent()->SupportsComponentAlphaChildren()) {
         473               0 :         mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
         474                 :       } else {
         475               0 :         contentType = gfxASurface::CONTENT_COLOR;
         476                 :       }
         477                 :  #endif
         478                 :     }
         479                 :
         480               0 :     if ((aFlags & PAINT_WILL_RESAMPLE) &&
         481               0 :         (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) ||
         482               0 :          neededRegion.GetNumRects() > 1)) {
         483                 :       // The area we add to neededRegion might not be painted opaquely
         484               0 :       if (mode == Layer::SURFACE_OPAQUE) {
         485               0 :         contentType = gfxASurface::CONTENT_COLOR_ALPHA;
         486               0 :         mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
         487                 :       }
         488                 :       // For component alpha layers, we leave contentType as CONTENT_COLOR.
         489                 :
         490                 :       // We need to validate the entire buffer, to make sure that only valid
         491                 :       // pixels are sampled
         492               0 :       neededRegion = destBufferRect;
         493                 :     }
         494                 :
         495               0 :     if (mTexImage &&
         496               0 :         (mTexImage->GetContentType() != contentType ||
         497               0 :          (mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nsnull))) {
         498                 :       // We're effectively clearing the valid region, so we need to draw
         499                 :       // the entire needed region now.
         500               0 :       result.mRegionToInvalidate = mLayer->GetValidRegion();
         501               0 :       validRegion.SetEmpty();
         502               0 :       mTexImage = nsnull;
         503               0 :       mTexImageOnWhite = nsnull;
         504               0 :       mBufferRect.SetRect(0, 0, 0, 0);
         505               0 :       mBufferRotation.MoveTo(0, 0);
         506                 :       // Restart decision process with the cleared buffer. We can only go
         507                 :       // around the loop one more iteration, since mTexImage is null now.
         508               0 :       continue;
         509                 :     }
         510                 :
         511                 :     break;
         512                 :   }
         513                 :
         514               0 :   result.mRegionToDraw.Sub(neededRegion, validRegion);
         515               0 :   if (result.mRegionToDraw.IsEmpty())
         516                 :     return result;
         517                 :
         518               0 :   if (destBufferRect.width > gl()->GetMaxTextureImageSize() ||
         519               0 :       destBufferRect.height > gl()->GetMaxTextureImageSize()) {
         520                 :     return result;
         521                 :   }
         522                 :
         523               0 :   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
         524               0 :   nsRefPtr<TextureImage> destBuffer;
         525               0 :   nsRefPtr<TextureImage> destBufferOnWhite;
         526                 :
         527               0 :   PRUint32 bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
         528               0 :   if (canReuseBuffer) {
         529               0 :     nsIntRect keepArea;
         530               0 :     if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
         531                 :       // Set mBufferRotation so that the pixels currently in mBuffer
         532                 :       // will still be rendered in the right place when mBufferRect
         533                 :       // changes to destBufferRect.
         534                 :       nsIntPoint newRotation = mBufferRotation +
         535               0 :         (destBufferRect.TopLeft() - mBufferRect.TopLeft());
         536               0 :       WrapRotationAxis(&newRotation.x, mBufferRect.width);
         537               0 :       WrapRotationAxis(&newRotation.y, mBufferRect.height);
         538               0 :       NS_ASSERTION(nsIntRect(nsIntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
         539                 :                    "newRotation out of bounds");
         540               0 :       PRInt32 xBoundary = destBufferRect.XMost() - newRotation.x;
         541               0 :       PRInt32 yBoundary = destBufferRect.YMost() - newRotation.y;
         542               0 :       if ((drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) ||
         543               0 :           (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) ||
         544               0 :           (newRotation != nsIntPoint(0,0) && !canHaveRotation)) {
         545                 :         // The stuff we need to redraw will wrap around an edge of the
         546                 :         // buffer, so we will need to do a self-copy
         547                 :         // If mBufferRotation == nsIntPoint(0,0) we could do a real
         548                 :         // self-copy but we're not going to do that in GL yet.
         549                 :         // We can't do a real self-copy because the buffer is rotated.
         550                 :         // So allocate a new buffer for the destination.
         551               0 :         destBufferRect = neededRegion.GetBounds();
         552               0 :         destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         553               0 :         if (!destBuffer)
         554                 :           return result;
         555               0 :         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         556                 :           destBufferOnWhite =
         557               0 :             CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         558               0 :           if (!destBufferOnWhite)
         559                 :             return result;
         560                 :         }
         561                 :       } else {
         562               0 :         mBufferRect = destBufferRect;
         563               0 :         mBufferRotation = newRotation;
         564                 :       }
         565                 :     } else {
         566                 :       // No pixels are going to be kept. The whole visible region
         567                 :       // will be redrawn, so we don't need to copy anything, so we don't
         568                 :       // set destBuffer.
         569               0 :       mBufferRect = destBufferRect;
         570               0 :       mBufferRotation = nsIntPoint(0,0);
         571                 :     }
         572                 :   } else {
         573                 :     // The buffer's not big enough, so allocate a new one
         574               0 :     destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         575               0 :     if (!destBuffer)
         576                 :       return result;
         577                 :
         578               0 :     if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         579                 :       destBufferOnWhite =
         580               0 :         CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         581               0 :       if (!destBufferOnWhite)
         582                 :         return result;
         583                 :     }
         584                 :   }
         585               0 :   NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
         586                 :                "If we're resampling, we need to validate the entire buffer");
         587                 :
         588               0 :   if (!destBuffer && !mTexImage) {
         589                 :     return result;
         590                 :   }
         591                 :
         592               0 :   if (destBuffer) {
         593               0 :     if (mTexImage && (mode != Layer::SURFACE_COMPONENT_ALPHA || mTexImageOnWhite)) {
         594                 :       // BlitTextureImage depends on the FBO texture target being
         595                 :       // TEXTURE_2D.  This isn't the case on some older X1600-era Radeons.
         596               0 :       if (mOGLLayer->OGLManager()->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) {
         597               0 :         nsIntRect overlap;
         598               0 :         overlap.IntersectRect(mBufferRect, destBufferRect);
         599                 :
         600               0 :         nsIntRect srcRect(overlap), dstRect(overlap);
         601               0 :         srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation);
         602               0 :         dstRect.MoveBy(- destBufferRect.TopLeft());
         603                 :
         604               0 :         if (mBufferRotation != nsIntPoint(0, 0)) {
         605                 :           // If mBuffer is rotated, then BlitTextureImage will only be copying the bottom-right section
         606                 :           // of the buffer. We need to invalidate the remaining sections so that they get redrawn too.
         607                 :           // Alternatively we could teach BlitTextureImage to rearrange the rotated segments onto
         608                 :           // the new buffer.
         609                 :
         610                 :           // When the rotated buffer is reorganised, the bottom-right section will be drawn in the top left.
         611                 :           // Find the point where this content ends.
         612                 :           nsIntPoint rotationPoint(mBufferRect.x + mBufferRect.width - mBufferRotation.x,
         613               0 :                                    mBufferRect.y + mBufferRect.height - mBufferRotation.y);
         614                 :
         615                 :           // The buffer looks like:
         616                 :           //  ______
         617                 :           // |1  |2 |  Where the center point is offset by mBufferRotation from the top-left corner.
         618                 :           // |___|__|
         619                 :           // |3  |4 |
         620                 :           // |___|__|
         621                 :           //
         622                 :           // This is drawn to the screen as:
         623                 :           //  ______
         624                 :           // |4  |3 |  Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from
         625                 :           // |___|__|  from the top left corner - rotationPoint. Since only quadrant 4 will actually be copied,
         626                 :           // |2  |1 |  we need to invalidate the others.
         627                 :           // |___|__|
         628                 :           //
         629                 :           // Quadrants 2 and 1
         630               0 :           nsIntRect bottom(mBufferRect.x, rotationPoint.y, mBufferRect.width, mBufferRotation.y);
         631                 :           // Quadrant 3
         632               0 :           nsIntRect topright(rotationPoint.x, mBufferRect.y, mBufferRotation.x, rotationPoint.y - mBufferRect.y);
         633                 :
         634               0 :           if (!bottom.IsEmpty()) {
         635               0 :             nsIntRegion temp;
         636               0 :             temp.And(destBufferRect, bottom);
         637               0 :             result.mRegionToDraw.Or(result.mRegionToDraw, temp);
         638                 :           }
         639               0 :           if (!topright.IsEmpty()) {
         640               0 :             nsIntRegion temp;
         641               0 :             temp.And(destBufferRect, topright);
         642               0 :             result.mRegionToDraw.Or(result.mRegionToDraw, temp);
         643                 :           }
         644                 :         }
         645                 :
         646               0 :         destBuffer->Resize(destBufferRect.Size());
         647                 :
         648                 :         gl()->BlitTextureImage(mTexImage, srcRect,
         649               0 :                                destBuffer, dstRect);
         650               0 :         destBuffer->MarkValid();
         651               0 :         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         652               0 :           destBufferOnWhite->Resize(destBufferRect.Size());
         653                 :           gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
         654               0 :                                  destBufferOnWhite, dstRect);
         655               0 :           destBufferOnWhite->MarkValid();
         656                 :         }
         657                 :       } else {
         658                 :         // can't blit, just draw everything
         659               0 :         destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         660               0 :         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         661                 :           destBufferOnWhite =
         662               0 :             CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         663                 :         }
         664                 :       }
         665                 :     }
         666                 :
         667               0 :     mTexImage = destBuffer.forget();
         668               0 :     if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         669               0 :       mTexImageOnWhite = destBufferOnWhite.forget();
         670                 :     }
         671               0 :     mBufferRect = destBufferRect;
         672               0 :     mBufferRotation = nsIntPoint(0,0);
         673                 :   }
         674               0 :   NS_ASSERTION(canHaveRotation || mBufferRotation == nsIntPoint(0,0),
         675                 :                "Rotation disabled, but we have nonzero rotation?");
         676                 :
         677               0 :   nsIntRegion invalidate;
         678               0 :   invalidate.Sub(mLayer->GetValidRegion(), destBufferRect);
         679               0 :   result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
         680                 :
         681                 :   // Figure out which quadrant to draw in
         682               0 :   PRInt32 xBoundary = mBufferRect.XMost() - mBufferRotation.x;
         683               0 :   PRInt32 yBoundary = mBufferRect.YMost() - mBufferRotation.y;
         684               0 :   XSide sideX = drawBounds.XMost() <= xBoundary ? RIGHT : LEFT;
         685               0 :   YSide sideY = drawBounds.YMost() <= yBoundary ? BOTTOM : TOP;
         686               0 :   nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
         687               0 :   NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants");
         688                 :
         689               0 :   nsIntPoint offset = -nsIntPoint(quadrantRect.x, quadrantRect.y);
         690                 :
         691                 :   // Make the region to draw relative to the buffer, before
         692                 :   // passing to BeginUpdate.
         693               0 :   result.mRegionToDraw.MoveBy(offset);
         694                 :   // BeginUpdate is allowed to modify the given region,
         695                 :   // if it wants more to be repainted than we request.
         696               0 :   if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
         697               0 :     nsIntRegion drawRegionCopy = result.mRegionToDraw;
         698               0 :     gfxASurface *onBlack = mTexImage->BeginUpdate(drawRegionCopy);
         699               0 :     gfxASurface *onWhite = mTexImageOnWhite->BeginUpdate(result.mRegionToDraw);
         700               0 :     NS_ASSERTION(result.mRegionToDraw == drawRegionCopy,
         701                 :                  "BeginUpdate should always modify the draw region in the same way!");
         702               0 :     FillSurface(onBlack, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(0.0, 0.0, 0.0, 1.0));
         703               0 :     FillSurface(onWhite, result.mRegionToDraw, nsIntPoint(0,0), gfxRGBA(1.0, 1.0, 1.0, 1.0));
         704               0 :     gfxASurface* surfaces[2] = { onBlack, onWhite };
         705               0 :     nsRefPtr<gfxTeeSurface> surf = new gfxTeeSurface(surfaces, ArrayLength(surfaces));
         706                 :
         707                 :     // XXX If the device offset is set on the individual surfaces instead of on
         708                 :     // the tee surface, we render in the wrong place. Why?
         709               0 :     gfxPoint deviceOffset = onBlack->GetDeviceOffset();
         710               0 :     onBlack->SetDeviceOffset(gfxPoint(0, 0));
         711               0 :     onWhite->SetDeviceOffset(gfxPoint(0, 0));
         712               0 :     surf->SetDeviceOffset(deviceOffset);
         713                 :
         714                 :     // Using this surface as a source will likely go horribly wrong, since
         715                 :     // only the onBlack surface will really be used, so alpha information will
         716                 :     // be incorrect.
         717               0 :     surf->SetAllowUseAsSource(false);
         718               0 :     result.mContext = new gfxContext(surf);
         719                 :   } else {
         720               0 :     result.mContext = new gfxContext(mTexImage->BeginUpdate(result.mRegionToDraw));
         721               0 :     if (mTexImage->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
         722               0 :       gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
         723               0 :       result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
         724               0 :       result.mContext->Paint();
         725               0 :       result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
         726                 :     }
         727                 :   }
         728               0 :   if (!result.mContext) {
         729               0 :     NS_WARNING("unable to get context for update");
         730                 :     return result;
         731                 :   }
         732               0 :   result.mContext->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
         733                 :   // Move rgnToPaint back into position so that the thebes callback
         734                 :   // gets the right coordintes.
         735               0 :   result.mRegionToDraw.MoveBy(-offset);
         736                 :
         737                 :   // If we do partial updates, we have to clip drawing to the regionToDraw.
         738                 :   // If we don't clip, background images will be fillrect'd to the region correctly,
         739                 :   // while text or lines will paint outside of the regionToDraw. This becomes apparent
         740                 :   // with concave regions. Right now the scrollbars invalidate a narrow strip of the awesomebar
         741                 :   // although they never cover it. This leads to two draw rects, the narow strip and the actually
         742                 :   // newly exposed area. It would be wise to fix this glitch in any way to have simpler
         743                 :   // clip and draw regions.
         744               0 :   gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
         745                 :
         746                 :   return result;
         747                 : }
         748                 :
         749               0 : ThebesLayerOGL::ThebesLayerOGL(LayerManagerOGL *aManager)
         750                 :   : ThebesLayer(aManager, nsnull)
         751                 :   , LayerOGL(aManager)
         752               0 :   , mBuffer(nsnull)
         753                 : {
         754               0 :   mImplData = static_cast<LayerOGL*>(this);
         755               0 : }
         756                 :
         757               0 : ThebesLayerOGL::~ThebesLayerOGL()
         758                 : {
         759               0 :   Destroy();
         760               0 : }
         761                 :
         762                 : void
         763               0 : ThebesLayerOGL::Destroy()
         764                 : {
         765               0 :   if (!mDestroyed) {
         766               0 :     mBuffer = nsnull;
         767               0 :     mDestroyed = true;
         768                 :   }
         769               0 : }
         770                 :
         771                 : bool
         772               0 : ThebesLayerOGL::CreateSurface()
         773                 : {
         774               0 :   NS_ASSERTION(!mBuffer, "buffer already created?");
         775                 :
         776               0 :   if (mVisibleRegion.IsEmpty()) {
         777               0 :     return false;
         778                 :   }
         779                 :
         780               0 :   if (gl()->TextureImageSupportsGetBackingSurface()) {
         781                 :     // use the ThebesLayerBuffer fast-path
         782               0 :     mBuffer = new SurfaceBufferOGL(this);
         783                 :   } else {
         784               0 :     mBuffer = new BasicBufferOGL(this);
         785                 :   }
         786               0 :   return true;
         787                 : }
         788                 :
         789                 : void
         790               0 : ThebesLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion)
         791                 : {
         792               0 :   if (aRegion.IsEqual(mVisibleRegion))
         793               0 :     return;
         794               0 :   ThebesLayer::SetVisibleRegion(aRegion);
         795                 : }
         796                 :
         797                 : void
         798               0 : ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion)
         799                 : {
         800               0 :   mValidRegion.Sub(mValidRegion, aRegion);
         801               0 : }
         802                 :
         803                 : void
         804               0 : ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
         805                 :                             const nsIntPoint& aOffset)
         806                 : {
         807               0 :   if (!mBuffer && !CreateSurface()) {
         808               0 :     return;
         809                 :   }
         810               0 :   NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
         811                 :
         812               0 :   mOGLManager->MakeCurrent();
         813               0 :   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
         814                 :
         815                 :   TextureImage::ContentType contentType =
         816               0 :     CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
         817               0 :                             gfxASurface::CONTENT_COLOR_ALPHA;
         818                 :
         819               0 :   PRUint32 flags = 0;
         820                 : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
         821               0 :   gfxMatrix transform2d;
         822               0 :   if (GetEffectiveTransform().Is2D(&transform2d)) {
         823               0 :     if (transform2d.HasNonIntegerTranslation()) {
         824               0 :       flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE;
         825                 :     }
         826                 :   } else {
         827               0 :     flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE;
         828                 :   }
         829                 : #endif
         830                 :
         831               0 :   Buffer::PaintState state = mBuffer->BeginPaint(contentType, flags);
         832               0 :   mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
         833                 :
         834               0 :   if (state.mContext) {
         835               0 :     state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
         836                 :
         837                 :     LayerManager::DrawThebesLayerCallback callback =
         838               0 :       mOGLManager->GetThebesLayerCallback();
         839               0 :     if (!callback) {
         840               0 :       NS_ERROR("GL should never need to update ThebesLayers in an empty transaction");
         841                 :     } else {
         842               0 :       void* callbackData = mOGLManager->GetThebesLayerCallbackData();
         843               0 :       SetAntialiasingFlags(this, state.mContext);
         844                 :       callback(this, state.mContext, state.mRegionToDraw,
         845               0 :                state.mRegionToInvalidate, callbackData);
         846                 :       // Everything that's visible has been validated. Do this instead of just
         847                 :       // OR-ing with aRegionToDraw, since that can lead to a very complex region
         848                 :       // here (OR doesn't automatically simplify to the simplest possible
         849                 :       // representation of a region.)
         850               0 :       nsIntRegion tmp;
         851               0 :       tmp.Or(mVisibleRegion, state.mRegionToDraw);
         852               0 :       mValidRegion.Or(mValidRegion, tmp);
         853                 :     }
         854                 :   }
         855                 :
         856                 :   // Drawing thebes layers can change the current context, reset it.
         857               0 :   gl()->MakeCurrent();
         858                 :
         859               0 :   gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
         860               0 :   mBuffer->RenderTo(aOffset, mOGLManager, flags);
         861                 : }
         862                 :
         863                 : Layer*
         864               0 : ThebesLayerOGL::GetLayer()
         865                 : {
         866               0 :   return this;
         867                 : }
         868                 :
         869                 : bool
         870               0 : ThebesLayerOGL::IsEmpty()
         871                 : {
         872               0 :   return !mBuffer;
         873                 : }
         874                 :
         875                 : void
         876               0 : ThebesLayerOGL::CleanupResources()
         877                 : {
         878               0 :   mBuffer = nsnull;
         879               0 : }
         880                 :
         881                 : class ShadowBufferOGL : public ThebesLayerBufferOGL
         882               0 : {
         883                 : public:
         884               0 :   ShadowBufferOGL(ShadowThebesLayerOGL* aLayer)
         885               0 :     : ThebesLayerBufferOGL(aLayer, aLayer)
         886               0 :   {}
         887                 :
         888               0 :   virtual PaintState BeginPaint(ContentType aContentType, PRUint32) {
         889               0 :     NS_RUNTIMEABORT("can't BeginPaint for a shadow layer");
         890               0 :     return PaintState();
         891                 :   }
         892                 :
         893                 :   void Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
         894                 :               const nsIntRect& aRect, const nsIntPoint& aRotation);
         895                 :
         896                 : protected:
         897               0 :   virtual nsIntPoint GetOriginOffset() {
         898               0 :     return mBufferRect.TopLeft() - mBufferRotation;
         899                 :   }
         900                 :
         901                 : private:
         902                 :   nsIntRect mBufferRect;
         903                 :   nsIntPoint mBufferRotation;
         904                 : };
         905                 :
         906                 : void
         907               0 : ShadowBufferOGL::Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
         908                 :                         const nsIntRect& aRect, const nsIntPoint& aRotation)
         909                 : {
         910               0 :   gfxIntSize size = aUpdate->GetSize();
         911               0 :   if (!mTexImage ||
         912               0 :       GetSize() != nsIntSize(size.width, size.height) ||
         913               0 :       mTexImage->GetContentType() != aUpdate->GetContentType()) {
         914                 :     // XXX we should do something here to decide whether to use REPEAT or not,
         915                 :     // but I'm not sure what
         916                 :     mTexImage = CreateClampOrRepeatTextureImage(gl(),
         917               0 :       nsIntSize(size.width, size.height), aUpdate->GetContentType(), ALLOW_REPEAT);
         918                 :   }
         919                 :
         920               0 :   nsIntRegion destRegion(aUpdated);
         921                 :   // aUpdated is in screen coordinates.  Move it so that the layer's
         922                 :   // top-left is 0,0
         923               0 :   nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft();
         924               0 :   destRegion.MoveBy(-visTopLeft);
         925                 :
         926                 :   // Correct for rotation
         927               0 :   destRegion.MoveBy(aRotation);
         928               0 :   nsIntRect destBounds = destRegion.GetBounds();
         929                 :   destRegion.MoveBy((destBounds.x >= size.width) ? -size.width : 0,
         930               0 :                     (destBounds.y >= size.height) ? -size.height : 0);
         931                 :
         932                 :   // There's code to make sure that updated regions don't cross rotation
         933                 :   // boundaries, so assert here that this is the case
         934               0 :   NS_ASSERTION(((destBounds.x % size.width) + destBounds.width <= size.width) &&
         935                 :                ((destBounds.y % size.height) + destBounds.height <= size.height),
         936                 :                "Updated region lies across rotation boundaries!");
         937                 :
         938                 :   // NB: this gfxContext must not escape EndUpdate() below
         939               0 :   mTexImage->DirectUpdate(aUpdate, destRegion);
         940                 :
         941               0 :   mBufferRect = aRect;
         942               0 :   mBufferRotation = aRotation;
         943               0 : }
         944                 :
         945               0 : ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
         946                 :   : ShadowThebesLayer(aManager, nsnull)
         947               0 :   , LayerOGL(aManager)
         948                 : {
         949               0 :   mImplData = static_cast<LayerOGL*>(this);
         950               0 : }
         951                 :
         952               0 : ShadowThebesLayerOGL::~ShadowThebesLayerOGL()
         953               0 : {}
         954                 :
         955                 : void
         956               0 : ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
         957                 :                            const nsIntRegion& aUpdatedRegion,
         958                 :                            OptionalThebesBuffer* aNewBack,
         959                 :                            nsIntRegion* aNewBackValidRegion,
         960                 :                            OptionalThebesBuffer* aReadOnlyFront,
         961                 :                            nsIntRegion* aFrontUpdatedRegion)
         962                 : {
         963               0 :   if (!mDestroyed) {
         964               0 :     if (!mBuffer) {
         965               0 :       mBuffer = new ShadowBufferOGL(this);
         966                 :     }
         967               0 :     nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
         968               0 :     mBuffer->Upload(surf, aUpdatedRegion, aNewFront.rect(), aNewFront.rotation());
         969                 :   }
         970                 :
         971               0 :   *aNewBack = aNewFront;
         972               0 :   *aNewBackValidRegion = mValidRegion;
         973               0 :   *aReadOnlyFront = null_t();
         974               0 :   aFrontUpdatedRegion->SetEmpty();
         975               0 : }
         976                 :
         977                 : void
         978               0 : ShadowThebesLayerOGL::DestroyFrontBuffer()
         979                 : {
         980               0 :   mBuffer = nsnull;
         981               0 : }
         982                 :
         983                 : void
         984               0 : ShadowThebesLayerOGL::Disconnect()
         985                 : {
         986               0 :   Destroy();
         987               0 : }
         988                 :
         989                 : void
         990               0 : ShadowThebesLayerOGL::Destroy()
         991                 : {
         992               0 :   if (!mDestroyed) {
         993               0 :     mDestroyed = true;
         994               0 :     mBuffer = nsnull;
         995                 :   }
         996               0 : }
         997                 :
         998                 : Layer*
         999               0 : ShadowThebesLayerOGL::GetLayer()
        1000                 : {
        1001               0 :   return this;
        1002                 : }
        1003                 :
        1004                 : bool
        1005               0 : ShadowThebesLayerOGL::IsEmpty()
        1006                 : {
        1007               0 :   return !mBuffer;
        1008                 : }
        1009                 :
        1010                 : void
        1011               0 : ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
        1012                 :                                   const nsIntPoint& aOffset)
        1013                 : {
        1014               0 :   if (!mBuffer) {
        1015               0 :     return;
        1016                 :   }
        1017               0 :   NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
        1018                 :
        1019               0 :   mOGLManager->MakeCurrent();
        1020               0 :   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
        1021                 :
        1022               0 :   gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
        1023               0 :   mBuffer->RenderTo(aOffset, mOGLManager, 0);
        1024                 : }
        1025                 :
        1026                 : void
        1027               0 : ShadowThebesLayerOGL::CleanupResources()
        1028                 : {
        1029               0 :   DestroyFrontBuffer();
        1030               0 : }
        1031                 :
        1032                 : } /* layers */
        1033                 : } /* mozilla */

Generated by: LCOV version 1.7