1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/basic/BasicContainerLayer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,139 @@ 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 "BasicContainerLayer.h" 1.10 +#include <sys/types.h> // for int32_t 1.11 +#include "BasicLayersImpl.h" // for ToData 1.12 +#include "basic/BasicImplData.h" // for BasicImplData 1.13 +#include "basic/BasicLayers.h" // for BasicLayerManager 1.14 +#include "mozilla/gfx/BaseRect.h" // for BaseRect 1.15 +#include "mozilla/mozalloc.h" // for operator new 1.16 +#include "nsAutoPtr.h" // for nsRefPtr 1.17 +#include "nsCOMPtr.h" // for already_AddRefed 1.18 +#include "nsISupportsImpl.h" // for Layer::AddRef, etc 1.19 +#include "nsPoint.h" // for nsIntPoint 1.20 +#include "nsRect.h" // for nsIntRect 1.21 +#include "nsRegion.h" // for nsIntRegion 1.22 + 1.23 +using namespace mozilla::gfx; 1.24 + 1.25 +namespace mozilla { 1.26 +namespace layers { 1.27 + 1.28 +BasicContainerLayer::~BasicContainerLayer() 1.29 +{ 1.30 + while (mFirstChild) { 1.31 + ContainerLayer::RemoveChild(mFirstChild); 1.32 + } 1.33 + 1.34 + MOZ_COUNT_DTOR(BasicContainerLayer); 1.35 +} 1.36 + 1.37 +void 1.38 +BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface) 1.39 +{ 1.40 + // We push groups for container layers if we need to, which always 1.41 + // are aligned in device space, so it doesn't really matter how we snap 1.42 + // containers. 1.43 + Matrix residual; 1.44 + Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface; 1.45 + idealTransform.ProjectTo2D(); 1.46 + 1.47 + if (!idealTransform.CanDraw2D()) { 1.48 + mEffectiveTransform = idealTransform; 1.49 + ComputeEffectiveTransformsForChildren(Matrix4x4()); 1.50 + ComputeEffectiveTransformForMaskLayer(Matrix4x4()); 1.51 + mUseIntermediateSurface = true; 1.52 + return; 1.53 + } 1.54 + 1.55 + mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual); 1.56 + // We always pass the ideal matrix down to our children, so there is no 1.57 + // need to apply any compensation using the residual from SnapTransformTranslation. 1.58 + ComputeEffectiveTransformsForChildren(idealTransform); 1.59 + 1.60 + ComputeEffectiveTransformForMaskLayer(aTransformToSurface); 1.61 + 1.62 + Layer* child = GetFirstChild(); 1.63 + bool hasSingleBlendingChild = false; 1.64 + if (!HasMultipleChildren() && child) { 1.65 + hasSingleBlendingChild = child->GetMixBlendMode() != CompositionOp::OP_OVER; 1.66 + } 1.67 + 1.68 + /* If we have a single childand it is not blending,, it can just inherit our opacity, 1.69 + * otherwise we need a PushGroup and we need to mark ourselves as using 1.70 + * an intermediate surface so our children don't inherit our opacity 1.71 + * via GetEffectiveOpacity. 1.72 + * Having a mask layer always forces our own push group 1.73 + * Having a blend mode also always forces our own push group 1.74 + */ 1.75 + mUseIntermediateSurface = 1.76 + GetMaskLayer() || 1.77 + GetForceIsolatedGroup() || 1.78 + (GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) || 1.79 + (GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild)); 1.80 +} 1.81 + 1.82 +bool 1.83 +BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect) 1.84 +{ 1.85 + Matrix transform; 1.86 + if (!GetEffectiveTransform().CanDraw2D(&transform) || 1.87 + ThebesMatrix(transform).HasNonIntegerTranslation()) 1.88 + return false; 1.89 + 1.90 + nsIntPoint offset(int32_t(transform._31), int32_t(transform._32)); 1.91 + nsIntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().GetBounds() + offset); 1.92 + nsIntRegion covered; 1.93 + 1.94 + for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) { 1.95 + if (ToData(l)->IsHidden()) 1.96 + continue; 1.97 + 1.98 + Matrix childTransform; 1.99 + if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) || 1.100 + ThebesMatrix(childTransform).HasNonIntegerTranslation() || 1.101 + l->GetEffectiveOpacity() != 1.0) 1.102 + return false; 1.103 + nsIntRegion childRegion = l->GetEffectiveVisibleRegion(); 1.104 + childRegion.MoveBy(int32_t(childTransform._31), int32_t(childTransform._32)); 1.105 + childRegion.And(childRegion, rect); 1.106 + if (l->GetClipRect()) { 1.107 + childRegion.And(childRegion, *l->GetClipRect() + offset); 1.108 + } 1.109 + nsIntRegion intersection; 1.110 + intersection.And(covered, childRegion); 1.111 + if (!intersection.IsEmpty()) 1.112 + return false; 1.113 + covered.Or(covered, childRegion); 1.114 + } 1.115 + 1.116 + return covered.Contains(rect); 1.117 +} 1.118 + 1.119 +void 1.120 +BasicContainerLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback, 1.121 + void* aCallbackData) 1.122 +{ 1.123 + for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) { 1.124 + BasicImplData* data = ToData(l); 1.125 + data->Validate(aCallback, aCallbackData); 1.126 + if (l->GetMaskLayer()) { 1.127 + data = ToData(l->GetMaskLayer()); 1.128 + data->Validate(aCallback, aCallbackData); 1.129 + } 1.130 + } 1.131 +} 1.132 + 1.133 +already_AddRefed<ContainerLayer> 1.134 +BasicLayerManager::CreateContainerLayer() 1.135 +{ 1.136 + NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); 1.137 + nsRefPtr<ContainerLayer> layer = new BasicContainerLayer(this); 1.138 + return layer.forget(); 1.139 +} 1.140 + 1.141 +} 1.142 +}