gfx/layers/basic/BasicThebesLayer.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/basic/BasicThebesLayer.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,229 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "BasicThebesLayer.h"
    1.10 +#include <stdint.h>                     // for uint32_t
    1.11 +#include "GeckoProfiler.h"              // for PROFILER_LABEL
    1.12 +#include "ReadbackLayer.h"              // for ReadbackLayer, ReadbackSink
    1.13 +#include "ReadbackProcessor.h"          // for ReadbackProcessor::Update, etc
    1.14 +#include "RenderTrace.h"                // for RenderTraceInvalidateEnd, etc
    1.15 +#include "BasicLayersImpl.h"            // for AutoMaskData, etc
    1.16 +#include "gfxContext.h"                 // for gfxContext, etc
    1.17 +#include "gfxRect.h"                    // for gfxRect
    1.18 +#include "gfxUtils.h"                   // for gfxUtils
    1.19 +#include "mozilla/gfx/2D.h"             // for DrawTarget
    1.20 +#include "mozilla/gfx/BaseRect.h"       // for BaseRect
    1.21 +#include "mozilla/gfx/Matrix.h"         // for Matrix
    1.22 +#include "mozilla/gfx/Rect.h"           // for Rect, IntRect
    1.23 +#include "mozilla/gfx/Types.h"          // for Float, etc
    1.24 +#include "mozilla/layers/LayersTypes.h"
    1.25 +#include "nsAutoPtr.h"                  // for nsRefPtr
    1.26 +#include "nsCOMPtr.h"                   // for already_AddRefed
    1.27 +#include "nsISupportsImpl.h"            // for gfxContext::Release, etc
    1.28 +#include "nsPoint.h"                    // for nsIntPoint
    1.29 +#include "nsRect.h"                     // for nsIntRect
    1.30 +#include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
    1.31 +#include "AutoMaskData.h"
    1.32 +#include "gfx2DGlue.h"
    1.33 +
    1.34 +using namespace mozilla::gfx;
    1.35 +
    1.36 +namespace mozilla {
    1.37 +namespace layers {
    1.38 +
    1.39 +static nsIntRegion
    1.40 +IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
    1.41 +{
    1.42 +  gfxRect clip = aContext->GetClipExtents();
    1.43 +  clip.RoundOut();
    1.44 +  nsIntRect r(clip.X(), clip.Y(), clip.Width(), clip.Height());
    1.45 +  nsIntRegion result;
    1.46 +  result.And(aRegion, r);
    1.47 +  return result;
    1.48 +}
    1.49 +
    1.50 +void
    1.51 +BasicThebesLayer::PaintThebes(gfxContext* aContext,
    1.52 +                              Layer* aMaskLayer,
    1.53 +                              LayerManager::DrawThebesLayerCallback aCallback,
    1.54 +                              void* aCallbackData,
    1.55 +                              ReadbackProcessor* aReadback)
    1.56 +{
    1.57 +  PROFILER_LABEL("BasicThebesLayer", "PaintThebes");
    1.58 +  NS_ASSERTION(BasicManager()->InDrawing(),
    1.59 +               "Can only draw in drawing phase");
    1.60 +
    1.61 +  nsTArray<ReadbackProcessor::Update> readbackUpdates;
    1.62 +  if (aReadback && UsedForReadback()) {
    1.63 +    aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
    1.64 +  }
    1.65 +
    1.66 +  float opacity = GetEffectiveOpacity();
    1.67 +  CompositionOp effectiveOperator = GetEffectiveOperator(this);
    1.68 +
    1.69 +  if (!BasicManager()->IsRetained()) {
    1.70 +    NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
    1.71 +
    1.72 +    mValidRegion.SetEmpty();
    1.73 +    mContentClient->Clear();
    1.74 +
    1.75 +    nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
    1.76 +
    1.77 +    RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
    1.78 +
    1.79 +    if (!toDraw.IsEmpty() && !IsHidden()) {
    1.80 +      if (!aCallback) {
    1.81 +        BasicManager()->SetTransactionIncomplete();
    1.82 +        return;
    1.83 +      }
    1.84 +
    1.85 +      aContext->Save();
    1.86 +
    1.87 +      bool needsClipToVisibleRegion = GetClipToVisibleRegion();
    1.88 +      bool needsGroup = opacity != 1.0 ||
    1.89 +                        effectiveOperator != CompositionOp::OP_OVER ||
    1.90 +                        aMaskLayer;
    1.91 +      nsRefPtr<gfxContext> groupContext;
    1.92 +      if (needsGroup) {
    1.93 +        groupContext =
    1.94 +          BasicManager()->PushGroupForLayer(aContext, this, toDraw,
    1.95 +                                            &needsClipToVisibleRegion);
    1.96 +        if (effectiveOperator != CompositionOp::OP_OVER) {
    1.97 +          needsClipToVisibleRegion = true;
    1.98 +        }
    1.99 +      } else {
   1.100 +        groupContext = aContext;
   1.101 +      }
   1.102 +      SetAntialiasingFlags(this, groupContext);
   1.103 +      aCallback(this, groupContext, toDraw, DrawRegionClip::CLIP_NONE, nsIntRegion(), aCallbackData);
   1.104 +      if (needsGroup) {
   1.105 +        BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
   1.106 +        if (needsClipToVisibleRegion) {
   1.107 +          gfxUtils::ClipToRegion(aContext, toDraw);
   1.108 +        }
   1.109 +        AutoSetOperator setOptimizedOperator(aContext, ThebesOp(effectiveOperator));
   1.110 +        PaintWithMask(aContext, opacity, aMaskLayer);
   1.111 +      }
   1.112 +
   1.113 +      aContext->Restore();
   1.114 +    }
   1.115 +
   1.116 +    RenderTraceInvalidateEnd(this, "FFFF00");
   1.117 +    return;
   1.118 +  }
   1.119 +
   1.120 +  if (BasicManager()->IsTransactionIncomplete())
   1.121 +    return;
   1.122 +
   1.123 +  gfxRect clipExtents;
   1.124 +  clipExtents = aContext->GetClipExtents();
   1.125 +
   1.126 +  // Pull out the mask surface and transform here, because the mask
   1.127 +  // is internal to basic layers
   1.128 +  AutoMoz2DMaskData mask;
   1.129 +  SourceSurface* maskSurface = nullptr;
   1.130 +  Matrix maskTransform;
   1.131 +  if (GetMaskData(aMaskLayer, Point(), &mask)) {
   1.132 +    maskSurface = mask.GetSurface();
   1.133 +    maskTransform = mask.GetTransform();
   1.134 +  }
   1.135 +
   1.136 +  if (!IsHidden() && !clipExtents.IsEmpty()) {
   1.137 +    mContentClient->DrawTo(this, aContext->GetDrawTarget(), opacity,
   1.138 +                           GetOperator(),
   1.139 +                           maskSurface, &maskTransform);
   1.140 +  }
   1.141 +
   1.142 +  for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
   1.143 +    ReadbackProcessor::Update& update = readbackUpdates[i];
   1.144 +    nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
   1.145 +    nsRefPtr<gfxContext> ctx =
   1.146 +      update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
   1.147 +                                            update.mSequenceCounter);
   1.148 +    if (ctx) {
   1.149 +      NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
   1.150 +      ctx->Translate(gfxPoint(offset.x, offset.y));
   1.151 +      mContentClient->DrawTo(this, ctx->GetDrawTarget(), 1.0,
   1.152 +                             CompositionOpForOp(ctx->CurrentOperator()),
   1.153 +                             maskSurface, &maskTransform);
   1.154 +      update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
   1.155 +    }
   1.156 +  }
   1.157 +}
   1.158 +
   1.159 +void
   1.160 +BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
   1.161 +                           void* aCallbackData)
   1.162 +{
   1.163 +  if (!mContentClient) {
   1.164 +    // This client will have a null Forwarder, which means it will not have
   1.165 +    // a ContentHost on the other side.
   1.166 +    mContentClient = new ContentClientBasic();
   1.167 +  }
   1.168 +
   1.169 +  if (!BasicManager()->IsRetained()) {
   1.170 +    return;
   1.171 +  }
   1.172 +
   1.173 +  uint32_t flags = 0;
   1.174 +#ifndef MOZ_WIDGET_ANDROID
   1.175 +  if (BasicManager()->CompositorMightResample()) {
   1.176 +    flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
   1.177 +  }
   1.178 +  if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) {
   1.179 +    if (MayResample()) {
   1.180 +      flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
   1.181 +    }
   1.182 +  }
   1.183 +#endif
   1.184 +  if (mDrawAtomically) {
   1.185 +    flags |= RotatedContentBuffer::PAINT_NO_ROTATION;
   1.186 +  }
   1.187 +  PaintState state =
   1.188 +    mContentClient->BeginPaintBuffer(this, flags);
   1.189 +  mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
   1.190 +
   1.191 +  if (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state)) {
   1.192 +    // The area that became invalid and is visible needs to be repainted
   1.193 +    // (this could be the whole visible area if our buffer switched
   1.194 +    // from RGB to RGBA, because we might need to repaint with
   1.195 +    // subpixel AA)
   1.196 +    state.mRegionToInvalidate.And(state.mRegionToInvalidate,
   1.197 +                                  GetEffectiveVisibleRegion());
   1.198 +    SetAntialiasingFlags(this, target);
   1.199 +
   1.200 +    RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
   1.201 +
   1.202 +    nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target);
   1.203 +    PaintBuffer(ctx,
   1.204 +                state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate,
   1.205 +                state.mDidSelfCopy,
   1.206 +                state.mClip,
   1.207 +                aCallback, aCallbackData);
   1.208 +    MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
   1.209 +    Mutated();
   1.210 +    ctx = nullptr;
   1.211 +    mContentClient->ReturnDrawTargetToBuffer(target);
   1.212 +
   1.213 +    RenderTraceInvalidateEnd(this, "FFFF00");
   1.214 +  } else {
   1.215 +    // It's possible that state.mRegionToInvalidate is nonempty here,
   1.216 +    // if we are shrinking the valid region to nothing. So use mRegionToDraw
   1.217 +    // instead.
   1.218 +    NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
   1.219 +                     "No context when we have something to draw, resource exhaustion?");
   1.220 +  }
   1.221 +}
   1.222 +
   1.223 +already_AddRefed<ThebesLayer>
   1.224 +BasicLayerManager::CreateThebesLayer()
   1.225 +{
   1.226 +  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   1.227 +  nsRefPtr<ThebesLayer> layer = new BasicThebesLayer(this);
   1.228 +  return layer.forget();
   1.229 +}
   1.230 +
   1.231 +}
   1.232 +}

mercurial