RenderNodeDrawable.cpp revision 500a0c30d4dcd012218c3e44a62926a1c34a259f
1021693b967a2c5556dddd183eb0247df4079e1adStan Iliev/* 2021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Copyright (C) 2016 The Android Open Source Project 3021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 4021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Licensed under the Apache License, Version 2.0 (the "License"); 5021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * you may not use this file except in compliance with the License. 6021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * You may obtain a copy of the License at 7021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 8021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * http://www.apache.org/licenses/LICENSE-2.0 9021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 10021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Unless required by applicable law or agreed to in writing, software 11021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * distributed under the License is distributed on an "AS IS" BASIS, 12021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * See the License for the specific language governing permissions and 14021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * limitations under the License. 15021693b967a2c5556dddd183eb0247df4079e1adStan Iliev */ 16021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 17021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "RenderNodeDrawable.h" 18021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "RenderNode.h" 19021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "SkiaDisplayList.h" 20500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "SkiaPipeline.h" 21021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "utils/TraceUtils.h" 22021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 23021693b967a2c5556dddd183eb0247df4079e1adStan Ilievnamespace android { 24021693b967a2c5556dddd183eb0247df4079e1adStan Ilievnamespace uirenderer { 25021693b967a2c5556dddd183eb0247df4079e1adStan Ilievnamespace skiapipeline { 26021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 27021693b967a2c5556dddd183eb0247df4079e1adStan Ilievstatic void clipOutline(const Outline& outline, SkCanvas* canvas, const SkRect* pendingClip) { 28021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(outline.willClip()); 29021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect possibleRect; 30021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float radius; 31021693b967a2c5556dddd183eb0247df4079e1adStan Iliev LOG_ALWAYS_FATAL_IF(!outline.getAsRoundRect(&possibleRect, &radius), 32021693b967a2c5556dddd183eb0247df4079e1adStan Iliev "clipping outlines should be at most roundedRects"); 33021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect rect = possibleRect.toSkRect(); 34021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (radius != 0.0f) { 35021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip && !pendingClip->contains(rect)) { 36021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(*pendingClip); 37021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 38021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRRect(SkRRect::MakeRectXY(rect, radius, radius), SkRegion::kIntersect_Op, true); 39021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 40021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip) { 41021693b967a2c5556dddd183eb0247df4079e1adStan Iliev (void)rect.intersect(*pendingClip); 42021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 43021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(rect); 44021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 45021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 46021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 47021693b967a2c5556dddd183eb0247df4079e1adStan Ilievconst RenderProperties& RenderNodeDrawable::getNodeProperties() const { 48021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return mRenderNode->properties(); 49021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 50021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 51021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::onDraw(SkCanvas* canvas) { 52021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //negative and positive Z order are drawn out of order 53021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (MathUtils::isZero(mRenderNode->properties().getZ())) { 54021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->forceDraw(canvas); 55021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 56021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 57021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 58021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::forceDraw(SkCanvas* canvas) { 59021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNode* renderNode = mRenderNode.get(); 60500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (SkiaPipeline::skpCaptureEnabled()) { 61021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight()); 62021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr); 63021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 64021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 65021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // We only respect the nothingToDraw check when we are composing a layer. This 66021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // ensures that we paint the layer even if it is not currently visible in the 67021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // event that the properties change and it becomes visible. 68021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!renderNode->isRenderable() || (renderNode->nothingToDraw() && mComposeLayer)) { 69021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return; 70021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 71021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 72021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(renderNode->getDisplayList()->isSkiaDL()); 73021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList(); 74021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 75021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkAutoCanvasRestore acr(canvas, true); 76021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 77021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const RenderProperties& properties = this->getNodeProperties(); 78021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (displayList->mIsProjectionReceiver) { 79021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // this node is a projection receiver. We will gather the projected nodes as we draw our 80021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // children, and then draw them on top of this node's content. 81021693b967a2c5556dddd183eb0247df4079e1adStan Iliev std::vector<ProjectedChild> newList; 82021693b967a2c5556dddd183eb0247df4079e1adStan Iliev for (auto& child : displayList->mChildNodes) { 83021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // our direct children are not supposed to project into us (nodes project to, at the 84021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // nearest, their grandparents). So we "delay" the list's activation one level by 85021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // passing it into mNextProjectedChildrenTarget rather than mProjectedChildrenTarget. 86021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mProjectedChildrenTarget = mNextProjectedChildrenTarget; 87021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mNextProjectedChildrenTarget = &newList; 88021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 89021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // draw ourselves and our children. As a side effect, this will add projected nodes to 90021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // newList. 91021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->drawContent(canvas); 92021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool willClip = properties.getOutline().willClip(); 93021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (willClip) { 94021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->save(); 95021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipOutline(properties.getOutline(), canvas, nullptr); 96021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 97021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // draw the collected projected nodes 98021693b967a2c5556dddd183eb0247df4079e1adStan Iliev for (auto& projectedChild : newList) { 99021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->setMatrix(projectedChild.matrix); 100021693b967a2c5556dddd183eb0247df4079e1adStan Iliev projectedChild.node->drawContent(canvas); 101021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 102021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (willClip) { 103021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->restore(); 104021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 105021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 106021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getProjectBackwards() && mProjectedChildrenTarget) { 107021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // We are supposed to project this node, so add it to the list and do not actually draw 108021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // yet. It will be drawn by its projection receiver. 109021693b967a2c5556dddd183eb0247df4079e1adStan Iliev mProjectedChildrenTarget->push_back({ this, canvas->getTotalMatrix() }); 110021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return; 111021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 112021693b967a2c5556dddd183eb0247df4079e1adStan Iliev for (auto& child : displayList->mChildNodes) { 113021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // storing these values in the nodes themselves is a bit ugly; they should "really" be 114021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // function parameters, but we have to go through the preexisting draw() method and 115021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // therefore cannot add additional parameters to it 116021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mProjectedChildrenTarget = mNextProjectedChildrenTarget; 117021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mNextProjectedChildrenTarget = mNextProjectedChildrenTarget; 118021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 119021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->drawContent(canvas); 120021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 121021693b967a2c5556dddd183eb0247df4079e1adStan Iliev mProjectedChildrenTarget = nullptr; 122021693b967a2c5556dddd183eb0247df4079e1adStan Iliev mNextProjectedChildrenTarget = nullptr; 123021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 124021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 125021693b967a2c5556dddd183eb0247df4079e1adStan Ilievstatic bool layerNeedsPaint(const LayerProperties& properties, 126021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float alphaMultiplier, SkPaint* paint) { 127021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (alphaMultiplier < 1.0f 128021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.alpha() < 255 129021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.xferMode() != SkBlendMode::kSrcOver 130021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.colorFilter() != nullptr) { 131021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setAlpha(properties.alpha() * alphaMultiplier); 132021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setBlendMode(properties.xferMode()); 133021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setColorFilter(properties.colorFilter()); 134021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return true; 135021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 136021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return false; 137021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 138021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 139021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::drawContent(SkCanvas* canvas) const { 140021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNode* renderNode = mRenderNode.get(); 141021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float alphaMultiplier = 1.0f; 142021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const RenderProperties& properties = renderNode->properties(); 143021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 144021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // If we are drawing the contents of layer, we don't want to apply any of 145021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // the RenderNode's properties during this pass. Those will all be applied 146021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // when the layer is composited. 147021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (mComposeLayer) { 148021693b967a2c5556dddd183eb0247df4079e1adStan Iliev setViewProperties(properties, canvas, &alphaMultiplier); 149021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 150021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 151021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //TODO should we let the bound of the drawable do this for us? 152021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight()); 153021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds); 154021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!quickRejected) { 155021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList(); 156021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const LayerProperties& layerProperties = properties.layerProperties(); 157021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // composing a hardware layer 158021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (renderNode->getLayerSurface() && mComposeLayer) { 159021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer); 160021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint* paint = nullptr; 161021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint tmpPaint; 162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (layerNeedsPaint(layerProperties, alphaMultiplier, &tmpPaint)) { 163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint = &tmpPaint; 164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev renderNode->getLayerSurface()->draw(canvas, 0, 0, paint); 166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // composing a software layer with alpha 167021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.effectiveLayerType() == LayerType::Software) { 168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint paint; 169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool needsLayer = layerNeedsPaint(layerProperties, alphaMultiplier, &paint); 170021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (needsLayer) { 171021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->saveLayer(bounds, &paint); 172021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 173021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawDrawable(displayList->mDrawable.get()); 174021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (needsLayer) { 175021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->restore(); 176021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 177021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 178021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawDrawable(displayList->mDrawable.get()); 179021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 180021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 181021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 182021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 183021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::setViewProperties(const RenderProperties& properties, SkCanvas* canvas, 184021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float* alphaMultiplier) { 185021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getLeft() != 0 || properties.getTop() != 0) { 186021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->translate(properties.getLeft(), properties.getTop()); 187021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 188021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getStaticMatrix()) { 189021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getStaticMatrix()); 190021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.getAnimationMatrix()) { 191021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getAnimationMatrix()); 192021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 193021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.hasTransformMatrix()) { 194021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.isTransformTranslateOnly()) { 195021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->translate(properties.getTranslationX(), properties.getTranslationY()); 196021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 197021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getTransformMatrix()); 198021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 199021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 200021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const bool isLayer = properties.effectiveLayerType() != LayerType::None; 201021693b967a2c5556dddd183eb0247df4079e1adStan Iliev int clipFlags = properties.getClippingFlags(); 202021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getAlpha() < 1) { 203021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (isLayer) { 204021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer 205021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 206021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) { 207021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *alphaMultiplier = properties.getAlpha(); 208021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 209021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // savelayer needed to create an offscreen buffer 210021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect layerBounds(0, 0, properties.getWidth(), properties.getHeight()); 211021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (clipFlags) { 212021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getClippingRectForFlags(clipFlags, &layerBounds); 213021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipFlags = 0; // all clipping done by savelayer 214021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 215021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect bounds = SkRect::MakeLTRB(layerBounds.left, layerBounds.top, 216021693b967a2c5556dddd183eb0247df4079e1adStan Iliev layerBounds.right, layerBounds.bottom); 217021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->saveLayerAlpha(&bounds, (int) (properties.getAlpha() * 255)); 218021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 219021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 220021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (CC_UNLIKELY(ATRACE_ENABLED() && properties.promotedToLayer())) { 221021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // pretend alpha always causes savelayer to warn about 222021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // performance problem affecting old versions 223021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ATRACE_FORMAT("alpha caused saveLayer %dx%d", properties.getWidth(), 224021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getHeight()); 225021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 226021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 227021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 228021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const SkRect* pendingClip = nullptr; 229021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect clipRect; 230021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 231021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (clipFlags) { 232021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect tmpRect; 233021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getClippingRectForFlags(clipFlags, &tmpRect); 234021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipRect = tmpRect.toSkRect(); 235021693b967a2c5556dddd183eb0247df4079e1adStan Iliev pendingClip = &clipRect; 236021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 237021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 238021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getRevealClip().willClip()) { 239021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipPath(*properties.getRevealClip().getPath(), SkRegion::kIntersect_Op, true); 240021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.getOutline().willClip()) { 241021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipOutline(properties.getOutline(), canvas, pendingClip); 242021693b967a2c5556dddd183eb0247df4079e1adStan Iliev pendingClip = nullptr; 243021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 244021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 245021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip) { 246021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(*pendingClip); 247021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 248021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 249021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 250021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace skiapipeline 251021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace uirenderer 252021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace android 253