RenderNodeDrawable.cpp revision 6c67f1d04591f44bccb476d715a005ad5bbdf840
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 27db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievvoid RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas, const SkiaDisplayList& displayList, 28db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev int nestLevel) { 29db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev LOG_ALWAYS_FATAL_IF(0 == nestLevel && !displayList.mProjectionReceiver); 30db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev for (auto& child : displayList.mChildNodes) { 31db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev const RenderProperties& childProperties = child.getNodeProperties(); 32db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 33db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //immediate children cannot be projected on their parent 34db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (childProperties.getProjectBackwards() && nestLevel > 0) { 35db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkAutoCanvasRestore acr2(canvas, true); 36db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //Apply recorded matrix, which is a total matrix saved at recording time to avoid 37db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //replaying all DL commands. 38db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->concat(child.getRecordedMatrix()); 39db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev child.drawContent(canvas); 40db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 41db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 42db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //skip walking sub-nodes if current display list contains a receiver with exception of 43db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //level 0, which is a known receiver 44db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (0 == nestLevel || !displayList.containsProjectionReceiver()) { 45db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkAutoCanvasRestore acr(canvas, true); 46db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkMatrix nodeMatrix; 47db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev mat4 hwuiMatrix(child.getRecordedMatrix()); 48db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto childNode = child.getRenderNode(); 49db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev childNode->applyViewPropertyTransforms(hwuiMatrix); 50db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev hwuiMatrix.copyTo(nodeMatrix); 51db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->concat(nodeMatrix); 52db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkiaDisplayList* childDisplayList = static_cast<SkiaDisplayList*>( 53db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev (const_cast<DisplayList*>(childNode->getDisplayList()))); 54db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (childDisplayList) { 55db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawBackwardsProjectedNodes(canvas, *childDisplayList, nestLevel+1); 56db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 57db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 58db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 59db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 60db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 61021693b967a2c5556dddd183eb0247df4079e1adStan Ilievstatic void clipOutline(const Outline& outline, SkCanvas* canvas, const SkRect* pendingClip) { 62021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect possibleRect; 63021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float radius; 64021693b967a2c5556dddd183eb0247df4079e1adStan Iliev LOG_ALWAYS_FATAL_IF(!outline.getAsRoundRect(&possibleRect, &radius), 65021693b967a2c5556dddd183eb0247df4079e1adStan Iliev "clipping outlines should be at most roundedRects"); 66021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect rect = possibleRect.toSkRect(); 67021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (radius != 0.0f) { 68021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip && !pendingClip->contains(rect)) { 69021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(*pendingClip); 70021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 716c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas->clipRRect(SkRRect::MakeRectXY(rect, radius, radius), SkClipOp::kIntersect, true); 72021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 73021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip) { 74021693b967a2c5556dddd183eb0247df4079e1adStan Iliev (void)rect.intersect(*pendingClip); 75021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 76021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(rect); 77021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 78021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 79021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 80021693b967a2c5556dddd183eb0247df4079e1adStan Ilievconst RenderProperties& RenderNodeDrawable::getNodeProperties() const { 81021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return mRenderNode->properties(); 82021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 83021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 84021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::onDraw(SkCanvas* canvas) { 852f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev //negative and positive Z order are drawn out of order, if this render node drawable is in 862f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev //a reordering section 872f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev if ((!mInReorderingSection) || MathUtils::isZero(mRenderNode->properties().getZ())) { 88021693b967a2c5556dddd183eb0247df4079e1adStan Iliev this->forceDraw(canvas); 89021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 90021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 91021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 92021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::forceDraw(SkCanvas* canvas) { 93021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNode* renderNode = mRenderNode.get(); 94500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (SkiaPipeline::skpCaptureEnabled()) { 95021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight()); 96021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr); 97021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 98021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 99021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // We only respect the nothingToDraw check when we are composing a layer. This 100021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // ensures that we paint the layer even if it is not currently visible in the 101021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // event that the properties change and it becomes visible. 102021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!renderNode->isRenderable() || (renderNode->nothingToDraw() && mComposeLayer)) { 103021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return; 104021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 105021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 106021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(renderNode->getDisplayList()->isSkiaDL()); 107021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList(); 108021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 109021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkAutoCanvasRestore acr(canvas, true); 110021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const RenderProperties& properties = this->getNodeProperties(); 111db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //pass this outline to the children that may clip backward projected nodes 112db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev displayList->mProjectedOutline = displayList->containsProjectionReceiver() 113db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ? &properties.getOutline() : nullptr; 114db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (!properties.getProjectBackwards()) { 115db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawContent(canvas); 116db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (mProjectedDisplayList) { 117db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev acr.restore(); //draw projected children using parent matrix 118db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev LOG_ALWAYS_FATAL_IF(!mProjectedDisplayList->mProjectedOutline); 119db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev const bool shouldClip = mProjectedDisplayList->mProjectedOutline->getPath(); 120db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkAutoCanvasRestore acr2(canvas, shouldClip); 121db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->setMatrix(mProjectedDisplayList->mProjectedReceiverParentMatrix); 122db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (shouldClip) { 123db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev clipOutline(*mProjectedDisplayList->mProjectedOutline, canvas, nullptr); 124db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 125db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawBackwardsProjectedNodes(canvas, *mProjectedDisplayList); 126021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 127021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 128db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev displayList->mProjectedOutline = nullptr; 129021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 130021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 131021693b967a2c5556dddd183eb0247df4079e1adStan Ilievstatic bool layerNeedsPaint(const LayerProperties& properties, 132021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float alphaMultiplier, SkPaint* paint) { 133021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (alphaMultiplier < 1.0f 134021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.alpha() < 255 135021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.xferMode() != SkBlendMode::kSrcOver 136021693b967a2c5556dddd183eb0247df4079e1adStan Iliev || properties.colorFilter() != nullptr) { 137021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setAlpha(properties.alpha() * alphaMultiplier); 138021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint->setBlendMode(properties.xferMode()); 139f87da67df90968adcddb2404ff20a41fe49a0315Derek Sollenberger paint->setColorFilter(sk_ref_sp(properties.colorFilter())); 140021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return true; 141021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 142021693b967a2c5556dddd183eb0247df4079e1adStan Iliev return false; 143021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 144021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 145021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::drawContent(SkCanvas* canvas) const { 146021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNode* renderNode = mRenderNode.get(); 147021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float alphaMultiplier = 1.0f; 148021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const RenderProperties& properties = renderNode->properties(); 149021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 150021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // If we are drawing the contents of layer, we don't want to apply any of 151021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // the RenderNode's properties during this pass. Those will all be applied 152021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // when the layer is composited. 153021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (mComposeLayer) { 154021693b967a2c5556dddd183eb0247df4079e1adStan Iliev setViewProperties(properties, canvas, &alphaMultiplier); 155021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 156db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)mRenderNode->getDisplayList(); 157db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (displayList->containsProjectionReceiver()) { 158db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev displayList->mProjectedReceiverParentMatrix = canvas->getTotalMatrix(); 159db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 160021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 161021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //TODO should we let the bound of the drawable do this for us? 162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight()); 163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds); 164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (!quickRejected) { 165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList(); 166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const LayerProperties& layerProperties = properties.layerProperties(); 167021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // composing a hardware layer 168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (renderNode->getLayerSurface() && mComposeLayer) { 169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer); 170021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint* paint = nullptr; 171021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint tmpPaint; 172021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (layerNeedsPaint(layerProperties, alphaMultiplier, &tmpPaint)) { 173021693b967a2c5556dddd183eb0247df4079e1adStan Iliev paint = &tmpPaint; 174021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 175021693b967a2c5556dddd183eb0247df4079e1adStan Iliev renderNode->getLayerSurface()->draw(canvas, 0, 0, paint); 17679756be175dea78ee9d51bb22abba7621bd9b5ccMatt Sarett 177f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) { 17879756be175dea78ee9d51bb22abba7621bd9b5ccMatt Sarett renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true; 179f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett if (CC_UNLIKELY(Properties::debugLayersUpdates)) { 180f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett SkPaint layerPaint; 181f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett layerPaint.setColor(0x7f00ff00); 182f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett canvas->drawRect(bounds, layerPaint); 183f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett } else if (CC_UNLIKELY(Properties::debugOverdraw)) { 184f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett // Render transparent rect to increment overdraw for repaint area. 185f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett // This can be "else if" because flashing green on layer updates 186f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett // will also increment the overdraw if it happens to be turned on. 187f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett SkPaint transparentPaint; 188f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett transparentPaint.setColor(SK_ColorTRANSPARENT); 189f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett canvas->drawRect(bounds, transparentPaint); 190f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett } 19179756be175dea78ee9d51bb22abba7621bd9b5ccMatt Sarett } 192f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett 193021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // composing a software layer with alpha 194021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.effectiveLayerType() == LayerType::Software) { 195021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkPaint paint; 196021693b967a2c5556dddd183eb0247df4079e1adStan Iliev bool needsLayer = layerNeedsPaint(layerProperties, alphaMultiplier, &paint); 197021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (needsLayer) { 198021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->saveLayer(bounds, &paint); 199021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 200021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawDrawable(displayList->mDrawable.get()); 201021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (needsLayer) { 202021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->restore(); 203021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 204021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 205021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->drawDrawable(displayList->mDrawable.get()); 206021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 207021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 208021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 209021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 210021693b967a2c5556dddd183eb0247df4079e1adStan Ilievvoid RenderNodeDrawable::setViewProperties(const RenderProperties& properties, SkCanvas* canvas, 211021693b967a2c5556dddd183eb0247df4079e1adStan Iliev float* alphaMultiplier) { 212021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getLeft() != 0 || properties.getTop() != 0) { 213021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->translate(properties.getLeft(), properties.getTop()); 214021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 215021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getStaticMatrix()) { 216021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getStaticMatrix()); 217021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.getAnimationMatrix()) { 218021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getAnimationMatrix()); 219021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 220021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.hasTransformMatrix()) { 221021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.isTransformTranslateOnly()) { 222021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->translate(properties.getTranslationX(), properties.getTranslationY()); 223021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 224021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->concat(*properties.getTransformMatrix()); 225021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 226021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 227021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const bool isLayer = properties.effectiveLayerType() != LayerType::None; 228021693b967a2c5556dddd183eb0247df4079e1adStan Iliev int clipFlags = properties.getClippingFlags(); 229021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getAlpha() < 1) { 230021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (isLayer) { 231021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer 232021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 233021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) { 234021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *alphaMultiplier = properties.getAlpha(); 235021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else { 236021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // savelayer needed to create an offscreen buffer 237021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect layerBounds(0, 0, properties.getWidth(), properties.getHeight()); 238021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (clipFlags) { 239021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getClippingRectForFlags(clipFlags, &layerBounds); 240021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipFlags = 0; // all clipping done by savelayer 241021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 242021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect bounds = SkRect::MakeLTRB(layerBounds.left, layerBounds.top, 243021693b967a2c5556dddd183eb0247df4079e1adStan Iliev layerBounds.right, layerBounds.bottom); 244021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->saveLayerAlpha(&bounds, (int) (properties.getAlpha() * 255)); 245021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 246021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 247021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (CC_UNLIKELY(ATRACE_ENABLED() && properties.promotedToLayer())) { 248021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // pretend alpha always causes savelayer to warn about 249021693b967a2c5556dddd183eb0247df4079e1adStan Iliev // performance problem affecting old versions 250021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ATRACE_FORMAT("alpha caused saveLayer %dx%d", properties.getWidth(), 251021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getHeight()); 252021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 253021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 254021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 255021693b967a2c5556dddd183eb0247df4079e1adStan Iliev const SkRect* pendingClip = nullptr; 256021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkRect clipRect; 257021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 258021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (clipFlags) { 259021693b967a2c5556dddd183eb0247df4079e1adStan Iliev Rect tmpRect; 260021693b967a2c5556dddd183eb0247df4079e1adStan Iliev properties.getClippingRectForFlags(clipFlags, &tmpRect); 261021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipRect = tmpRect.toSkRect(); 262021693b967a2c5556dddd183eb0247df4079e1adStan Iliev pendingClip = &clipRect; 263021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 264021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 265021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (properties.getRevealClip().willClip()) { 2666c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas->clipPath(*properties.getRevealClip().getPath(), SkClipOp::kIntersect, true); 267021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } else if (properties.getOutline().willClip()) { 268021693b967a2c5556dddd183eb0247df4079e1adStan Iliev clipOutline(properties.getOutline(), canvas, pendingClip); 269021693b967a2c5556dddd183eb0247df4079e1adStan Iliev pendingClip = nullptr; 270021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 271021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 272021693b967a2c5556dddd183eb0247df4079e1adStan Iliev if (pendingClip) { 273021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas->clipRect(*pendingClip); 274021693b967a2c5556dddd183eb0247df4079e1adStan Iliev } 275021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 276021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 277021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace skiapipeline 278021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace uirenderer 279021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}; // namespace android 280