LCOV - code coverage report
Current view: top level - gfx/layers/wr - WebRenderCompositableHolder.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 188 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
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 "WebRenderCompositableHolder.h"
       7             : 
       8             : #include "CompositableHost.h"
       9             : #include "mozilla/gfx/gfxVars.h"
      10             : #include "mozilla/layers/WebRenderImageHost.h"
      11             : #include "mozilla/layers/WebRenderTextureHost.h"
      12             : #include "mozilla/webrender/WebRenderAPI.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace layers {
      16             : 
      17           0 : WebRenderCompositableHolder::AsyncImagePipelineHolder::AsyncImagePipelineHolder()
      18             :  : mInitialised(false)
      19             :  , mIsChanged(false)
      20             :  , mUseExternalImage(false)
      21             :  , mFilter(WrImageRendering::Auto)
      22           0 :  , mMixBlendMode(WrMixBlendMode::Normal)
      23           0 : {}
      24             : 
      25           0 : WebRenderCompositableHolder::WebRenderCompositableHolder(uint32_t aIdNamespace)
      26             :  : mIdNamespace(aIdNamespace)
      27             :  , mResourceId(0)
      28             :  , mAsyncImageEpoch(0)
      29           0 :  , mDestroyed(false)
      30             : {
      31           0 :   MOZ_COUNT_CTOR(WebRenderCompositableHolder);
      32           0 : }
      33             : 
      34           0 : WebRenderCompositableHolder::~WebRenderCompositableHolder()
      35             : {
      36           0 :   MOZ_COUNT_DTOR(WebRenderCompositableHolder);
      37           0 : }
      38             : 
      39             : void
      40           0 : WebRenderCompositableHolder::Destroy(wr::WebRenderAPI* aApi)
      41             : {
      42           0 :   DeleteOldAsyncImages(aApi);
      43           0 :   mDestroyed = true;
      44           0 : }
      45             : 
      46             : bool
      47           0 : WebRenderCompositableHolder::HasKeysToDelete()
      48             : {
      49           0 :   return !mKeysToDelete.IsEmpty();
      50             : }
      51             : 
      52             : void
      53           0 : WebRenderCompositableHolder::DeleteOldAsyncImages(wr::WebRenderAPI* aApi)
      54             : {
      55           0 :   for (wr::ImageKey key : mKeysToDelete) {
      56           0 :     aApi->DeleteImage(key);
      57             :   }
      58           0 :   mKeysToDelete.Clear();
      59           0 : }
      60             : 
      61             : void
      62           0 : WebRenderCompositableHolder::AddPipeline(const wr::PipelineId& aPipelineId)
      63             : {
      64           0 :   if (mDestroyed) {
      65           0 :     return;
      66             :   }
      67           0 :   uint64_t id = wr::AsUint64(aPipelineId);
      68             : 
      69           0 :   PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
      70           0 :   if(holder) {
      71             :     // This could happen during tab move between different windows.
      72             :     // Previously removed holder could be still alive for waiting destroyed.
      73           0 :     MOZ_ASSERT(holder->mDestroyedEpoch.isSome());
      74           0 :     holder->mDestroyedEpoch = Nothing(); // Revive holder
      75           0 :     return;
      76             :   }
      77           0 :   holder = new PipelineTexturesHolder();
      78           0 :   mPipelineTexturesHolders.Put(id, holder);
      79             : }
      80             : 
      81             : void
      82           0 : WebRenderCompositableHolder::RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch)
      83             : {
      84           0 :   if (mDestroyed) {
      85           0 :     return;
      86             :   }
      87             : 
      88           0 :   PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
      89           0 :   MOZ_ASSERT(holder);
      90           0 :   if (!holder) {
      91           0 :     return;
      92             :   }
      93           0 :   holder->mDestroyedEpoch = Some(aEpoch);
      94             : }
      95             : 
      96             : void
      97           0 : WebRenderCompositableHolder::AddAsyncImagePipeline(const wr::PipelineId& aPipelineId, WebRenderImageHost* aImageHost)
      98             : {
      99           0 :   if (mDestroyed) {
     100           0 :     return;
     101             :   }
     102           0 :   MOZ_ASSERT(aImageHost);
     103           0 :   uint64_t id = wr::AsUint64(aPipelineId);
     104             : 
     105           0 :   MOZ_ASSERT(!mAsyncImagePipelineHolders.Get(id));
     106           0 :   AsyncImagePipelineHolder* holder = new AsyncImagePipelineHolder();
     107           0 :   holder->mImageHost = aImageHost;
     108           0 :   mAsyncImagePipelineHolders.Put(id, holder);
     109           0 :   AddPipeline(aPipelineId);
     110             : }
     111             : 
     112             : void
     113           0 : WebRenderCompositableHolder::RemoveAsyncImagePipeline(wr::WebRenderAPI* aApi, const wr::PipelineId& aPipelineId)
     114             : {
     115           0 :   if (mDestroyed) {
     116           0 :     return;
     117             :   }
     118             : 
     119           0 :   uint64_t id = wr::AsUint64(aPipelineId);
     120           0 :   if (auto entry = mAsyncImagePipelineHolders.Lookup(id)) {
     121           0 :     AsyncImagePipelineHolder* holder = entry.Data();
     122           0 :     ++mAsyncImageEpoch; // Update webrender epoch
     123           0 :     aApi->ClearRootDisplayList(wr::NewEpoch(mAsyncImageEpoch), aPipelineId);
     124           0 :     for (wr::ImageKey key : holder->mKeys) {
     125           0 :       aApi->DeleteImage(key);
     126             :     }
     127           0 :     entry.Remove();
     128           0 :     RemovePipeline(aPipelineId, wr::NewEpoch(mAsyncImageEpoch));
     129             :   }
     130             : }
     131             : 
     132             : void
     133           0 : WebRenderCompositableHolder::UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
     134             :                                                       const LayerRect& aScBounds,
     135             :                                                       const gfx::Matrix4x4& aScTransform,
     136             :                                                       const gfx::MaybeIntSize& aScaleToSize,
     137             :                                                       const WrImageRendering& aFilter,
     138             :                                                       const WrMixBlendMode& aMixBlendMode)
     139             : {
     140           0 :   if (mDestroyed) {
     141           0 :     return;
     142             :   }
     143           0 :   AsyncImagePipelineHolder* holder = mAsyncImagePipelineHolders.Get(wr::AsUint64(aPipelineId));
     144           0 :   if (!holder) {
     145           0 :     return;
     146             :   }
     147           0 :   holder->mInitialised = true;
     148           0 :   holder->mIsChanged = true;
     149           0 :   holder->mScBounds = aScBounds;
     150           0 :   holder->mScTransform = aScTransform;
     151           0 :   holder->mScaleToSize = aScaleToSize;
     152           0 :   holder->mFilter = aFilter;
     153           0 :   holder->mMixBlendMode = aMixBlendMode;
     154             : }
     155             : 
     156             : bool
     157           0 : WebRenderCompositableHolder::GetImageKeyForTextureHost(wr::WebRenderAPI* aApi, TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys)
     158             : {
     159           0 :   MOZ_ASSERT(aKeys.IsEmpty());
     160           0 :   MOZ_ASSERT(aTexture);
     161             : 
     162           0 :   WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost();
     163             : 
     164           0 :   if (wrTexture) {
     165           0 :     wrTexture->GetWRImageKeys(aKeys, std::bind(&WebRenderCompositableHolder::GetImageKey, this));
     166           0 :     MOZ_ASSERT(!aKeys.IsEmpty());
     167           0 :     Range<const wr::ImageKey> keys(&aKeys[0], aKeys.Length());
     168           0 :     wrTexture->AddWRImage(aApi, keys, wrTexture->GetExternalImageKey());
     169           0 :     return true;
     170             :   } else {
     171           0 :     RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
     172           0 :     if (!dSurf) {
     173           0 :       NS_ERROR("TextureHost does not return DataSourceSurface");
     174           0 :       return false;
     175             :     }
     176             :     gfx::DataSourceSurface::MappedSurface map;
     177           0 :     if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
     178           0 :       NS_ERROR("DataSourceSurface failed to map");
     179           0 :       return false;
     180             :     }
     181           0 :     gfx::IntSize size = dSurf->GetSize();
     182           0 :     wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
     183           0 :     auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
     184             : 
     185           0 :     wr::ImageKey key = GetImageKey();
     186           0 :     aKeys.AppendElement(key);
     187           0 :     aApi->AddImage(key, descriptor, slice);
     188           0 :     dSurf->Unmap();
     189             :   }
     190           0 :   return false;
     191             : }
     192             : 
     193             : bool
     194           0 : WebRenderCompositableHolder::UpdateImageKeys(wr::WebRenderAPI* aApi,
     195             :                                              bool& aUseExternalImage,
     196             :                                              AsyncImagePipelineHolder* aHolder,
     197             :                                              nsTArray<wr::ImageKey>& aKeys,
     198             :                                              nsTArray<wr::ImageKey>& aKeysToDelete)
     199             : {
     200           0 :   MOZ_ASSERT(aKeys.IsEmpty());
     201           0 :   MOZ_ASSERT(aHolder);
     202           0 :   TextureHost* texture = aHolder->mImageHost->GetAsTextureHostForComposite();
     203             : 
     204           0 :   if (!aHolder->mInitialised) {
     205           0 :     return false;
     206             :   }
     207             : 
     208             :   // No change
     209           0 :   if (!aHolder->mIsChanged && texture == aHolder->mCurrentTexture) {
     210             :     // No need to update DisplayList.
     211           0 :     return false;
     212             :   }
     213             : 
     214           0 :   aHolder->mIsChanged = false;
     215             : 
     216           0 :   if (texture == aHolder->mCurrentTexture) {
     217             :     // Reuse previous ImageKeys.
     218           0 :     aKeys.AppendElements(aHolder->mKeys);
     219           0 :     aUseExternalImage = aHolder->mUseExternalImage;
     220           0 :     return true;
     221             :   }
     222             : 
     223             :   // Delete old ImageKeys
     224           0 :   aKeysToDelete.AppendElements(aHolder->mKeys);
     225           0 :   aHolder->mKeys.Clear();
     226           0 :   aHolder->mCurrentTexture = nullptr;
     227             : 
     228             :   // No txture to render
     229           0 :   if (!texture) {
     230           0 :     return true;
     231             :   }
     232             : 
     233           0 :   aUseExternalImage = aHolder->mUseExternalImage = GetImageKeyForTextureHost(aApi, texture, aKeys);
     234           0 :   MOZ_ASSERT(!aKeys.IsEmpty());
     235           0 :   aHolder->mKeys.AppendElements(aKeys);
     236           0 :   aHolder->mCurrentTexture = texture;
     237           0 :   return true;
     238             : }
     239             : 
     240             : void
     241           0 : WebRenderCompositableHolder::ApplyAsyncImages(wr::WebRenderAPI* aApi)
     242             : {
     243           0 :   if (mDestroyed || mAsyncImagePipelineHolders.Count() == 0) {
     244           0 :     return;
     245             :   }
     246             : 
     247           0 :   ++mAsyncImageEpoch; // Update webrender epoch
     248           0 :   wr::Epoch epoch = wr::NewEpoch(mAsyncImageEpoch);
     249           0 :   nsTArray<wr::ImageKey> keysToDelete;
     250             : 
     251           0 :   for (auto iter = mAsyncImagePipelineHolders.Iter(); !iter.Done(); iter.Next()) {
     252           0 :     wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
     253           0 :     AsyncImagePipelineHolder* holder = iter.Data();
     254             : 
     255           0 :     nsTArray<wr::ImageKey> keys;
     256           0 :     bool useExternalImage = false;
     257             :     bool updateDisplayList = UpdateImageKeys(aApi,
     258             :                                              useExternalImage,
     259             :                                              holder,
     260             :                                              keys,
     261           0 :                                              keysToDelete);
     262           0 :     if (!updateDisplayList) {
     263           0 :       continue;
     264             :     }
     265             : 
     266           0 :     WrSize contentSize { holder->mScBounds.width, holder->mScBounds.height };
     267           0 :     wr::DisplayListBuilder builder(pipelineId, contentSize);
     268             : 
     269           0 :     if (!keys.IsEmpty()) {
     270           0 :       MOZ_ASSERT(holder->mCurrentTexture.get());
     271             : 
     272           0 :       float opacity = 1.0f;
     273           0 :       builder.PushStackingContext(wr::ToWrRect(holder->mScBounds),
     274             :                                   0,
     275             :                                   &opacity,
     276           0 :                                   holder->mScTransform.IsIdentity() ? nullptr : &holder->mScTransform,
     277             :                                   WrTransformStyle::Flat,
     278             :                                   holder->mMixBlendMode,
     279           0 :                                   nsTArray<WrFilterOp>());
     280             : 
     281           0 :       LayerRect rect(0, 0, holder->mCurrentTexture->GetSize().width, holder->mCurrentTexture->GetSize().height);
     282           0 :       if (holder->mScaleToSize.isSome()) {
     283           0 :         rect = LayerRect(0, 0, holder->mScaleToSize.value().width, holder->mScaleToSize.value().height);
     284             :       }
     285             : 
     286           0 :       if (useExternalImage) {
     287           0 :         MOZ_ASSERT(holder->mCurrentTexture->AsWebRenderTextureHost());
     288           0 :         Range<const wr::ImageKey> range_keys(&keys[0], keys.Length());
     289           0 :         holder->mCurrentTexture->PushExternalImage(builder,
     290           0 :                                                    wr::ToWrRect(rect),
     291           0 :                                                    wr::ToWrRect(rect),
     292             :                                                    holder->mFilter,
     293           0 :                                                    range_keys);
     294           0 :         HoldExternalImage(pipelineId, epoch, holder->mCurrentTexture->AsWebRenderTextureHost());
     295             :       } else {
     296           0 :         MOZ_ASSERT(keys.Length() == 1);
     297           0 :         builder.PushImage(wr::ToWrRect(rect),
     298           0 :                           wr::ToWrRect(rect),
     299             :                           holder->mFilter,
     300           0 :                           keys[0]);
     301             :       }
     302           0 :       builder.PopStackingContext();
     303             :     }
     304             : 
     305           0 :     wr::BuiltDisplayList dl;
     306             :     WrSize builderContentSize;
     307           0 :     builder.Finalize(builderContentSize, dl);
     308           0 :     aApi->SetRootDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch, LayerSize(holder->mScBounds.width, holder->mScBounds.height),
     309             :                              pipelineId, builderContentSize,
     310           0 :                              dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length);
     311             :   }
     312           0 :   DeleteOldAsyncImages(aApi);
     313           0 :   mKeysToDelete.SwapElements(keysToDelete);
     314             : }
     315             : 
     316             : void
     317           0 : WebRenderCompositableHolder::HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
     318             : {
     319           0 :   if (mDestroyed) {
     320           0 :     return;
     321             :   }
     322           0 :   MOZ_ASSERT(aTexture);
     323             : 
     324           0 :   PipelineTexturesHolder* holder = mPipelineTexturesHolders.Get(wr::AsUint64(aPipelineId));
     325           0 :   MOZ_ASSERT(holder);
     326           0 :   if (!holder) {
     327           0 :     return;
     328             :   }
     329             :   // Hold WebRenderTextureHost until end of its usage on RenderThread
     330           0 :   holder->mTextureHosts.push(ForwardingTextureHost(aEpoch, aTexture));
     331             : }
     332             : 
     333             : void
     334           0 : WebRenderCompositableHolder::Update(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch)
     335             : {
     336           0 :   if (mDestroyed) {
     337           0 :     return;
     338             :   }
     339           0 :   if (auto entry = mPipelineTexturesHolders.Lookup(wr::AsUint64(aPipelineId))) {
     340           0 :     PipelineTexturesHolder* holder = entry.Data();
     341             :     // Remove Pipeline
     342           0 :     if (holder->mDestroyedEpoch.isSome() && holder->mDestroyedEpoch.ref() <= aEpoch) {
     343           0 :       entry.Remove();
     344           0 :       return;
     345             :     }
     346             : 
     347             :     // Release TextureHosts based on Epoch
     348           0 :     while (!holder->mTextureHosts.empty()) {
     349           0 :       if (aEpoch <= holder->mTextureHosts.front().mEpoch) {
     350           0 :         break;
     351             :       }
     352           0 :       holder->mTextureHosts.pop();
     353             :     }
     354             :   }
     355             : }
     356             : 
     357             : } // namespace layers
     358             : } // namespace mozilla

Generated by: LCOV version 1.13