LCOV - code coverage report
Current view: top level - gfx/layers/mlgpu - RenderPassMLGPU.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 484 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 46 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 "RenderPassMLGPU.h"
       7             : #include "ContainerLayerMLGPU.h"
       8             : #include "FrameBuilder.h"
       9             : #include "ImageLayerMLGPU.h"
      10             : #include "LayersLogging.h"
      11             : #include "MaskOperation.h"
      12             : #include "MLGDevice.h"
      13             : #include "PaintedLayerMLGPU.h"
      14             : #include "RenderViewMLGPU.h"
      15             : #include "ShaderDefinitionsMLGPU.h"
      16             : #include "ShaderDefinitionsMLGPU-inl.h"
      17             : #include "SharedBufferMLGPU.h"
      18             : #include "mozilla/layers/LayersHelpers.h"
      19             : #include "mozilla/layers/LayersMessages.h"
      20             : #include "RenderPassMLGPU-inl.h"
      21             : 
      22             : namespace mozilla {
      23             : namespace layers {
      24             : 
      25             : using namespace gfx;
      26             : 
      27           0 : ItemInfo::ItemInfo(FrameBuilder* aBuilder,
      28             :                    RenderViewMLGPU* aView,
      29             :                    LayerMLGPU* aLayer,
      30             :                    int32_t aSortOrder,
      31             :                    const IntRect& aBounds,
      32           0 :                    Maybe<Polygon>&& aGeometry)
      33             :  : view(aView),
      34             :    layer(aLayer),
      35             :    type(RenderPassType::Unknown),
      36             :    layerIndex(kInvalidResourceIndex),
      37             :    sortOrder(aSortOrder),
      38             :    bounds(aBounds),
      39           0 :    geometry(Move(aGeometry))
      40             : {
      41           0 :   const Matrix4x4& transform = aLayer->GetLayer()->GetEffectiveTransform();
      42             : 
      43           0 :   Matrix transform2D;
      44           0 :   if (!geometry &&
      45           0 :       transform.Is2D(&transform2D) &&
      46           0 :       transform2D.IsRectilinear())
      47             :   {
      48           0 :     this->rectilinear = true;
      49           0 :     if (transform2D.IsIntegerTranslation()) {
      50           0 :       this->translation = Some(IntPoint::Truncate(transform2D.GetTranslation()));
      51             :     }
      52             :   } else {
      53           0 :     this->rectilinear = false;
      54             :   }
      55             : 
      56             :   // Layers can have arbitrary clips or transforms, and we can't use built-in
      57             :   // scissor functionality when batching. Instead, pixel shaders will write
      58             :   // transparent pixels for positions outside of the clip. Unfortunately that
      59             :   // breaks z-buffering because the transparent pixels will still write to
      60             :   // the depth buffer.
      61             :   //
      62             :   // To make this work, we clamp the final vertices in the vertex shader to
      63             :   // the clip rect. We can only do this for rectilinear transforms. If a
      64             :   // transform can produce a rotation or perspective change, then we might
      65             :   // accidentally change the geometry. These items are not treated as
      66             :   // opaque.
      67             :   //
      68             :   // Also, we someday want non-rectilinear items to be antialiased with DEAA,
      69             :   // and we can't do this if the items are rendered front-to-back, since
      70             :   // such items cannot be blended. (Though we could consider adding these
      71             :   // items in two separate draw calls, one for DEAA and for not - that is
      72             :   // definitely future work.)
      73           0 :   if (aLayer->GetComputedOpacity() != 1.0f ||
      74           0 :       aLayer->GetMask() ||
      75           0 :       !aLayer->IsContentOpaque() ||
      76           0 :       !rectilinear)
      77             :   {
      78           0 :     this->opaque = false;
      79           0 :     this->renderOrder = RenderOrder::BackToFront;
      80             :   } else {
      81           0 :     this->opaque = true;
      82           0 :     this->renderOrder = aView->HasDepthBuffer()
      83           0 :                         ? RenderOrder::FrontToBack
      84             :                         : RenderOrder::BackToFront;
      85             :   }
      86             : 
      87           0 :   this->type = RenderPassMLGPU::GetPreferredPassType(aBuilder, *this);
      88           0 : }
      89             : 
      90             : RenderPassType
      91           0 : RenderPassMLGPU::GetPreferredPassType(FrameBuilder* aBuilder, const ItemInfo& aItem)
      92             : {
      93           0 :   LayerMLGPU* layer = aItem.layer;
      94           0 :   switch (layer->GetType()) {
      95             :   case Layer::TYPE_COLOR:
      96             :   {
      97           0 :     if (aBuilder->GetDevice()->CanUseClearView() &&
      98           0 :         aItem.HasRectTransformAndClip() &&
      99           0 :         aItem.translation &&
     100           0 :         aItem.opaque &&
     101           0 :         !aItem.view->HasDepthBuffer())
     102             :     {
     103             :       // Note: we don't have ClearView set up to do depth buffer writes, so we
     104             :       // exclude depth buffering from the test above.
     105           0 :       return RenderPassType::ClearView;
     106             :     }
     107           0 :     return RenderPassType::SolidColor;
     108             :   }
     109             :   case Layer::TYPE_PAINTED: {
     110           0 :     PaintedLayerMLGPU* painted = layer->AsPaintedLayerMLGPU();
     111           0 :     if (painted->HasComponentAlpha()) {
     112           0 :       return RenderPassType::ComponentAlpha;
     113             :     }
     114           0 :     return RenderPassType::SingleTexture;
     115             :   }
     116             :   case Layer::TYPE_CANVAS:
     117           0 :     return RenderPassType::SingleTexture;
     118             :   case Layer::TYPE_IMAGE: {
     119           0 :     ImageHost* host = layer->AsTexturedLayerMLGPU()->GetImageHost();
     120           0 :     TextureHost* texture = host->CurrentTextureHost();
     121           0 :     if (texture->GetReadFormat() == SurfaceFormat::YUV ||
     122           0 :         texture->GetReadFormat() == SurfaceFormat::NV12)
     123             :     {
     124           0 :       return RenderPassType::Video;
     125             :     }
     126           0 :     return RenderPassType::SingleTexture;
     127             :   }
     128             :   case Layer::TYPE_CONTAINER:
     129           0 :     return RenderPassType::RenderView;
     130             :   default:
     131           0 :     return RenderPassType::Unknown;
     132             :   }
     133             : }
     134             : 
     135             : RefPtr<RenderPassMLGPU>
     136           0 : RenderPassMLGPU::CreatePass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     137             : {
     138           0 :   switch (aItem.type) {
     139             :   case RenderPassType::SolidColor:
     140           0 :     return MakeAndAddRef<SolidColorPass>(aBuilder, aItem);
     141             :   case RenderPassType::SingleTexture:
     142           0 :     return MakeAndAddRef<SingleTexturePass>(aBuilder, aItem);
     143             :   case RenderPassType::RenderView:
     144           0 :     return MakeAndAddRef<RenderViewPass>(aBuilder, aItem);
     145             :   case RenderPassType::Video:
     146           0 :     return MakeAndAddRef<VideoRenderPass>(aBuilder, aItem);
     147             :   case RenderPassType::ComponentAlpha:
     148           0 :     return MakeAndAddRef<ComponentAlphaPass>(aBuilder, aItem);
     149             :   case RenderPassType::ClearView:
     150           0 :     return MakeAndAddRef<ClearViewPass>(aBuilder, aItem);
     151             :   default:
     152           0 :     return nullptr;
     153             :   }
     154             : }
     155             : 
     156           0 : RenderPassMLGPU::RenderPassMLGPU(FrameBuilder* aBuilder, const ItemInfo& aItem)
     157             :  : mBuilder(aBuilder),
     158             :    mDevice(aBuilder->GetDevice()),
     159           0 :    mLayerBufferIndex(aBuilder->CurrentLayerBufferIndex()),
     160             :    mMaskRectBufferIndex(kInvalidResourceIndex),
     161           0 :    mPrepared(false)
     162             : {
     163           0 : }
     164             : 
     165           0 : RenderPassMLGPU::~RenderPassMLGPU()
     166             : {
     167           0 : }
     168             : 
     169             : bool
     170           0 : RenderPassMLGPU::IsCompatible(const ItemInfo& aItem)
     171             : {
     172           0 :   if (GetType() != aItem.type) {
     173           0 :     return false;
     174             :   }
     175           0 :   if (mLayerBufferIndex != mBuilder->CurrentLayerBufferIndex()) {
     176           0 :     return false;
     177             :   }
     178           0 :   return true;
     179             : }
     180             : 
     181             : bool
     182           0 : RenderPassMLGPU::AcceptItem(ItemInfo& aInfo)
     183             : {
     184           0 :   MOZ_ASSERT(IsCompatible(aInfo));
     185             : 
     186           0 :   if (!AddToPass(aInfo.layer, aInfo)) {
     187           0 :     return false;
     188             :   }
     189             : 
     190           0 :   if (aInfo.renderOrder == RenderOrder::BackToFront) {
     191           0 :     mAffectedRegion.OrWith(aInfo.bounds);
     192           0 :     mAffectedRegion.SimplifyOutward(4);
     193             :   }
     194           0 :   return true;
     195             : }
     196             : 
     197             : bool
     198           0 : RenderPassMLGPU::Intersects(const ItemInfo& aItem)
     199             : {
     200           0 :   MOZ_ASSERT(aItem.renderOrder == RenderOrder::BackToFront);
     201           0 :   return !mAffectedRegion.Intersect(aItem.bounds).IsEmpty();
     202             : }
     203             : 
     204             : void
     205           0 : RenderPassMLGPU::PrepareForRendering()
     206             : {
     207           0 :   mPrepared = true;
     208           0 : }
     209             : 
     210           0 : ShaderRenderPass::ShaderRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     211             :  : RenderPassMLGPU(aBuilder, aItem),
     212             :    mGeometry(GeometryMode::Unknown),
     213           0 :    mHasRectTransformAndClip(aItem.HasRectTransformAndClip())
     214             : {
     215           0 :   mMask = aItem.layer->GetMask();
     216           0 :   if (mMask) {
     217           0 :     mMaskRectBufferIndex = mBuilder->CurrentMaskRectBufferIndex();
     218             :   }
     219           0 : }
     220             : 
     221             : bool
     222           0 : ShaderRenderPass::IsCompatible(const ItemInfo& aItem)
     223             : {
     224           0 :   MOZ_ASSERT(mGeometry != GeometryMode::Unknown);
     225             : 
     226           0 :   if (!RenderPassMLGPU::IsCompatible(aItem)) {
     227           0 :     return false;
     228             :   }
     229             : 
     230             :   // A masked batch cannot accept non-masked items, since the pixel shader
     231             :   // bakes in whether a mask is present. Also, the pixel shader can only bind
     232             :   // one specific mask at a time.
     233           0 :   if (aItem.layer->GetMask() != mMask) {
     234           0 :     return false;
     235             :   }
     236           0 :   if (mMask && mBuilder->CurrentMaskRectBufferIndex() != mMaskRectBufferIndex) {
     237           0 :     return false;
     238             :   }
     239             : 
     240             :   // We key batches on this property, since we can use more efficient pixel
     241             :   // shaders if we don't need to propagate a clip and a mask.
     242           0 :   if (mHasRectTransformAndClip != aItem.HasRectTransformAndClip()) {
     243           0 :     return false;
     244             :   }
     245             : 
     246             :   // We should be assured at this point, that if the item requires complex
     247             :   // geometry, then it should have already been rejected from a unit-quad
     248             :   // batch. Therefore this batch should be in polygon mode.
     249           0 :   MOZ_ASSERT_IF(aItem.geometry.isSome(), mGeometry == GeometryMode::Polygon);
     250           0 :   return true;
     251             : }
     252             : 
     253             : void
     254           0 : ShaderRenderPass::SetGeometry(const ItemInfo& aItem, GeometryMode aMode)
     255             : {
     256           0 :   MOZ_ASSERT(mGeometry == GeometryMode::Unknown);
     257             : 
     258           0 :   if (aMode == GeometryMode::Unknown) {
     259           0 :     mGeometry = mHasRectTransformAndClip
     260           0 :                 ? GeometryMode::UnitQuad
     261             :                 : GeometryMode::Polygon;
     262             :   } else {
     263           0 :     mGeometry = aMode;
     264             :   }
     265             : 
     266             :   // Since we process layers front-to-back, back-to-front items are
     267             :   // in the wrong order. We address this by automatically reversing
     268             :   // the buffers we use to build vertices.
     269           0 :   if (aItem.renderOrder != RenderOrder::FrontToBack) {
     270           0 :     mInstances.SetReversed();
     271             :   }
     272           0 : }
     273             : 
     274             : void
     275           0 : ShaderRenderPass::PrepareForRendering()
     276             : {
     277           0 :   if (mInstances.IsEmpty()) {
     278           0 :     return;
     279             :   }
     280           0 :   if (!mDevice->GetSharedVertexBuffer()->Allocate(&mInstanceBuffer, mInstances) ||
     281           0 :       !SetupPSBuffer0(GetOpacity()) ||
     282           0 :       !OnPrepareBuffers())
     283             :   {
     284           0 :     return;
     285             :   }
     286           0 :   return RenderPassMLGPU::PrepareForRendering();
     287             : }
     288             : 
     289             : bool
     290           0 : ShaderRenderPass::SetupPSBuffer0(float aOpacity)
     291             : {
     292           0 :   if (aOpacity == 1.0f && !HasMask()) {
     293           0 :     mPSBuffer0 = mBuilder->GetDefaultMaskInfo();
     294           0 :     return true;
     295             :   }
     296             : 
     297           0 :   MaskInformation cb(aOpacity, HasMask());
     298           0 :   return mDevice->GetSharedPSBuffer()->Allocate(&mPSBuffer0, cb);
     299             : }
     300             : 
     301             : void
     302           0 : ShaderRenderPass::ExecuteRendering()
     303             : {
     304           0 :   if (mInstances.IsEmpty()) {
     305           0 :     return;
     306             :   }
     307             : 
     308           0 :   mDevice->SetPSConstantBuffer(0, &mPSBuffer0);
     309           0 :   if (MaskOperation* mask = GetMask()) {
     310           0 :     mDevice->SetPSTexture(kMaskLayerTextureSlot, mask->GetTexture());
     311           0 :     mDevice->SetSamplerMode(kMaskSamplerSlot, SamplerMode::LinearClampToZero);
     312             :   }
     313             : 
     314           0 :   SetupPipeline();
     315             : 
     316           0 :   if (mGeometry == GeometryMode::Polygon) {
     317           0 :     mDevice->SetTopology(MLGPrimitiveTopology::UnitTriangle);
     318             :   } else {
     319           0 :     mDevice->SetTopology(MLGPrimitiveTopology::UnitQuad);
     320             :   }
     321           0 :   mDevice->SetVertexBuffer(1, &mInstanceBuffer);
     322             : 
     323           0 :   if (mGeometry == GeometryMode::Polygon) {
     324           0 :     mDevice->DrawInstanced(3, mInstanceBuffer.NumVertices(), 0, 0);
     325             :   } else {
     326           0 :     mDevice->DrawInstanced(4, mInstanceBuffer.NumVertices(), 0, 0);
     327             :   }
     328             : }
     329             : 
     330             : static inline Color
     331           0 : ComputeLayerColor(LayerMLGPU* aLayer, const Color& aColor)
     332             : {
     333           0 :   float opacity = aLayer->GetComputedOpacity();
     334           0 :   return Color(
     335           0 :     aColor.r * aColor.a * opacity,
     336           0 :     aColor.g * aColor.a * opacity,
     337           0 :     aColor.b * aColor.a * opacity,
     338           0 :     aColor.a * opacity);
     339             : }
     340             : 
     341           0 : ClearViewPass::ClearViewPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     342             :  : RenderPassMLGPU(aBuilder, aItem),
     343           0 :    mView(aItem.view)
     344             : {
     345             :   // Note: we could write to the depth buffer, but since the depth buffer is
     346             :   // disabled by default, we don't bother yet.
     347           0 :   MOZ_ASSERT(!mView->HasDepthBuffer());
     348             : 
     349           0 :   ColorLayer* colorLayer = aItem.layer->GetLayer()->AsColorLayer();
     350           0 :   mColor = ComputeLayerColor(aItem.layer, colorLayer->GetColor());
     351           0 : }
     352             : 
     353             : bool
     354           0 : ClearViewPass::IsCompatible(const ItemInfo& aItem)
     355             : {
     356           0 :   if (!RenderPassMLGPU::IsCompatible(aItem)) {
     357           0 :     return false;
     358             :   }
     359             : 
     360             :   // These should be true if we computed a ClearView pass type.
     361           0 :   MOZ_ASSERT(aItem.translation);
     362           0 :   MOZ_ASSERT(aItem.opaque);
     363           0 :   MOZ_ASSERT(aItem.HasRectTransformAndClip());
     364             : 
     365             :   // Each call only supports a single color.
     366           0 :   ColorLayer* colorLayer = aItem.layer->GetLayer()->AsColorLayer();
     367           0 :   if (mColor != ComputeLayerColor(aItem.layer, colorLayer->GetColor())) {
     368           0 :     return false;
     369             :   }
     370             : 
     371             :   // We don't support opacity here since it would not blend correctly.
     372           0 :   MOZ_ASSERT(mColor.a == 1.0f);
     373           0 :   return true;
     374             : }
     375             : 
     376             : bool
     377           0 : ClearViewPass::AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo)
     378             : {
     379           0 :   const LayerIntRegion& region = aItem->GetShadowVisibleRegion();
     380           0 :   for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
     381           0 :     IntRect rect = iter.Get().ToUnknownRect();
     382           0 :     rect += aInfo.translation.value();
     383           0 :     rect -= mView->GetTargetOffset();
     384           0 :     mRects.AppendElement(rect);
     385             :   }
     386           0 :   return true;
     387             : }
     388             : 
     389             : void
     390           0 : ClearViewPass::ExecuteRendering()
     391             : {
     392           0 :   mDevice->ClearView(mDevice->GetRenderTarget(), mColor, mRects.Elements(), mRects.Length());
     393           0 : }
     394             : 
     395           0 : SolidColorPass::SolidColorPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     396           0 :  : BatchRenderPass(aBuilder, aItem)
     397             : {
     398           0 :   SetDefaultGeometry(aItem);
     399           0 : }
     400             : 
     401             : bool
     402           0 : SolidColorPass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aInfo)
     403             : {
     404           0 :   MOZ_ASSERT(aLayer->GetType() == Layer::TYPE_COLOR);
     405             : 
     406           0 :   ColorLayer* colorLayer = aLayer->GetLayer()->AsColorLayer();
     407             : 
     408           0 :   Txn txn(this);
     409             : 
     410           0 :   gfx::Color color = ComputeLayerColor(aLayer, colorLayer->GetColor());
     411             : 
     412           0 :   const LayerIntRegion& region = aLayer->GetShadowVisibleRegion();
     413           0 :   for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
     414           0 :     const IntRect rect = iter.Get().ToUnknownRect();
     415           0 :     ColorTraits traits(aInfo, Rect(rect), color);
     416             : 
     417           0 :     if (!txn.Add(traits)) {
     418           0 :       return false;
     419             :     }
     420             :   }
     421           0 :   return txn.Commit();
     422             : }
     423             : 
     424             : float
     425           0 : SolidColorPass::GetOpacity() const
     426             : {
     427             :   // Note our pixel shader just ignores the opacity, since we baked it
     428             :   // into our color values already. Just return 1, which ensures we can
     429             :   // use the default constant buffer binding.
     430           0 :   return 1.0f;
     431             : }
     432             : 
     433             : void
     434           0 : SolidColorPass::SetupPipeline()
     435             : {
     436           0 :   if (mGeometry == GeometryMode::UnitQuad) {
     437           0 :     mDevice->SetVertexShader(VertexShaderID::ColoredQuad);
     438           0 :     mDevice->SetPixelShader(PixelShaderID::ColoredQuad);
     439             :   } else {
     440           0 :     mDevice->SetVertexShader(VertexShaderID::ColoredVertex);
     441           0 :     mDevice->SetPixelShader(PixelShaderID::ColoredVertex);
     442             :   }
     443           0 : }
     444             : 
     445           0 : TexturedRenderPass::TexturedRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     446             :  : BatchRenderPass(aBuilder, aItem),
     447           0 :    mTextureFlags(TextureFlags::NO_FLAGS)
     448             : {
     449           0 : }
     450             : 
     451             : bool
     452           0 : TexturedRenderPass::AddItem(Txn& aTxn,
     453             :                             const ItemInfo& aInfo,
     454             :                             const Rect& aDrawRect,
     455             :                             const Point& aDestOrigin,
     456             :                             const IntSize& aTextureSize,
     457             :                             const Maybe<Size>& aScale)
     458             : {
     459             : 
     460           0 :   if (mGeometry == GeometryMode::Polygon) {
     461             :     // This path will not clamp the draw rect to the layer clip, so we can pass
     462             :     // the draw rect texture rects straight through.
     463           0 :     return AddClippedItem(aTxn, aInfo, aDrawRect, aDestOrigin, aTextureSize, aScale);
     464             :   }
     465             : 
     466           0 :   MOZ_ASSERT(!aInfo.geometry);
     467           0 :   MOZ_ASSERT(aInfo.HasRectTransformAndClip());
     468           0 :   MOZ_ASSERT(mHasRectTransformAndClip);
     469             : 
     470           0 :   const Matrix4x4& fullTransform = aInfo.layer->GetLayer()->GetEffectiveTransformForBuffer();
     471           0 :   Matrix transform = fullTransform.As2D();
     472           0 :   Matrix inverse = transform.Inverse();
     473           0 :   MOZ_ASSERT(inverse.IsRectilinear());
     474             : 
     475             :   // Transform the clip rect.
     476           0 :   IntRect clipRect = aInfo.layer->GetComputedClipRect().ToUnknownRect();
     477           0 :   clipRect += aInfo.view->GetTargetOffset();
     478             : 
     479             :   // Clip and adjust the texture rect.
     480           0 :   Rect localClip = inverse.TransformBounds(Rect(clipRect));
     481           0 :   Rect clippedDrawRect = aDrawRect.Intersect(localClip);
     482           0 :   if (clippedDrawRect.IsEmpty()) {
     483           0 :     return true;
     484             :   }
     485             : 
     486           0 :   return AddClippedItem(aTxn, aInfo, clippedDrawRect, aDestOrigin, aTextureSize, aScale);
     487             : }
     488             : 
     489             : bool
     490           0 : TexturedRenderPass::AddClippedItem(Txn& aTxn,
     491             :                                    const ItemInfo& aInfo,
     492             :                                    const gfx::Rect& aDrawRect,
     493             :                                    const gfx::Point& aDestOrigin,
     494             :                                    const gfx::IntSize& aTextureSize,
     495             :                                    const Maybe<gfx::Size>& aScale)
     496             : {
     497           0 :   float xScale = aScale ? aScale->width : 1.0f;
     498           0 :   float yScale = aScale ? aScale->height : 1.0f;
     499             : 
     500           0 :   Point offset = aDrawRect.TopLeft() - aDestOrigin;
     501             :   Rect textureRect(
     502           0 :     offset.x * xScale,
     503           0 :     offset.y * yScale,
     504           0 :     aDrawRect.width * xScale,
     505           0 :     aDrawRect.height * yScale);
     506             : 
     507           0 :   Rect textureCoords = TextureRectToCoords(textureRect, aTextureSize);
     508           0 :   if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
     509           0 :     textureCoords.y = 1.0 - textureCoords.y;
     510           0 :     textureCoords.height = -textureCoords.height;
     511             :   }
     512             : 
     513           0 :   Rect layerRects[4];
     514           0 :   Rect textureRects[4];
     515             :   size_t numRects =
     516           0 :     DecomposeIntoNoRepeatRects(aDrawRect, textureCoords, &layerRects, &textureRects);
     517             : 
     518           0 :   for (size_t i = 0; i < numRects; i++) {
     519           0 :     TexturedTraits traits(aInfo, layerRects[i], textureRects[i]);
     520           0 :     if (!aTxn.Add(traits)) {
     521           0 :       return false;
     522             :     }
     523             :   }
     524           0 :   return true;
     525             : }
     526             : 
     527           0 : SingleTexturePass::SingleTexturePass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     528             :  : TexturedRenderPass(aBuilder, aItem),
     529           0 :    mOpacity(1.0f)
     530             : {
     531           0 :   SetDefaultGeometry(aItem);
     532           0 : }
     533             : 
     534             : bool
     535           0 : SingleTexturePass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aInfo)
     536             : {
     537           0 :   RefPtr<TextureSource> texture;
     538             : 
     539             :   gfx::SamplingFilter filter;
     540           0 :   TextureFlags flags = TextureFlags::NO_FLAGS;
     541           0 :   if (PaintedLayerMLGPU* paintedLayer = aLayer->AsPaintedLayerMLGPU()) {
     542           0 :     if (paintedLayer->HasComponentAlpha()) {
     543           0 :       return false;
     544             :     }
     545           0 :     texture = paintedLayer->GetTexture();
     546           0 :     filter = SamplingFilter::LINEAR;
     547           0 :   } else if (TexturedLayerMLGPU* texLayer = aLayer->AsTexturedLayerMLGPU()) {
     548           0 :     texture = texLayer->GetTexture();
     549           0 :     filter = texLayer->GetSamplingFilter();
     550           0 :     TextureHost* host = texLayer->GetImageHost()->CurrentTextureHost();
     551           0 :     flags = host->GetFlags();
     552             :   } else {
     553           0 :     return false;
     554             :   }
     555             : 
     556             :   // We should not assign a texture-based layer to tiles if it has no texture.
     557           0 :   MOZ_ASSERT(texture);
     558             : 
     559           0 :   float opacity = aLayer->GetComputedOpacity();
     560           0 :   if (mTexture) {
     561           0 :     if (texture != mTexture) {
     562           0 :       return false;
     563             :     }
     564           0 :     if (mFilter != filter) {
     565           0 :       return false;
     566             :     }
     567           0 :     if (mOpacity != opacity) {
     568           0 :       return false;
     569             :     }
     570             :     // Note: premultiplied, origin-bottom-left are already implied by the texture source.
     571             :   } else {
     572           0 :     mTexture = texture;
     573           0 :     mFilter = filter;
     574           0 :     mOpacity = opacity;
     575           0 :     mTextureFlags = flags;
     576             :   }
     577             : 
     578           0 :   Txn txn(this);
     579             : 
     580           0 :   if (PaintedLayerMLGPU* layer = aLayer->AsPaintedLayerMLGPU()) {
     581           0 :     nsIntRegion visible = layer->GetRenderRegion();
     582           0 :     IntPoint offset = layer->GetContentHost()->GetOriginOffset();
     583             : 
     584           0 :     if (!AddItems(txn, aInfo, visible, offset, mTexture->GetSize())) {
     585           0 :       return false;
     586             :     }
     587           0 :   } else if (TexturedLayerMLGPU* layer = aLayer->AsTexturedLayerMLGPU()) {
     588           0 :     IntPoint origin(0, 0);
     589           0 :     Maybe<Size> pictureScale = layer->GetPictureScale();
     590           0 :     nsIntRegion visible = layer->GetShadowVisibleRegion().ToUnknownRegion();
     591             : 
     592           0 :     if (!AddItems(txn, aInfo, visible, origin, mTexture->GetSize(), pictureScale)) {
     593           0 :       return false;
     594             :     }
     595             :   }
     596             : 
     597           0 :   return txn.Commit();
     598             : }
     599             : 
     600             : Maybe<MLGBlendState>
     601           0 : SingleTexturePass::GetBlendState() const
     602             : {
     603           0 :   return (mTextureFlags & TextureFlags::NON_PREMULTIPLIED)
     604             :          ? Some(MLGBlendState::OverAndPremultiply)
     605           0 :          : Some(MLGBlendState::Over);
     606             : }
     607             : 
     608             : void
     609           0 : SingleTexturePass::SetupPipeline()
     610             : {
     611           0 :   MOZ_ASSERT(mTexture);
     612             : 
     613           0 :   if (mGeometry == GeometryMode::UnitQuad) {
     614           0 :     mDevice->SetVertexShader(VertexShaderID::TexturedQuad);
     615             :   } else {
     616           0 :     mDevice->SetVertexShader(VertexShaderID::TexturedVertex);
     617             :   }
     618             : 
     619           0 :   mDevice->SetPSTexture(0, mTexture);
     620           0 :   mDevice->SetSamplerMode(kDefaultSamplerSlot, mFilter);
     621           0 :   switch (mTexture.get()->GetFormat()) {
     622             :     case SurfaceFormat::B8G8R8A8:
     623             :     case SurfaceFormat::R8G8B8A8:
     624           0 :       if (mGeometry == GeometryMode::UnitQuad)
     625           0 :         mDevice->SetPixelShader(PixelShaderID::TexturedQuadRGBA);
     626             :       else
     627           0 :         mDevice->SetPixelShader(PixelShaderID::TexturedVertexRGBA);
     628           0 :       break;
     629             :     default:
     630           0 :       if (mGeometry == GeometryMode::UnitQuad)
     631           0 :         mDevice->SetPixelShader(PixelShaderID::TexturedQuadRGB);
     632             :       else
     633           0 :         mDevice->SetPixelShader(PixelShaderID::TexturedVertexRGB);
     634           0 :       break;
     635             :   }
     636           0 : }
     637             : 
     638           0 : ComponentAlphaPass::ComponentAlphaPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     639             : : TexturedRenderPass(aBuilder, aItem),
     640           0 :   mAssignedLayer(nullptr)
     641             : {
     642           0 :   SetDefaultGeometry(aItem);
     643           0 : }
     644             : 
     645             : bool
     646           0 : ComponentAlphaPass::AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo)
     647             : {
     648           0 :   PaintedLayerMLGPU* layer = aItem->AsPaintedLayerMLGPU();
     649           0 :   MOZ_ASSERT(layer);
     650             : 
     651           0 :   if (mAssignedLayer && mAssignedLayer != layer) {
     652           0 :     return false;
     653             :   }
     654           0 :   if (!mAssignedLayer) {
     655           0 :     mAssignedLayer = layer;
     656           0 :     mTextureOnBlack = layer->GetTexture();
     657           0 :     mTextureOnWhite = layer->GetTextureOnWhite();
     658             :   } 
     659             : 
     660           0 :   Txn txn(this);
     661             : 
     662           0 :   nsIntRegion visible = layer->GetRenderRegion();
     663           0 :   IntPoint offset = layer->GetContentHost()->GetOriginOffset();
     664             : 
     665           0 :   if (!AddItems(txn, aInfo, visible, offset, mTextureOnWhite->GetSize())) {
     666           0 :     return false;
     667             :   }
     668           0 :   return txn.Commit();
     669             : }
     670             : 
     671             : float
     672           0 : ComponentAlphaPass::GetOpacity() const
     673             : {
     674           0 :   return mAssignedLayer->GetComputedOpacity();
     675             : }
     676             : 
     677             : void
     678           0 : ComponentAlphaPass::SetupPipeline()
     679             : {
     680             :   TextureSource* textures[2] = {
     681             :     mTextureOnBlack,
     682             :     mTextureOnWhite
     683           0 :   };
     684           0 :   MOZ_ASSERT(textures[0]);
     685           0 :   MOZ_ASSERT(textures[1]);
     686             : 
     687           0 :   if (mGeometry == GeometryMode::UnitQuad) {
     688           0 :     mDevice->SetVertexShader(VertexShaderID::TexturedQuad);
     689           0 :     mDevice->SetPixelShader(PixelShaderID::ComponentAlphaQuad);
     690             :   } else {
     691           0 :     mDevice->SetVertexShader(VertexShaderID::TexturedVertex);
     692           0 :     mDevice->SetPixelShader(PixelShaderID::ComponentAlphaVertex);
     693             :   }
     694             : 
     695           0 :   mDevice->SetSamplerMode(kDefaultSamplerSlot, SamplerMode::LinearClamp);
     696           0 :   mDevice->SetPSTextures(0, 2, textures);
     697           0 : }
     698             : 
     699           0 : VideoRenderPass::VideoRenderPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     700             :  : TexturedRenderPass(aBuilder, aItem),
     701           0 :    mOpacity(1.0f)
     702             : {
     703           0 :   SetDefaultGeometry(aItem);
     704           0 : }
     705             : 
     706             : bool
     707           0 : VideoRenderPass::AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo)
     708             : {
     709           0 :   ImageLayerMLGPU* layer = aItem->AsImageLayerMLGPU();
     710           0 :   if (!layer) {
     711           0 :     return false;
     712             :   }
     713             : 
     714           0 :   RefPtr<TextureHost> host = layer->GetImageHost()->CurrentTextureHost();
     715           0 :   RefPtr<TextureSource> source = layer->GetTexture();
     716           0 :   float opacity = layer->GetComputedOpacity();
     717           0 :   SamplingFilter filter = layer->GetSamplingFilter();
     718             : 
     719           0 :   if (mHost) {
     720           0 :     if (mHost != host) {
     721           0 :       return false;
     722             :     }
     723           0 :     if (mTexture != source) {
     724           0 :       return false;
     725             :     }
     726           0 :     if (mOpacity != opacity) {
     727           0 :       return false;
     728             :     }
     729           0 :     if (mFilter != filter) {
     730           0 :       return false;
     731             :     }
     732             :   } else {
     733           0 :     mHost = host;
     734           0 :     mTexture = source;
     735           0 :     mOpacity = opacity;
     736           0 :     mFilter = filter;
     737             :   }
     738           0 :   MOZ_ASSERT(!mTexture->AsBigImageIterator());
     739           0 :   MOZ_ASSERT(!(mHost->GetFlags() & TextureFlags::NON_PREMULTIPLIED));
     740           0 :   MOZ_ASSERT(!(mHost->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT));
     741             : 
     742           0 :   Txn txn(this);
     743             : 
     744           0 :   IntPoint origin(0, 0);
     745           0 :   Maybe<Size> pictureScale = layer->GetPictureScale();
     746           0 :   nsIntRegion visible = layer->GetShadowVisibleRegion().ToUnknownRegion();
     747             : 
     748           0 :   if (!AddItems(txn, aInfo, visible, origin, mTexture->GetSize(), pictureScale)) {
     749           0 :     return false;
     750             :   }
     751           0 :   return txn.Commit();
     752             : }
     753             : 
     754             : void
     755           0 : VideoRenderPass::SetupPipeline()
     756             : {
     757           0 :   YUVColorSpace colorSpace = YUVColorSpace::UNKNOWN;
     758           0 :   switch (mHost->GetReadFormat()) {
     759             :   case SurfaceFormat::YUV: {
     760           0 :     colorSpace = mHost->GetYUVColorSpace();
     761           0 :     break;
     762             :   }
     763             :   case SurfaceFormat::NV12:
     764           0 :     colorSpace = YUVColorSpace::BT601;
     765           0 :     break;
     766             :   default:
     767           0 :     MOZ_ASSERT_UNREACHABLE("Unexpected surface format in VideoRenderPass");
     768             :     break;
     769             :   }
     770           0 :   MOZ_ASSERT(colorSpace != YUVColorSpace::UNKNOWN);
     771             : 
     772           0 :   RefPtr<MLGBuffer> ps1 = mDevice->GetBufferForColorSpace(colorSpace);
     773           0 :   if (!ps1) {
     774           0 :     return;
     775             :   }
     776             : 
     777           0 :   if (mGeometry == GeometryMode::UnitQuad) {
     778           0 :     mDevice->SetVertexShader(VertexShaderID::TexturedQuad);
     779             :   } else {
     780           0 :     mDevice->SetVertexShader(VertexShaderID::TexturedVertex);
     781             :   }
     782             : 
     783           0 :   switch (mHost->GetReadFormat()) {
     784             :   case SurfaceFormat::YUV:
     785             :   {
     786           0 :     if (mGeometry == GeometryMode::UnitQuad)
     787           0 :       mDevice->SetPixelShader(PixelShaderID::TexturedQuadIMC4);
     788             :     else
     789           0 :       mDevice->SetPixelShader(PixelShaderID::TexturedVertexIMC4);
     790           0 :     mDevice->SetPSTexturesYUV(0, mTexture);
     791           0 :     break;
     792             :   }
     793             :   case SurfaceFormat::NV12:
     794           0 :     if (mGeometry == GeometryMode::UnitQuad)
     795           0 :       mDevice->SetPixelShader(PixelShaderID::TexturedQuadNV12);
     796             :     else
     797           0 :       mDevice->SetPixelShader(PixelShaderID::TexturedVertexNV12);
     798           0 :     mDevice->SetPSTexturesNV12(0, mTexture);
     799           0 :     break;
     800             :   default:
     801           0 :     MOZ_ASSERT_UNREACHABLE("Unknown video format");
     802             :     break;
     803             :   }
     804             : 
     805           0 :   mDevice->SetSamplerMode(kDefaultSamplerSlot, mFilter);
     806           0 :   mDevice->SetPSConstantBuffer(1, ps1);
     807             : }
     808             : 
     809           0 : RenderViewPass::RenderViewPass(FrameBuilder* aBuilder, const ItemInfo& aItem)
     810             :  : TexturedRenderPass(aBuilder, aItem),
     811           0 :    mParentView(nullptr)
     812             : {
     813           0 :   mAssignedLayer = aItem.layer->AsContainerLayerMLGPU();
     814             : 
     815           0 :   CompositionOp blendOp = mAssignedLayer->GetMixBlendMode();
     816           0 :   if (BlendOpIsMixBlendMode(blendOp)) {
     817           0 :     mBlendMode = Some(blendOp);
     818             :   }
     819             : 
     820           0 :   if (mBlendMode) {
     821             :     // We do not have fast-path rect shaders for blending.
     822           0 :     SetGeometry(aItem, GeometryMode::Polygon);
     823             :   } else {
     824           0 :     SetDefaultGeometry(aItem);
     825             :   }
     826           0 : }
     827             : 
     828             : bool
     829           0 : RenderViewPass::AddToPass(LayerMLGPU* aLayer, ItemInfo& aInfo)
     830             : {
     831             :   // We bake in the layer ahead of time, which also guarantees the blend mode
     832             :   // is baked in, as well as the geometry requirement.
     833           0 :   if (mAssignedLayer != aLayer) {
     834           0 :     return false;
     835             :   }
     836             : 
     837           0 :   mSource = mAssignedLayer->GetRenderTarget();
     838           0 :   if (!mSource) {
     839           0 :     return false;
     840             :   }
     841             : 
     842           0 :   mParentView = aInfo.view;
     843             : 
     844           0 :   Txn txn(this);
     845             : 
     846           0 :   IntPoint offset = mAssignedLayer->GetTargetOffset();
     847           0 :   IntSize size = mAssignedLayer->GetTargetSize();
     848             : 
     849             :   // Clamp the visible region to the texture size.
     850           0 :   nsIntRegion visible = mAssignedLayer->GetShadowVisibleRegion().ToUnknownRegion();
     851           0 :   visible.AndWith(IntRect(offset, size));
     852             : 
     853           0 :   if (!AddItems(txn, aInfo, visible, offset, size)) {
     854           0 :     return false;
     855             :   }
     856           0 :   return txn.Commit();
     857             : }
     858             : 
     859             : float
     860           0 : RenderViewPass::GetOpacity() const
     861             : {
     862           0 :   return mAssignedLayer->GetLayer()->GetEffectiveOpacity();
     863             : }
     864             : 
     865             : bool
     866           0 : RenderViewPass::OnPrepareBuffers()
     867             : {
     868           0 :   if (mBlendMode && !PrepareBlendState()) {
     869           0 :     return false;
     870             :   }
     871           0 :   return true;
     872             : }
     873             : 
     874             : static inline PixelShaderID
     875           0 : GetShaderForBlendMode(CompositionOp aOp)
     876             : {
     877           0 :   switch (aOp) {
     878           0 :   case CompositionOp::OP_MULTIPLY: return PixelShaderID::BlendMultiply;
     879           0 :   case CompositionOp::OP_SCREEN: return PixelShaderID::BlendScreen;
     880           0 :   case CompositionOp::OP_OVERLAY: return PixelShaderID::BlendOverlay;
     881           0 :   case CompositionOp::OP_DARKEN: return PixelShaderID::BlendDarken;
     882           0 :   case CompositionOp::OP_LIGHTEN: return PixelShaderID::BlendLighten;
     883           0 :   case CompositionOp::OP_COLOR_DODGE: return PixelShaderID::BlendColorDodge;
     884           0 :   case CompositionOp::OP_COLOR_BURN: return PixelShaderID::BlendColorBurn;
     885           0 :   case CompositionOp::OP_HARD_LIGHT: return PixelShaderID::BlendHardLight;
     886           0 :   case CompositionOp::OP_SOFT_LIGHT: return PixelShaderID::BlendSoftLight;
     887           0 :   case CompositionOp::OP_DIFFERENCE: return PixelShaderID::BlendDifference;
     888           0 :   case CompositionOp::OP_EXCLUSION: return PixelShaderID::BlendExclusion;
     889           0 :   case CompositionOp::OP_HUE: return PixelShaderID::BlendHue;
     890           0 :   case CompositionOp::OP_SATURATION: return PixelShaderID::BlendSaturation;
     891           0 :   case CompositionOp::OP_COLOR: return PixelShaderID::BlendColor;
     892           0 :   case CompositionOp::OP_LUMINOSITY: return PixelShaderID::BlendLuminosity;
     893             :   default:
     894           0 :     MOZ_ASSERT_UNREACHABLE("Unexpected blend mode");
     895             :     return PixelShaderID::TexturedVertexRGBA;
     896             :   }
     897             : }
     898             : 
     899             : bool
     900           0 : RenderViewPass::PrepareBlendState()
     901             : {
     902           0 :   Rect visibleRect(mAssignedLayer->GetShadowVisibleRegion().GetBounds().ToUnknownRect());
     903           0 :   IntRect clipRect(mAssignedLayer->GetComputedClipRect().ToUnknownRect());
     904           0 :   const Matrix4x4& transform = mAssignedLayer->GetLayer()->GetEffectiveTransformForBuffer();
     905             : 
     906             :   // Note that we must use our parent RenderView for this calculation,
     907             :   // since we're copying the backdrop, not our actual local target.
     908           0 :   IntRect rtRect(mParentView->GetTargetOffset(), mParentView->GetSize());
     909             : 
     910           0 :   Matrix4x4 backdropTransform;
     911             :   mBackdropCopyRect = ComputeBackdropCopyRect(
     912             :     visibleRect,
     913             :     clipRect,
     914             :     transform,
     915             :     rtRect,
     916           0 :     &backdropTransform);
     917             : 
     918           0 :   AutoBufferUpload<BlendVertexShaderConstants> cb;
     919           0 :   if (!mDevice->GetSharedVSBuffer()->Allocate(&mBlendConstants, &cb)) {
     920           0 :     return false;
     921             :   }
     922           0 :   memcpy(cb->backdropTransform, &backdropTransform._11, 64);
     923           0 :   return true;
     924             : }
     925             : 
     926             : void
     927           0 : RenderViewPass::SetupPipeline()
     928             : {
     929           0 :   if (mBlendMode) {
     930           0 :     RefPtr<MLGRenderTarget> backdrop = mParentView->GetRenderTarget();
     931           0 :     MOZ_ASSERT(mDevice->GetRenderTarget() == backdrop);
     932             : 
     933           0 :     RefPtr<MLGTexture> copy = mDevice->CreateTexture(
     934           0 :       mBackdropCopyRect.Size(),
     935             :       SurfaceFormat::B8G8R8A8,
     936             :       MLGUsage::Default,
     937           0 :       MLGTextureFlags::ShaderResource);
     938           0 :     if (!copy) {
     939           0 :       return;
     940             :     }
     941             : 
     942           0 :     mDevice->CopyTexture(
     943             :       copy,
     944           0 :       IntPoint(0, 0),
     945           0 :       backdrop->GetTexture(),
     946           0 :       mBackdropCopyRect);
     947             : 
     948           0 :     MOZ_ASSERT(mGeometry == GeometryMode::Polygon);
     949           0 :     mDevice->SetVertexShader(VertexShaderID::BlendVertex);
     950           0 :     mDevice->SetPixelShader(GetShaderForBlendMode(mBlendMode.value()));
     951           0 :     mDevice->SetVSConstantBuffer(kBlendConstantBufferSlot, &mBlendConstants);
     952           0 :     mDevice->SetPSTexture(1, copy);
     953             :   } else {
     954           0 :     if (mGeometry == GeometryMode::UnitQuad) {
     955           0 :       mDevice->SetVertexShader(VertexShaderID::TexturedQuad);
     956           0 :       mDevice->SetPixelShader(PixelShaderID::TexturedQuadRGBA);
     957             :     } else {
     958           0 :       mDevice->SetVertexShader(VertexShaderID::TexturedVertex);
     959           0 :       mDevice->SetPixelShader(PixelShaderID::TexturedVertexRGBA);
     960             :     }
     961             :   }
     962             : 
     963           0 :   mDevice->SetPSTexture(0, mSource->GetTexture());
     964           0 :   mDevice->SetSamplerMode(kDefaultSamplerSlot, SamplerMode::LinearClamp);
     965             : }
     966             : 
     967             : } // namespace layers
     968             : } // namespace mozilla

Generated by: LCOV version 1.13