LCOV - code coverage report
Current view: top level - gfx/layers/composite - ContentHost.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 102 241 42.3 %
Date: 2017-07-14 16:53:18 Functions: 6 16 37.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/layers/ContentHost.h"
       7             : #include "LayersLogging.h"              // for AppendToString
       8             : #include "gfx2DGlue.h"                  // for ContentForFormat
       9             : #include "mozilla/gfx/Point.h"          // for IntSize
      10             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
      11             : #include "mozilla/gfx/BaseRect.h"       // for BaseRect
      12             : #include "mozilla/layers/Compositor.h"  // for Compositor
      13             : #include "mozilla/layers/Effects.h"     // for TexturedEffect, Effect, etc
      14             : #include "mozilla/layers/LayersMessages.h"  // for ThebesBufferData
      15             : #include "nsAString.h"
      16             : #include "nsPrintfCString.h"            // for nsPrintfCString
      17             : #include "nsString.h"                   // for nsAutoCString
      18             : #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
      19             : 
      20             : namespace mozilla {
      21             : using namespace gfx;
      22             : 
      23             : namespace layers {
      24             : 
      25          22 : ContentHostBase::ContentHostBase(const TextureInfo& aTextureInfo)
      26             :   : ContentHost(aTextureInfo)
      27          22 :   , mInitialised(false)
      28          22 : {}
      29             : 
      30          19 : ContentHostBase::~ContentHostBase()
      31             : {
      32          19 : }
      33             : 
      34             : void
      35          56 : ContentHostTexture::Composite(Compositor* aCompositor,
      36             :                               LayerComposite* aLayer,
      37             :                               EffectChain& aEffectChain,
      38             :                               float aOpacity,
      39             :                               const gfx::Matrix4x4& aTransform,
      40             :                               const SamplingFilter aSamplingFilter,
      41             :                               const IntRect& aClipRect,
      42             :                               const nsIntRegion* aVisibleRegion,
      43             :                               const Maybe<gfx::Polygon>& aGeometry)
      44             : {
      45          56 :   NS_ASSERTION(aVisibleRegion, "Requires a visible region");
      46             : 
      47         112 :   AutoLockCompositableHost lock(this);
      48          56 :   if (lock.Failed()) {
      49           0 :     return;
      50             :   }
      51             : 
      52          56 :   if (!mTextureHost->BindTextureSource(mTextureSource)) {
      53           0 :     return;
      54             :   }
      55          56 :   MOZ_ASSERT(mTextureSource.get());
      56             : 
      57          56 :   if (!mTextureHostOnWhite) {
      58          56 :     mTextureSourceOnWhite = nullptr;
      59             :   }
      60          56 :   if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
      61           0 :     return;
      62             :   }
      63             : 
      64         112 :   RefPtr<TexturedEffect> effect = CreateTexturedEffect(mTextureSource.get(),
      65             :                                                        mTextureSourceOnWhite.get(),
      66         112 :                                                        aSamplingFilter, true);
      67          56 :   if (!effect) {
      68           0 :     return;
      69             :   }
      70             : 
      71          56 :   aEffectChain.mPrimaryEffect = effect;
      72             : 
      73         112 :   nsIntRegion tmpRegion;
      74             :   const nsIntRegion* renderRegion;
      75             : #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
      76          56 :   if (PaintWillResample()) {
      77             :     // If we're resampling, then the texture image will contain exactly the
      78             :     // entire visible region's bounds, and we should draw it all in one quad
      79             :     // to avoid unexpected aliasing.
      80           0 :     tmpRegion = aVisibleRegion->GetBounds();
      81           0 :     renderRegion = &tmpRegion;
      82             :   } else {
      83          56 :     renderRegion = aVisibleRegion;
      84             :   }
      85             : #else
      86             :   renderRegion = aVisibleRegion;
      87             : #endif
      88             : 
      89         112 :   nsIntRegion region(*renderRegion);
      90          56 :   nsIntPoint origin = GetOriginOffset();
      91             :   // translate into TexImage space, buffer origin might not be at texture (0,0)
      92          56 :   region.MoveBy(-origin);
      93             : 
      94             :   // Figure out the intersecting draw region
      95          56 :   gfx::IntSize texSize = mTextureSource->GetSize();
      96          56 :   IntRect textureRect = IntRect(0, 0, texSize.width, texSize.height);
      97          56 :   textureRect.MoveBy(region.GetBounds().TopLeft());
      98         112 :   nsIntRegion subregion;
      99          56 :   subregion.And(region, textureRect);
     100          56 :   if (subregion.IsEmpty()) {
     101             :     // Region is empty, nothing to draw
     102           0 :     return;
     103             :   }
     104             : 
     105         112 :   nsIntRegion screenRects;
     106         112 :   nsIntRegion regionRects;
     107             : 
     108             :   // Collect texture/screen coordinates for drawing
     109         112 :   for (auto iter = subregion.RectIter(); !iter.Done(); iter.Next()) {
     110          56 :     IntRect regionRect = iter.Get();
     111          56 :     IntRect screenRect = iter.Get();
     112          56 :     screenRect.MoveBy(origin);
     113             : 
     114          56 :     screenRects.Or(screenRects, screenRect);
     115          56 :     regionRects.Or(regionRects, regionRect);
     116             :   }
     117             : 
     118          56 :   BigImageIterator* bigImgIter = mTextureSource->AsBigImageIterator();
     119          56 :   BigImageIterator* iterOnWhite = nullptr;
     120          56 :   if (bigImgIter) {
     121           0 :     bigImgIter->BeginBigImageIteration();
     122             :   }
     123             : 
     124          56 :   if (mTextureSourceOnWhite) {
     125           0 :     iterOnWhite = mTextureSourceOnWhite->AsBigImageIterator();
     126           0 :     MOZ_ASSERT(!bigImgIter || bigImgIter->GetTileCount() == iterOnWhite->GetTileCount(),
     127             :                "Tile count mismatch on component alpha texture");
     128           0 :     if (iterOnWhite) {
     129           0 :       iterOnWhite->BeginBigImageIteration();
     130             :     }
     131             :   }
     132             : 
     133          56 :   bool usingTiles = (bigImgIter && bigImgIter->GetTileCount() > 1);
     134          56 :   do {
     135          56 :     if (iterOnWhite && bigImgIter) {
     136           0 :       MOZ_ASSERT(iterOnWhite->GetTileRect() == bigImgIter->GetTileRect(),
     137             :                  "component alpha textures should be the same size.");
     138             :     }
     139             : 
     140           0 :     IntRect texRect = bigImgIter ? bigImgIter->GetTileRect()
     141             :                                  : IntRect(0, 0,
     142             :                                              texSize.width,
     143          56 :                                              texSize.height);
     144             : 
     145             :     // Draw texture. If we're using tiles, we do repeating manually, as texture
     146             :     // repeat would cause each individual tile to repeat instead of the
     147             :     // compound texture as a whole. This involves drawing at most 4 sections,
     148             :     // 2 for each axis that has texture repeat.
     149         112 :     for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
     150         112 :       for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
     151          56 :         IntRect currentTileRect(texRect);
     152          56 :         currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
     153             : 
     154         280 :         for (auto screenIter = screenRects.RectIter(),
     155         112 :                   regionIter = regionRects.RectIter();
     156         112 :              !screenIter.Done() && !regionIter.Done();
     157          56 :              screenIter.Next(), regionIter.Next()) {
     158          56 :           const IntRect& screenRect = screenIter.Get();
     159          56 :           const IntRect& regionRect = regionIter.Get();
     160          56 :           IntRect tileScreenRect(screenRect);
     161          56 :           IntRect tileRegionRect(regionRect);
     162             : 
     163             :           // When we're using tiles, find the intersection between the tile
     164             :           // rect and this region rect. Tiling is then handled by the
     165             :           // outer for-loops and modifying the tile rect.
     166          56 :           if (usingTiles) {
     167           0 :             tileScreenRect.MoveBy(-origin);
     168           0 :             tileScreenRect = tileScreenRect.Intersect(currentTileRect);
     169           0 :             tileScreenRect.MoveBy(origin);
     170             : 
     171           0 :             if (tileScreenRect.IsEmpty())
     172           0 :               continue;
     173             : 
     174           0 :             tileRegionRect = regionRect.Intersect(currentTileRect);
     175           0 :             tileRegionRect.MoveBy(-currentTileRect.TopLeft());
     176             :           }
     177         112 :           gfx::Rect rect(tileScreenRect.x, tileScreenRect.y,
     178         168 :                          tileScreenRect.width, tileScreenRect.height);
     179             : 
     180         224 :           effect->mTextureCoords = Rect(Float(tileRegionRect.x) / texRect.width,
     181          56 :                                         Float(tileRegionRect.y) / texRect.height,
     182          56 :                                         Float(tileRegionRect.width) / texRect.width,
     183          56 :                                         Float(tileRegionRect.height) / texRect.height);
     184             : 
     185             :           aCompositor->DrawGeometry(rect, aClipRect, aEffectChain,
     186          56 :                                     aOpacity, aTransform, aGeometry);
     187             : 
     188          56 :           if (usingTiles) {
     189           0 :             DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT | DiagnosticFlags::BIGIMAGE;
     190           0 :             if (iterOnWhite) {
     191           0 :               diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
     192             :             }
     193           0 :             aCompositor->DrawDiagnostics(diagnostics, rect, aClipRect,
     194           0 :                                          aTransform, mFlashCounter);
     195             :           }
     196             :         }
     197             :       }
     198             :     }
     199             : 
     200          56 :     if (iterOnWhite) {
     201           0 :       iterOnWhite->NextTile();
     202             :     }
     203          56 :   } while (usingTiles && bigImgIter->NextTile());
     204             : 
     205          56 :   if (bigImgIter) {
     206           0 :     bigImgIter->EndBigImageIteration();
     207             :   }
     208          56 :   if (iterOnWhite) {
     209           0 :     iterOnWhite->EndBigImageIteration();
     210             :   }
     211             : 
     212          56 :   DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT;
     213          56 :   if (iterOnWhite) {
     214           0 :     diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
     215             :   }
     216         112 :   aCompositor->DrawDiagnostics(diagnostics, nsIntRegion(mBufferRect), aClipRect,
     217          56 :                                aTransform, mFlashCounter);
     218             : }
     219             : 
     220             : RefPtr<TextureSource>
     221           0 : ContentHostTexture::AcquireTextureSource()
     222             : {
     223           0 :   if (!mTextureHost || !mTextureHost->AcquireTextureSource(mTextureSource)) {
     224           0 :     return nullptr;
     225             :   }
     226           0 :   return mTextureSource.get();
     227             : }
     228             : 
     229             : RefPtr<TextureSource>
     230           0 : ContentHostTexture::AcquireTextureSourceOnWhite()
     231             : {
     232           0 :   if (!mTextureHostOnWhite ||
     233           0 :       !mTextureHostOnWhite->AcquireTextureSource(mTextureSourceOnWhite))
     234             :   {
     235           0 :     return nullptr;
     236             :   }
     237           0 :   return mTextureSourceOnWhite.get();
     238             : }
     239             : 
     240             : void
     241          33 : ContentHostTexture::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
     242             : {
     243          33 :   ContentHostBase::UseTextureHost(aTextures);
     244          33 :   MOZ_ASSERT(aTextures.Length() == 1);
     245          33 :   const TimedTexture& t = aTextures[0];
     246          33 :   MOZ_ASSERT(t.mPictureRect.IsEqualInterior(
     247             :       nsIntRect(nsIntPoint(0, 0), nsIntSize(t.mTexture->GetSize()))),
     248             :       "Only default picture rect supported");
     249             : 
     250          33 :   if (t.mTexture != mTextureHost) {
     251          33 :     mReceivedNewHost = true;
     252             :   }
     253             : 
     254          33 :   mTextureHost = t.mTexture;
     255          33 :   mTextureHostOnWhite = nullptr;
     256          33 :   mTextureSourceOnWhite = nullptr;
     257          33 :   if (mTextureHost) {
     258          33 :     mTextureHost->PrepareTextureSource(mTextureSource);
     259             :   }
     260          33 : }
     261             : 
     262             : void
     263           0 : ContentHostTexture::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
     264             :                                               TextureHost* aTextureOnWhite)
     265             : {
     266           0 :   ContentHostBase::UseComponentAlphaTextures(aTextureOnBlack, aTextureOnWhite);
     267           0 :   mTextureHost = aTextureOnBlack;
     268           0 :   mTextureHostOnWhite = aTextureOnWhite;
     269           0 :   if (mTextureHost) {
     270           0 :     mTextureHost->PrepareTextureSource(mTextureSource);
     271             :   }
     272           0 :   if (mTextureHostOnWhite) {
     273           0 :     mTextureHostOnWhite->PrepareTextureSource(mTextureSourceOnWhite);
     274             :   }
     275           0 : }
     276             : 
     277             : void
     278          22 : ContentHostTexture::SetTextureSourceProvider(TextureSourceProvider* aProvider)
     279             : {
     280          22 :   ContentHostBase::SetTextureSourceProvider(aProvider);
     281          22 :   if (mTextureHost) {
     282           0 :     mTextureHost->SetTextureSourceProvider(aProvider);
     283             :   }
     284          22 :   if (mTextureHostOnWhite) {
     285           0 :     mTextureHostOnWhite->SetTextureSourceProvider(aProvider);
     286             :   }
     287          22 : }
     288             : 
     289             : void
     290           0 : ContentHostTexture::Dump(std::stringstream& aStream,
     291             :                          const char* aPrefix,
     292             :                          bool aDumpHtml)
     293             : {
     294             : #ifdef MOZ_DUMP_PAINTING
     295           0 :   if (aDumpHtml) {
     296           0 :     aStream << "<ul>";
     297             :   }
     298           0 :   if (mTextureHost) {
     299           0 :     aStream << aPrefix;
     300           0 :     if (aDumpHtml) {
     301           0 :       aStream << "<li> <a href=";
     302             :     } else {
     303           0 :       aStream << "Front buffer: ";
     304             :     }
     305           0 :     DumpTextureHost(aStream, mTextureHost);
     306           0 :     if (aDumpHtml) {
     307           0 :       aStream << "> Front buffer </a></li> ";
     308             :     } else {
     309           0 :       aStream << "\n";
     310             :     }
     311             :   }
     312           0 :   if (mTextureHostOnWhite) {
     313           0 :     aStream << aPrefix;
     314           0 :     if (aDumpHtml) {
     315           0 :       aStream << "<li> <a href=";
     316             :     } else {
     317           0 :       aStream << "Front buffer on white: ";
     318             :     }
     319           0 :     DumpTextureHost(aStream, mTextureHostOnWhite);
     320           0 :     if (aDumpHtml) {
     321           0 :       aStream << "> Front buffer on white </a> </li> ";
     322             :     } else {
     323           0 :       aStream << "\n";
     324             :     }
     325             :   }
     326           0 :   if (aDumpHtml) {
     327           0 :     aStream << "</ul>";
     328             :   }
     329             : #endif
     330           0 : }
     331             : 
     332             : static inline void
     333           0 : AddWrappedRegion(const nsIntRegion& aInput, nsIntRegion& aOutput,
     334             :                  const IntSize& aSize, const nsIntPoint& aShift)
     335             : {
     336           0 :   nsIntRegion tempRegion;
     337           0 :   tempRegion.And(IntRect(aShift, aSize), aInput);
     338           0 :   tempRegion.MoveBy(-aShift);
     339           0 :   aOutput.Or(aOutput, tempRegion);
     340           0 : }
     341             : 
     342             : bool
     343           0 : ContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
     344             :                                         const nsIntRegion& aUpdated,
     345             :                                         const nsIntRegion& aOldValidRegionBack)
     346             : {
     347           0 :   if (!mTextureHost) {
     348           0 :     mInitialised = false;
     349           0 :     return true; // FIXME should we return false? Returning true for now
     350             :   }              // to preserve existing behavior of NOT causing IPC errors.
     351             : 
     352             :   // updated is in screen coordinates. Convert it to buffer coordinates.
     353           0 :   nsIntRegion destRegion(aUpdated);
     354             : 
     355           0 :   if (mReceivedNewHost) {
     356           0 :     destRegion.Or(destRegion, aOldValidRegionBack);
     357           0 :     mReceivedNewHost = false;
     358             :   }
     359           0 :   destRegion.MoveBy(-aData.rect().TopLeft());
     360             : 
     361           0 :   if (!aData.rect().Contains(aUpdated.GetBounds()) ||
     362           0 :       aData.rotation().x > aData.rect().width ||
     363           0 :       aData.rotation().y > aData.rect().height) {
     364           0 :     NS_ERROR("Invalid update data");
     365           0 :     return false;
     366             :   }
     367             : 
     368             :   // destRegion is now in logical coordinates relative to the buffer, but we
     369             :   // need to account for rotation. We do that by moving the region to the
     370             :   // rotation offset and then wrapping any pixels that extend off the
     371             :   // bottom/right edges.
     372             : 
     373             :   // Shift to the rotation point
     374           0 :   destRegion.MoveBy(aData.rotation());
     375             : 
     376           0 :   IntSize bufferSize = aData.rect().Size();
     377             : 
     378             :   // Select only the pixels that are still within the buffer.
     379           0 :   nsIntRegion finalRegion;
     380           0 :   finalRegion.And(IntRect(IntPoint(), bufferSize), destRegion);
     381             : 
     382             :   // For each of the overlap areas (right, bottom-right, bottom), select those
     383             :   // pixels and wrap them around to the opposite edge of the buffer rect.
     384           0 :   AddWrappedRegion(destRegion, finalRegion, bufferSize, nsIntPoint(aData.rect().width, 0));
     385           0 :   AddWrappedRegion(destRegion, finalRegion, bufferSize, nsIntPoint(aData.rect().width, aData.rect().height));
     386           0 :   AddWrappedRegion(destRegion, finalRegion, bufferSize, nsIntPoint(0, aData.rect().height));
     387             : 
     388           0 :   MOZ_ASSERT(IntRect(0, 0, aData.rect().width, aData.rect().height).Contains(finalRegion.GetBounds()));
     389             : 
     390           0 :   mTextureHost->Updated(&finalRegion);
     391           0 :   if (mTextureHostOnWhite) {
     392           0 :     mTextureHostOnWhite->Updated(&finalRegion);
     393             :   }
     394           0 :   mInitialised = true;
     395             : 
     396           0 :   mBufferRect = aData.rect();
     397           0 :   mBufferRotation = aData.rotation();
     398             : 
     399           0 :   return true;
     400             : }
     401             : 
     402             : bool
     403          33 : ContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
     404             :                                         const nsIntRegion& aUpdated,
     405             :                                         const nsIntRegion& aOldValidRegionBack)
     406             : {
     407          33 :   if (!mTextureHost) {
     408           0 :     mInitialised = false;
     409           0 :     return true;
     410             :   }
     411             : 
     412             :   // We don't need to calculate an update region because we assume that if we
     413             :   // are using double buffering then we have render-to-texture and thus no
     414             :   // upload to do.
     415          33 :   mTextureHost->Updated();
     416          33 :   if (mTextureHostOnWhite) {
     417           0 :     mTextureHostOnWhite->Updated();
     418             :   }
     419          33 :   mInitialised = true;
     420             : 
     421          33 :   mBufferRect = aData.rect();
     422          33 :   mBufferRotation = aData.rotation();
     423             : 
     424             :   // Save the current valid region of our front buffer, because if
     425             :   // we're double buffering, it's going to be the valid region for the
     426             :   // next back buffer sent back to the renderer.
     427             :   //
     428             :   // NB: we rely here on the fact that mValidRegion is initialized to
     429             :   // empty, and that the first time Swap() is called we don't have a
     430             :   // valid front buffer that we're going to return to content.
     431          33 :   mValidRegionForNextBackBuffer = aOldValidRegionBack;
     432             : 
     433          33 :   return true;
     434             : }
     435             : 
     436             : void
     437           0 : ContentHostTexture::PrintInfo(std::stringstream& aStream, const char* aPrefix)
     438             : {
     439           0 :   aStream << aPrefix;
     440           0 :   aStream << nsPrintfCString("ContentHost (0x%p)", this).get();
     441             : 
     442           0 :   AppendToString(aStream, mBufferRect, " [buffer-rect=", "]");
     443           0 :   AppendToString(aStream, mBufferRotation, " [buffer-rotation=", "]");
     444           0 :   if (PaintWillResample()) {
     445           0 :     aStream << " [paint-will-resample]";
     446             :   }
     447             : 
     448           0 :   if (mTextureHost) {
     449           0 :     nsAutoCString pfx(aPrefix);
     450           0 :     pfx += "  ";
     451             : 
     452           0 :     aStream << "\n";
     453           0 :     mTextureHost->PrintInfo(aStream, pfx.get());
     454             :   }
     455           0 : }
     456             : 
     457             : 
     458             : already_AddRefed<TexturedEffect>
     459           0 : ContentHostTexture::GenEffect(const gfx::SamplingFilter aSamplingFilter)
     460             : {
     461           0 :   if (!mTextureHost) {
     462           0 :     return nullptr;
     463             :   }
     464           0 :   if (!mTextureHost->BindTextureSource(mTextureSource)) {
     465           0 :     return nullptr;
     466             :   }
     467           0 :   if (!mTextureHostOnWhite) {
     468           0 :     mTextureSourceOnWhite = nullptr;
     469             :   }
     470           0 :   if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
     471           0 :     return nullptr;
     472             :   }
     473             :   return CreateTexturedEffect(mTextureSource.get(),
     474             :                               mTextureSourceOnWhite.get(),
     475           0 :                               aSamplingFilter, true);
     476             : }
     477             : 
     478             : already_AddRefed<gfx::DataSourceSurface>
     479           0 : ContentHostTexture::GetAsSurface()
     480             : {
     481           0 :   if (!mTextureHost) {
     482           0 :     return nullptr;
     483             :   }
     484             : 
     485           0 :   return mTextureHost->GetAsSurface();
     486             : }
     487             : 
     488             : 
     489             : } // namespace layers
     490             : } // namespace mozilla

Generated by: LCOV version 1.13