LCOV - code coverage report
Current view: top level - gfx/layers/client - ClientPaintedLayer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 70 157 44.6 %
Date: 2017-07-14 16:53:18 Functions: 8 12 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; 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 "ClientPaintedLayer.h"
       7             : #include "ClientTiledPaintedLayer.h"     // for ClientTiledPaintedLayer
       8             : #include <stdint.h>                     // for uint32_t
       9             : #include "GeckoProfiler.h"              // for AUTO_PROFILER_LABEL
      10             : #include "client/ClientLayerManager.h"  // for ClientLayerManager, etc
      11             : #include "gfxContext.h"                 // for gfxContext
      12             : #include "gfx2DGlue.h"
      13             : #include "gfxRect.h"                    // for gfxRect
      14             : #include "gfxPrefs.h"                   // for gfxPrefs
      15             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
      16             : #include "mozilla/gfx/2D.h"             // for DrawTarget
      17             : #include "mozilla/gfx/DrawEventRecorder.h"
      18             : #include "mozilla/gfx/Matrix.h"         // for Matrix
      19             : #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
      20             : #include "mozilla/gfx/Types.h"          // for Float, etc
      21             : #include "mozilla/layers/LayersTypes.h"
      22             : #include "mozilla/Preferences.h"
      23             : #include "nsCOMPtr.h"                   // for already_AddRefed
      24             : #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
      25             : #include "nsRect.h"                     // for mozilla::gfx::IntRect
      26             : #include "PaintThread.h"
      27             : #include "ReadbackProcessor.h"
      28             : 
      29             : namespace mozilla {
      30             : namespace layers {
      31             : 
      32             : using namespace mozilla::gfx;
      33             : 
      34             : bool
      35          77 : ClientPaintedLayer::EnsureContentClient()
      36             : {
      37          77 :   if (!mContentClient) {
      38          44 :     mContentClient = ContentClient::CreateContentClient(
      39          44 :       ClientManager()->AsShadowForwarder());
      40             : 
      41          22 :     if (!mContentClient) {
      42           0 :       return false;
      43             :     }
      44             : 
      45          22 :     mContentClient->Connect();
      46          22 :     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
      47          22 :     MOZ_ASSERT(mContentClient->GetForwarder());
      48             :   }
      49             : 
      50          77 :   return true;
      51             : }
      52             : 
      53             : bool
      54          77 : ClientPaintedLayer::CanRecordLayer(ReadbackProcessor* aReadback)
      55             : {
      56             :   // If we don't have a paint thread, this is either not the content
      57             :   // process or the pref is disabled.
      58          77 :   if (!PaintThread::Get()) {
      59          77 :     return false;
      60             :   }
      61             : 
      62             :   // Not supported yet
      63           0 :   if (aReadback && UsedForReadback()) {
      64           0 :     return false;
      65             :   }
      66             : 
      67             :   // If we have mask layers, we have to render those first
      68             :   // In this case, don't record for now.
      69           0 :   if (GetMaskLayer()) {
      70           0 :     return false;
      71             :   }
      72             : 
      73           0 :   return GetAncestorMaskLayerCount() == 0;
      74             : }
      75             : 
      76             : void
      77          33 : ClientPaintedLayer::UpdateContentClient(PaintState& aState)
      78             : {
      79          33 :   Mutated();
      80             : 
      81          33 :   AddToValidRegion(aState.mRegionToDraw);
      82             : 
      83             :   ContentClientRemote *contentClientRemote =
      84          33 :       static_cast<ContentClientRemote *>(mContentClient.get());
      85          33 :   MOZ_ASSERT(contentClientRemote->GetIPCHandle());
      86             : 
      87             :   // Hold(this) ensures this layer is kept alive through the current transaction
      88             :   // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
      89             :   // so deleting this Hold for whatever reason will break things.
      90          33 :   ClientManager()->Hold(this);
      91          66 :   contentClientRemote->Updated(aState.mRegionToDraw,
      92          66 :                                mVisibleRegion.ToUnknownRegion(),
      93          66 :                                aState.mDidSelfCopy);
      94          33 : }
      95             : 
      96             : bool
      97          77 : ClientPaintedLayer::UpdatePaintRegion(PaintState& aState)
      98             : {
      99          77 :   SubtractFromValidRegion(aState.mRegionToInvalidate);
     100             : 
     101          77 :   if (!aState.mRegionToDraw.IsEmpty() && !ClientManager()->GetPaintedLayerCallback()) {
     102           0 :     ClientManager()->SetTransactionIncomplete();
     103           0 :     mContentClient->EndPaint(nullptr);
     104           0 :     return false;
     105             :    }
     106             : 
     107             :    // The area that became invalid and is visible needs to be repainted
     108             :    // (this could be the whole visible area if our buffer switched
     109             :    // from RGB to RGBA, because we might need to repaint with
     110             :    // subpixel AA)
     111             :   aState.mRegionToInvalidate.And(aState.mRegionToInvalidate,
     112          77 :                                  GetLocalVisibleRegion().ToUnknownRegion());
     113          77 :   return true;
     114             : }
     115             : 
     116             : void
     117           0 : ClientPaintedLayer::PaintOffMainThread(DrawTargetCapture* aCapture)
     118             : {
     119           0 :   MOZ_ASSERT(NS_IsMainThread());
     120           0 :   LayerIntRegion visibleRegion = GetVisibleRegion();
     121           0 :   mContentClient->BeginPaint();
     122             : 
     123           0 :   uint32_t flags = GetPaintFlags();
     124             : 
     125             :   PaintState state =
     126           0 :     mContentClient->BeginPaintBuffer(this, flags);
     127           0 :   if (!UpdatePaintRegion(state)) {
     128           0 :     return;
     129             :   }
     130             : 
     131           0 :   bool didUpdate = false;
     132           0 :   RotatedContentBuffer::DrawIterator iter;
     133           0 :   while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
     134           0 :     if (!target || !target->IsValid()) {
     135           0 :       if (target) {
     136           0 :         mContentClient->ReturnDrawTargetToBuffer(target);
     137             :       }
     138           0 :       continue;
     139             :     }
     140             : 
     141           0 :     SetAntialiasingFlags(this, target);
     142             : 
     143             :     // Basic version, wait for the paint thread to finish painting.
     144           0 :     PaintThread::Get()->PaintContents(aCapture, target);
     145             : 
     146           0 :     mContentClient->ReturnDrawTargetToBuffer(target);
     147           0 :     didUpdate = true;
     148           0 :   }
     149             : 
     150             :   // ending paint w/o any readback updates
     151             :   // TODO: Fix me
     152           0 :   mContentClient->EndPaint(nullptr);
     153             : 
     154           0 :   if (didUpdate) {
     155           0 :     UpdateContentClient(state);
     156             :    }
     157             :  }
     158             : 
     159             : 
     160             : uint32_t
     161          77 : ClientPaintedLayer::GetPaintFlags()
     162             : {
     163          77 :   uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
     164             :   #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
     165          77 :    if (ClientManager()->CompositorMightResample()) {
     166           0 :      flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
     167             :    }
     168          77 :    if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
     169          77 :      if (MayResample()) {
     170           0 :        flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
     171             :      }
     172             :    }
     173             :   #endif
     174          77 :   return flags;
     175             : }
     176             : 
     177             : void
     178          77 : ClientPaintedLayer::PaintThebes(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates)
     179             : {
     180         154 :   AUTO_PROFILER_LABEL("ClientPaintedLayer::PaintThebes", GRAPHICS);
     181             : 
     182          77 :   NS_ASSERTION(ClientManager()->InDrawing(),
     183             :                "Can only draw in drawing phase");
     184             : 
     185          77 :   mContentClient->BeginPaint();
     186             : 
     187          77 :   uint32_t flags = GetPaintFlags();
     188             : 
     189         154 :   PaintState state = mContentClient->BeginPaintBuffer(this, flags);
     190          77 :   if (!UpdatePaintRegion(state)) {
     191           0 :     return;
     192             :   }
     193             : 
     194          77 :   bool didUpdate = false;
     195         154 :   RotatedContentBuffer::DrawIterator iter;
     196         110 :   while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
     197          33 :     if (!target || !target->IsValid()) {
     198           0 :       if (target) {
     199           0 :         mContentClient->ReturnDrawTargetToBuffer(target);
     200             :       }
     201           0 :       continue;
     202             :     }
     203             : 
     204          33 :     SetAntialiasingFlags(this, target);
     205             : 
     206          66 :     RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
     207          33 :     MOZ_ASSERT(ctx); // already checked the target above
     208             : 
     209          33 :     ClientManager()->GetPaintedLayerCallback()(this,
     210             :                                               ctx,
     211             :                                               iter.mDrawRegion,
     212             :                                               iter.mDrawRegion,
     213             :                                               state.mClip,
     214             :                                               state.mRegionToInvalidate,
     215          33 :                                               ClientManager()->GetPaintedLayerCallbackData());
     216             : 
     217          33 :     ctx = nullptr;
     218          33 :     mContentClient->ReturnDrawTargetToBuffer(target);
     219          33 :     didUpdate = true;
     220          33 :   }
     221             : 
     222          77 :   mContentClient->EndPaint(aReadbackUpdates);
     223             : 
     224          77 :   if (didUpdate) {
     225          33 :     UpdateContentClient(state);
     226             :   }
     227             : }
     228             : 
     229             : already_AddRefed<DrawTargetCapture>
     230           0 : ClientPaintedLayer::CapturePaintedContent()
     231             : {
     232           0 :   LayerIntRegion visibleRegion = GetVisibleRegion();
     233           0 :   LayerIntRect bounds = visibleRegion.GetBounds();
     234           0 :   LayerIntSize size = bounds.Size();
     235             : 
     236           0 :   if (visibleRegion.IsEmpty()) {
     237           0 :     if (gfxPrefs::LayersDump()) {
     238           0 :       printf_stderr("PaintedLayer %p skipping\n", this);
     239             :     }
     240           0 :     return nullptr;
     241             :   }
     242             : 
     243           0 :   nsIntRegion regionToPaint;
     244           0 :   regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), GetValidRegion());
     245             : 
     246           0 :   if (regionToPaint.IsEmpty()) {
     247             :     // Do we ever have to do anything if the region to paint is empty
     248             :     // but we have a painted layer callback?
     249           0 :     return nullptr;
     250             :   }
     251             : 
     252           0 :   if (!ClientManager()->GetPaintedLayerCallback()) {
     253           0 :     ClientManager()->SetTransactionIncomplete();
     254           0 :     return nullptr;
     255             :   }
     256             : 
     257           0 :   IntSize imageSize(size.ToUnknownSize());
     258             : 
     259             :   // DrawTargetCapture requires a reference DT
     260             :   // That is used when some API requires a snapshot.
     261             :   // TODO: Fixup so DrawTargetCapture lazily creates a reference DT
     262             :   RefPtr<DrawTarget> refDT =
     263           0 :     Factory::CreateDrawTarget(gfxPlatform::GetPlatform()->GetDefaultContentBackend(),
     264           0 :                               imageSize, gfx::SurfaceFormat::B8G8R8A8);
     265             : 
     266             :   // We don't clear the rect here like WRPaintedBlobLayers do
     267             :   // because ContentClient already clears the surface for us during BeginPaint.
     268           0 :   RefPtr<DrawTargetCapture> captureDT = refDT->CreateCaptureDT(imageSize);
     269           0 :   captureDT->SetTransform(Matrix().PreTranslate(-bounds.x, -bounds.y));
     270             : 
     271           0 :   RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(captureDT);
     272           0 :   MOZ_ASSERT(ctx); // already checked the target above
     273             : 
     274           0 :   ClientManager()->GetPaintedLayerCallback()(this,
     275             :                                              ctx,
     276           0 :                                              visibleRegion.ToUnknownRegion(),
     277           0 :                                              visibleRegion.ToUnknownRegion(),
     278             :                                              DrawRegionClip::DRAW,
     279           0 :                                              nsIntRegion(),
     280           0 :                                              ClientManager()->GetPaintedLayerCallbackData());
     281             : 
     282           0 :   return captureDT.forget();
     283             : }
     284             : 
     285             : void
     286          77 : ClientPaintedLayer::RenderLayerWithReadback(ReadbackProcessor *aReadback)
     287             : {
     288          77 :   RenderMaskLayers(this);
     289             : 
     290          77 :   if (CanRecordLayer(aReadback)) {
     291           0 :     RefPtr<DrawTargetCapture> capture = CapturePaintedContent();
     292           0 :     if (capture) {
     293           0 :       if (!EnsureContentClient()) {
     294           0 :         return;
     295             :       }
     296             : 
     297           0 :       PaintOffMainThread(capture);
     298           0 :       return;
     299             :     }
     300             :   }
     301             : 
     302          77 :   if (!EnsureContentClient()) {
     303           0 :     return;
     304             :   }
     305             : 
     306         154 :   nsTArray<ReadbackProcessor::Update> readbackUpdates;
     307         154 :   nsIntRegion readbackRegion;
     308          77 :   if (aReadback && UsedForReadback()) {
     309           0 :     aReadback->GetPaintedLayerUpdates(this, &readbackUpdates);
     310             :   }
     311             : 
     312          77 :   PaintThebes(&readbackUpdates);
     313             : }
     314             : 
     315             : already_AddRefed<PaintedLayer>
     316           0 : ClientLayerManager::CreatePaintedLayer()
     317             : {
     318           0 :   return CreatePaintedLayerWithHint(NONE);
     319             : }
     320             : 
     321             : already_AddRefed<PaintedLayer>
     322          22 : ClientLayerManager::CreatePaintedLayerWithHint(PaintedLayerCreationHint aHint)
     323             : {
     324          22 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
     325             :   // The non-tiling ContentClient requires CrossProcessSemaphore which
     326             :   // isn't implemented for OSX.
     327             : #ifdef XP_MACOSX
     328             :   if (true) {
     329             : #else
     330          22 :   if (gfxPrefs::LayersTilesEnabled()) {
     331             : #endif
     332           0 :     RefPtr<ClientTiledPaintedLayer> layer = new ClientTiledPaintedLayer(this, aHint);
     333           0 :     CREATE_SHADOW(Painted);
     334           0 :     return layer.forget();
     335             :   } else {
     336          44 :     RefPtr<ClientPaintedLayer> layer = new ClientPaintedLayer(this, aHint);
     337          22 :     CREATE_SHADOW(Painted);
     338          22 :     return layer.forget();
     339             :   }
     340             : }
     341             : 
     342             : void
     343           0 : ClientPaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
     344             : {
     345           0 :   PaintedLayer::PrintInfo(aStream, aPrefix);
     346           0 :   if (mContentClient) {
     347           0 :     aStream << "\n";
     348           0 :     nsAutoCString pfx(aPrefix);
     349           0 :     pfx += "  ";
     350           0 :     mContentClient->PrintInfo(aStream, pfx.get());
     351             :   }
     352           0 : }
     353             : 
     354             : } // namespace layers
     355             : } // namespace mozilla

Generated by: LCOV version 1.13