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 +}