RenderNodeDrawable.cpp revision 2f06e8ad1a1c4d0866bb66854d2759e275898635
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) { 522f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev //negative and positive Z order are drawn out of order, if this render node drawable is in 532f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev //a reordering section 542f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev if ((!mInReorderingSection) || MathUtils::isZero(mRenderNode->properties().getZ())) { 55021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->forceDraw(canvas); 56021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 57021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 58021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 59021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::forceDraw(SkCanvas* canvas) { 60021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNode* renderNode = mRenderNode.get(); 61500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (SkiaPipeline::skpCaptureEnabled()) { 62021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight()); 63021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr); 64021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 65021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 66021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // We only respect the nothingToDraw check when we are composing a layer. This 67021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // ensures that we paint the layer even if it is not currently visible in the 68021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // event that the properties change and it becomes visible. 69021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!renderNode->isRenderable() || (renderNode->nothingToDraw() && mComposeLayer)) { 70021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return; 71021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 72021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 73021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(renderNode->getDisplayList()->isSkiaDL()); 74021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList(); 75021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 76021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkAutoCanvasRestore acr(canvas, true); 77021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 78021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const RenderProperties& properties = this->getNodeProperties(); 79021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (displayList->mIsProjectionReceiver) { 80021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // this node is a projection receiver. We will gather the projected nodes as we draw our 81021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // children, and then draw them on top of this node's content. 82021693b967a2c5556dddd183eb0247df4079e1adStan Iliev std::vector<ProjectedChild> newList; 83021693b967a2c5556dddd183eb0247df4079e1adStan Iliev for (auto& child : displayList->mChildNodes) { 84021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // our direct children are not supposed to project into us (nodes project to, at the 85021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // nearest, their grandparents). So we "delay" the list's activation one level by 86021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // passing it into mNextProjectedChildrenTarget rather than mProjectedChildrenTarget. 87021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mProjectedChildrenTarget = mNextProjectedChildrenTarget; 88021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mNextProjectedChildrenTarget = &newList; 89021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 90021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // draw ourselves and our children. As a side effect, this will add projected nodes to 91021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // newList. 92021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->drawContent(canvas); 93021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool willClip = properties.getOutline().willClip(); 94021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (willClip) { 95021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->save(); 96021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipOutline(properties.getOutline(), canvas, nullptr); 97021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 98021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // draw the collected projected nodes 99021693b967a2c5556dddd183eb0247df4079e1adStan Iliev for (auto& projectedChild : newList) { 100021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->setMatrix(projectedChild.matrix); 101021693b967a2c5556dddd183eb0247df4079e1adStan Iliev projectedChild.node->drawContent(canvas); 102021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 103021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (willClip) { 104021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->restore(); 105021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 106021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 107021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getProjectBackwards() && mProjectedChildrenTarget) { 108021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // We are supposed to project this node, so add it to the list and do not actually draw 109021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // yet. It will be drawn by its projection receiver. 110021693b967a2c5556dddd183eb0247df4079e1adStan Iliev mProjectedChildrenTarget->push_back({ this, canvas->getTotalMatrix() }); 111021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return; 112021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 113021693b967a2c5556dddd183eb0247df4079e1adStan Iliev for (auto& child : displayList->mChildNodes) { 114021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // storing these values in the nodes themselves is a bit ugly; they should "really" be 115021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // function parameters, but we have to go through the preexisting draw() method and 116021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // therefore cannot add additional parameters to it 117021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mProjectedChildrenTarget = mNextProjectedChildrenTarget; 118021693b967a2c5556dddd183eb0247df4079e1adStan Iliev child.mNextProjectedChildrenTarget = mNextProjectedChildrenTarget; 119021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 120021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->drawContent(canvas); 121021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 122021693b967a2c5556dddd183eb0247df4079e1adStan Iliev mProjectedChildrenTarget = nullptr; 123021693b967a2c5556dddd183eb0247df4079e1adStan Iliev mNextProjectedChildrenTarget = nullptr; 124021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 125021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 126021693b967a2c5556dddd183eb0247df4079e1adStan Ilievstatic bool layerNeedsPaint(const LayerProperties& properties, 127021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float alphaMultiplier, SkPaint* paint) { 128021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (alphaMultiplier < 1.0f 129021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.alpha() < 255 130021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.xferMode() != SkBlendMode::kSrcOver 131021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.colorFilter() != nullptr) { 132021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setAlpha(properties.alpha() * alphaMultiplier); 133021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setBlendMode(properties.xferMode()); 134021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setColorFilter(properties.colorFilter()); 135021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return true; 136021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 137021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return false; 138021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 139021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 140021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::drawContent(SkCanvas* canvas) const { 141021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNode* renderNode = mRenderNode.get(); 142021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float alphaMultiplier = 1.0f; 143021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const RenderProperties& properties = renderNode->properties(); 144021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 145021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // If we are drawing the contents of layer, we don't want to apply any of 146021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // the RenderNode's properties during this pass. Those will all be applied 147021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // when the layer is composited. 148021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (mComposeLayer) { 149021693b967a2c5556dddd183eb0247df4079e1adStan Iliev setViewProperties(properties, canvas, &alphaMultiplier); 150021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 151021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 152021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //TODO should we let the bound of the drawable do this for us? 153021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight()); 154021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds); 155021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!quickRejected) { 156021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList(); 157021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const LayerProperties& layerProperties = properties.layerProperties(); 158021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // composing a hardware layer 159021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (renderNode->getLayerSurface() && mComposeLayer) { 160021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer); 161021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint* paint = nullptr; 162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint tmpPaint; 163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (layerNeedsPaint(layerProperties, alphaMultiplier, &tmpPaint)) { 164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint = &tmpPaint; 165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev renderNode->getLayerSurface()->draw(canvas, 0, 0, paint); 167021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // composing a software layer with alpha 168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.effectiveLayerType() == LayerType::Software) { 169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint paint; 170021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool needsLayer = layerNeedsPaint(layerProperties, alphaMultiplier, &paint); 171021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (needsLayer) { 172021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->saveLayer(bounds, &paint); 173021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 174021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawDrawable(displayList->mDrawable.get()); 175021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (needsLayer) { 176021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->restore(); 177021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 178021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 179021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawDrawable(displayList->mDrawable.get()); 180021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 181021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 182021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 183021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 184021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::setViewProperties(const RenderProperties& properties, SkCanvas* canvas, 185021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float* alphaMultiplier) { 186021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getLeft() != 0 || properties.getTop() != 0) { 187021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->translate(properties.getLeft(), properties.getTop()); 188021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 189021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getStaticMatrix()) { 190021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getStaticMatrix()); 191021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.getAnimationMatrix()) { 192021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getAnimationMatrix()); 193021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 194021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.hasTransformMatrix()) { 195021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.isTransformTranslateOnly()) { 196021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->translate(properties.getTranslationX(), properties.getTranslationY()); 197021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 198021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getTransformMatrix()); 199021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 200021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 201021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const bool isLayer = properties.effectiveLayerType() != LayerType::None; 202021693b967a2c5556dddd183eb0247df4079e1adStan Iliev int clipFlags = properties.getClippingFlags(); 203021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getAlpha() < 1) { 204021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (isLayer) { 205021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer 206021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 207021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) { 208021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *alphaMultiplier = properties.getAlpha(); 209021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 210021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // savelayer needed to create an offscreen buffer 211021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect layerBounds(0, 0, properties.getWidth(), properties.getHeight()); 212021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (clipFlags) { 213021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getClippingRectForFlags(clipFlags, &layerBounds); 214021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipFlags = 0; // all clipping done by savelayer 215021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 216021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect bounds = SkRect::MakeLTRB(layerBounds.left, layerBounds.top, 217021693b967a2c5556dddd183eb0247df4079e1adStan Iliev layerBounds.right, layerBounds.bottom); 218021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->saveLayerAlpha(&bounds, (int) (properties.getAlpha() * 255)); 219021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 220021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 221021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (CC_UNLIKELY(ATRACE_ENABLED() && properties.promotedToLayer())) { 222021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // pretend alpha always causes savelayer to warn about 223021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // performance problem affecting old versions 224021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ATRACE_FORMAT("alpha caused saveLayer %dx%d", properties.getWidth(), 225021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getHeight()); 226021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 227021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 228021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 229021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const SkRect* pendingClip = nullptr; 230021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect clipRect; 231021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 232021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (clipFlags) { 233021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect tmpRect; 234021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getClippingRectForFlags(clipFlags, &tmpRect); 235021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipRect = tmpRect.toSkRect(); 236021693b967a2c5556dddd183eb0247df4079e1adStan Iliev pendingClip = &clipRect; 237021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 238021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 239021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getRevealClip().willClip()) { 240021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipPath(*properties.getRevealClip().getPath(), SkRegion::kIntersect_Op, true); 241021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.getOutline().willClip()) { 242021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipOutline(properties.getOutline(), canvas, pendingClip); 243021693b967a2c5556dddd183eb0247df4079e1adStan Iliev pendingClip = nullptr; 244021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 245021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 246021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip) { 247021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(*pendingClip); 248021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 249021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 250021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 251021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace skiapipeline 252021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace uirenderer 253021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace android 254