diff options
author | 2021-04-19 19:45:13 -0700 | |
---|---|---|
committer | 2021-05-03 18:08:47 -0700 | |
commit | 197743ff9c6ffb7bc96004c38b518fd3941948b0 (patch) | |
tree | 833d7f67ff16d4bf478710e0c711fe4ffce06844 /libs | |
parent | 9443a3e84d73d3423ede16e158b641fb320910dd (diff) |
Update hole punch logic in HWUI
--Updated HWUI holepunch logic for SurfaceView to
also apply the stretch to the hole punch
--Updated RenderNode callbacks to also include
an offset from the ancestor RenderNode that also
has a stretch configured on it
--Added new test activity to verify hole punch
logic
Bug: 179047472
Test: manual
Change-Id: Ibbaf8248a31839ba9dc352ecb9fef54e1276918e
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
-rw-r--r-- | libs/hwui/DamageAccumulator.cpp | 50 | ||||
-rw-r--r-- | libs/hwui/DamageAccumulator.h | 26 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 4 | ||||
-rw-r--r-- | libs/hwui/effects/StretchEffect.cpp | 17 | ||||
-rw-r--r-- | libs/hwui/effects/StretchEffect.h | 33 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_RenderNode.cpp | 34 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/RenderNodeDrawable.cpp | 33 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/StretchMask.cpp | 64 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/StretchMask.h | 62 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/TransformCanvas.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/TransformCanvas.h | 5 |
13 files changed, 281 insertions, 61 deletions
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index f2c48bb8d2bc..02123090e1c4 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -467,6 +467,7 @@ cc_defaults { "pipeline/skia/HolePunch.cpp", "pipeline/skia/SkiaDisplayList.cpp", "pipeline/skia/SkiaRecordingCanvas.cpp", + "pipeline/skia/StretchMask.cpp", "pipeline/skia/RenderNodeDrawable.cpp", "pipeline/skia/ReorderBarrierDrawables.cpp", "pipeline/skia/TransformCanvas.cpp", diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp index 0bf948006ea0..94fe243378b1 100644 --- a/libs/hwui/DamageAccumulator.cpp +++ b/libs/hwui/DamageAccumulator.cpp @@ -197,6 +197,27 @@ static void applyTransforms(DirtyStack* frame, DirtyStack* end) { } } +static void computeTransformImpl(const DirtyStack* frame, const DirtyStack* end, + Matrix4* outMatrix) { + while (frame != end) { + switch (frame->type) { + case TransformRenderNode: + frame->renderNode->applyViewPropertyTransforms(*outMatrix); + break; + case TransformMatrix4: + outMatrix->multiply(*frame->matrix4); + break; + case TransformNone: + // nothing to be done + break; + default: + LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d", + frame->type); + } + frame = frame->prev; + } +} + void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) { if (frame->pendingDirty.isEmpty()) { return; @@ -249,19 +270,38 @@ void DamageAccumulator::finish(SkRect* totalDirty) { mHead->pendingDirty.setEmpty(); } -const StretchEffect* DamageAccumulator::findNearestStretchEffect() const { +DamageAccumulator::StretchResult DamageAccumulator::findNearestStretchEffect() const { DirtyStack* frame = mHead; while (frame->prev != frame) { - frame = frame->prev; if (frame->type == TransformRenderNode) { + const auto& renderNode = frame->renderNode; + const auto& frameRenderNodeProperties = renderNode->properties(); const auto& effect = - frame->renderNode->properties().layerProperties().getStretchEffect(); + frameRenderNodeProperties.layerProperties().getStretchEffect(); + const float width = (float) renderNode->getWidth(); + const float height = (float) renderNode->getHeight(); if (!effect.isEmpty()) { - return &effect; + Matrix4 stretchMatrix; + computeTransformImpl(mHead, frame, &stretchMatrix); + Rect stretchRect = Rect(0.f, 0.f, width, height); + stretchMatrix.mapRect(stretchRect); + + return StretchResult{ + .stretchEffect = &effect, + .childRelativeBounds = SkRect::MakeLTRB( + stretchRect.left, + stretchRect.top, + stretchRect.right, + stretchRect.bottom + ), + .width = width, + .height = height + }; } } + frame = frame->prev; } - return nullptr; + return StretchResult{}; } } /* namespace uirenderer */ diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h index 89ee0e34055b..90a35174d929 100644 --- a/libs/hwui/DamageAccumulator.h +++ b/libs/hwui/DamageAccumulator.h @@ -21,6 +21,7 @@ #include <SkMatrix.h> #include <SkRect.h> +#include <effects/StretchEffect.h> #include "utils/Macros.h" @@ -35,7 +36,6 @@ namespace uirenderer { struct DirtyStack; class RenderNode; class Matrix4; -class StretchEffect; class DamageAccumulator { PREVENT_COPY_AND_ASSIGN(DamageAccumulator); @@ -63,7 +63,29 @@ public: void finish(SkRect* totalDirty); - const StretchEffect* findNearestStretchEffect() const; + struct StretchResult { + /** + * Stretch parameters configured on the stretch container + */ + const StretchEffect* stretchEffect; + + /** + * Bounds of the child relative to the stretch container + */ + const SkRect childRelativeBounds; + + /** + * Width of the stretch container + */ + const float width; + + /** + * Height of the stretch container + */ + const float height; + }; + + [[nodiscard]] StretchResult findNearestStretchEffect() const; private: void pushCommon(); diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index e9eae3d14760..fce2e1fa9970 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -194,6 +194,9 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { SkRect dirty; info.damageAccumulator->peekAtDirty(&dirty); info.layerUpdateQueue->enqueueLayerWithDamage(this, dirty); + if (!dirty.isEmpty()) { + mStretchMask.markDirty(); + } // There might be prefetched layers that need to be accounted for. // That might be us, so tell CanvasContext that this layer is in the @@ -302,6 +305,12 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) { damageSelf(info); info.damageAccumulator->popTransform(); syncProperties(); + + const StretchEffect& stagingStretch = + mProperties.layerProperties().getStretchEffect(); + if (stagingStretch.isEmpty()) { + mStretchMask.clear(); + } // We could try to be clever and only re-damage if the matrix changed. // However, we don't need to worry about that. The cost of over-damaging // here is only going to be a single additional map rect of this node diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 988141fe191d..6a0b1aafd7c7 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -40,6 +40,7 @@ #include "pipeline/skia/SkiaLayer.h" #include <vector> +#include <pipeline/skia/StretchMask.h> class SkBitmap; class SkPaint; @@ -127,6 +128,8 @@ public: } } + StretchMask& getStretchMask() { return mStretchMask; } + VirtualLightRefBase* getUserContext() const { return mUserContext.get(); } void setUserContext(VirtualLightRefBase* context) { mUserContext = context; } @@ -286,6 +289,7 @@ private: UsageHint mUsageHint = UsageHint::Unknown; bool mHasHolePunches; + StretchMask mStretchMask; // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER public: diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp index 6eb6e1ee4a5c..1519d69d7053 100644 --- a/libs/hwui/effects/StretchEffect.cpp +++ b/libs/hwui/effects/StretchEffect.cpp @@ -189,17 +189,12 @@ static const float ZERO = 0.f; static const float CONTENT_DISTANCE_STRETCHED = 1.f; static const float INTERPOLATION_STRENGTH_VALUE = 0.7f; -sk_sp<SkShader> StretchEffect::getShader(const sk_sp<SkImage>& snapshotImage) const { +sk_sp<SkShader> StretchEffect::getShader(float width, float height, + const sk_sp<SkImage>& snapshotImage) const { if (isEmpty()) { return nullptr; } - if (mStretchShader != nullptr) { - return mStretchShader; - } - - float viewportWidth = stretchArea.width(); - float viewportHeight = stretchArea.height(); float normOverScrollDistX = mStretchDirection.x(); float normOverScrollDistY = mStretchDirection.y(); float distanceStretchedX = CONTENT_DISTANCE_STRETCHED / (1 + abs(normOverScrollDistX)); @@ -228,12 +223,10 @@ sk_sp<SkShader> StretchEffect::getShader(const sk_sp<SkImage>& snapshotImage) co mBuilder->uniform("uOverscrollY").set(&normOverScrollDistY, 1); mBuilder->uniform("uScrollX").set(&ZERO, 1); mBuilder->uniform("uScrollY").set(&ZERO, 1); - mBuilder->uniform("viewportWidth").set(&viewportWidth, 1); - mBuilder->uniform("viewportHeight").set(&viewportHeight, 1); - - mStretchShader = mBuilder->makeShader(nullptr, false); + mBuilder->uniform("viewportWidth").set(&width, 1); + mBuilder->uniform("viewportHeight").set(&height, 1); - return mStretchShader; + return mBuilder->makeShader(nullptr, false); } sk_sp<SkRuntimeEffect> StretchEffect::getStretchEffect() { diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h index 546d53b1a2df..61537f0b5a2c 100644 --- a/libs/hwui/effects/StretchEffect.h +++ b/libs/hwui/effects/StretchEffect.h @@ -26,19 +26,15 @@ namespace android::uirenderer { -// TODO: Inherit from base RenderEffect type? class StretchEffect { public: - enum class StretchInterpolator { - SmoothStep, - }; - StretchEffect(const SkRect& area, const SkVector& direction, float maxStretchAmountX, + StretchEffect(const SkVector& direction, + float maxStretchAmountX, float maxStretchAmountY) - : stretchArea(area) - , maxStretchAmountX(maxStretchAmountX) + : maxStretchAmountX(maxStretchAmountX) , maxStretchAmountY(maxStretchAmountY) - , mStretchDirection(direction) {} + , mStretchDirection(direction) { } StretchEffect() {} @@ -51,14 +47,18 @@ public: } StretchEffect& operator=(const StretchEffect& other) { - this->stretchArea = other.stretchArea; this->mStretchDirection = other.mStretchDirection; - this->mStretchShader = other.mStretchShader; this->maxStretchAmountX = other.maxStretchAmountX; this->maxStretchAmountY = other.maxStretchAmountY; return *this; } + bool operator==(const StretchEffect& other) const { + return mStretchDirection == other.mStretchDirection && + maxStretchAmountX == other.maxStretchAmountX && + maxStretchAmountY == other.maxStretchAmountY; + } + void mergeWith(const StretchEffect& other) { if (other.isEmpty()) { return; @@ -67,33 +67,26 @@ public: *this = other; return; } - setStretchDirection(mStretchDirection + other.mStretchDirection); + mStretchDirection += other.mStretchDirection; if (isEmpty()) { return setEmpty(); } - stretchArea.join(other.stretchArea); maxStretchAmountX = std::max(maxStretchAmountX, other.maxStretchAmountX); maxStretchAmountY = std::max(maxStretchAmountY, other.maxStretchAmountY); } - sk_sp<SkShader> getShader(const sk_sp<SkImage>& snapshotImage) const; + sk_sp<SkShader> getShader(float width, float height, + const sk_sp<SkImage>& snapshotImage) const; - SkRect stretchArea {0, 0, 0, 0}; float maxStretchAmountX = 0; float maxStretchAmountY = 0; - void setStretchDirection(const SkVector& direction) { - mStretchShader = nullptr; - mStretchDirection = direction; - } - const SkVector getStretchDirection() const { return mStretchDirection; } private: static sk_sp<SkRuntimeEffect> getStretchEffect(); mutable SkVector mStretchDirection{0, 0}; mutable std::unique_ptr<SkRuntimeShaderBuilder> mBuilder; - mutable sk_sp<SkShader> mStretchShader; }; } // namespace android::uirenderer diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index fffa80614370..5131c646c4a4 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -180,12 +180,10 @@ static jboolean android_view_RenderNode_clearStretch(CRITICAL_JNI_PARAMS_COMMA j } static jboolean android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, - jfloat left, jfloat top, jfloat right, - jfloat bottom, jfloat vX, jfloat vY, jfloat maxX, + jfloat vX, jfloat vY, jfloat maxX, jfloat maxY) { - StretchEffect effect = StretchEffect(SkRect::MakeLTRB(left, top, right, bottom), - {.fX = vX, .fY = vY}, maxX, maxY); - RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + auto* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + StretchEffect effect = StretchEffect({.fX = vX, .fY = vY}, maxX, maxY); renderNode->mutateStagingProperties().mutateLayerProperties().mutableStretchEffect().mergeWith( effect); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); @@ -643,13 +641,15 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, void handleStretchEffect(const TreeInfo& info, const Matrix4& transform) { // Search up to find the nearest stretcheffect parent - const StretchEffect* effect = info.damageAccumulator->findNearestStretchEffect(); + const DamageAccumulator::StretchResult result = + info.damageAccumulator->findNearestStretchEffect(); + const StretchEffect* effect = result.stretchEffect; if (!effect) { return; } - uirenderer::Rect area = effect->stretchArea; - transform.mapRect(area); + const auto& childRelativeBounds = result.childRelativeBounds; + JNIEnv* env = jnienv(); jobject localref = env->NewLocalRef(mWeakRef); @@ -661,9 +661,17 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, #ifdef __ANDROID__ // Layoutlib does not support CanvasContext SkVector stretchDirection = effect->getStretchDirection(); env->CallVoidMethod(localref, gPositionListener_ApplyStretchMethod, - info.canvasContext.getFrameNumber(), area.left, area.top, - area.right, area.bottom, stretchDirection.fX, stretchDirection.fY, - effect->maxStretchAmountX, effect->maxStretchAmountY); + info.canvasContext.getFrameNumber(), + result.width, + result.height, + stretchDirection.fX, + stretchDirection.fY, + effect->maxStretchAmountX, + effect->maxStretchAmountY, + childRelativeBounds.left(), + childRelativeBounds.top(), + childRelativeBounds.right(), + childRelativeBounds.bottom()); #endif env->DeleteLocalRef(localref); } @@ -739,7 +747,7 @@ static const JNINativeMethod gMethods[] = { {"nSetOutlineEmpty", "(J)Z", (void*)android_view_RenderNode_setOutlineEmpty}, {"nSetOutlineNone", "(J)Z", (void*)android_view_RenderNode_setOutlineNone}, {"nClearStretch", "(J)Z", (void*)android_view_RenderNode_clearStretch}, - {"nStretch", "(JFFFFFFFF)Z", (void*)android_view_RenderNode_stretch}, + {"nStretch", "(JFFFF)Z", (void*)android_view_RenderNode_stretch}, {"nHasShadow", "(J)Z", (void*)android_view_RenderNode_hasShadow}, {"nSetSpotShadowColor", "(JI)Z", (void*)android_view_RenderNode_setSpotShadowColor}, {"nGetSpotShadowColor", "(J)I", (void*)android_view_RenderNode_getSpotShadowColor}, @@ -814,7 +822,7 @@ int register_android_view_RenderNode(JNIEnv* env) { gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz, "positionChanged", "(JIIII)V"); gPositionListener_ApplyStretchMethod = - GetMethodIDOrDie(env, clazz, "applyStretch", "(JFFFFFFF)V"); + GetMethodIDOrDie(env, clazz, "applyStretch", "(JFFFFFFFFFF)V"); gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz, "positionLost", "(J)V"); return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 77d99a67b602..1ae06d082744 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -16,6 +16,7 @@ #include "RenderNodeDrawable.h" #include <SkPaintFilterCanvas.h> +#include "StretchMask.h" #include "RenderNode.h" #include "SkiaDisplayList.h" #include "TransformCanvas.h" @@ -245,17 +246,37 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { "SurfaceID|%" PRId64, renderNode->uniqueId()).c_str(), nullptr); } - if (renderNode->hasHolePunches()) { - TransformCanvas transformCanvas(canvas); - displayList->draw(&transformCanvas); - } - const StretchEffect& stretch = properties.layerProperties().getStretchEffect(); if (stretch.isEmpty()) { + // If we don't have any stretch effects, issue the filtered + // canvas draw calls to make sure we still punch a hole + // with the same canvas transformation + clip into the target + // canvas then draw the layer on top + if (renderNode->hasHolePunches()) { + TransformCanvas transformCanvas(canvas, SkBlendMode::kClear); + displayList->draw(&transformCanvas); + } canvas->drawImageRect(snapshotImage, bounds, bounds, sampling, &paint, SkCanvas::kStrict_SrcRectConstraint); } else { - sk_sp<SkShader> stretchShader = stretch.getShader(snapshotImage); + // If we do have stretch effects and have hole punches, + // then create a mask and issue the filtered draw calls to + // get the corresponding hole punches. + // Then apply the stretch to the mask and draw the mask to + // the destination + if (renderNode->hasHolePunches()) { + GrRecordingContext* context = canvas->recordingContext(); + StretchMask& stretchMask = renderNode->getStretchMask(); + stretchMask.draw(context, + stretch, + bounds, + displayList, + canvas); + } + + sk_sp<SkShader> stretchShader = stretch.getShader(bounds.width(), + bounds.height(), + snapshotImage); paint.setShader(stretchShader); canvas->drawRect(bounds, paint); } diff --git a/libs/hwui/pipeline/skia/StretchMask.cpp b/libs/hwui/pipeline/skia/StretchMask.cpp new file mode 100644 index 000000000000..2bbd8a4fa028 --- /dev/null +++ b/libs/hwui/pipeline/skia/StretchMask.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "StretchMask.h" +#include "SkSurface.h" +#include "SkCanvas.h" +#include "TransformCanvas.h" +#include "SkiaDisplayList.h" + +using android::uirenderer::StretchMask; + +void StretchMask::draw(GrRecordingContext* context, + const StretchEffect& stretch, + const SkRect& bounds, + skiapipeline::SkiaDisplayList* displayList, + SkCanvas* canvas) { + float width = bounds.width(); + float height = bounds.height(); + if (mMaskSurface == nullptr || mMaskSurface->width() != width || + mMaskSurface->height() != height) { + // Create a new surface if we don't have one or our existing size does + // not match. + mMaskSurface = SkSurface::MakeRenderTarget( + context, + SkBudgeted::kYes, + SkImageInfo::Make( + width, + height, + SkColorType::kAlpha_8_SkColorType, + SkAlphaType::kPremul_SkAlphaType) + ); + mIsDirty = true; + } + + if (mIsDirty) { + SkCanvas* maskCanvas = mMaskSurface->getCanvas(); + maskCanvas->drawColor(0, SkBlendMode::kClear); + TransformCanvas transformCanvas(maskCanvas, SkBlendMode::kSrcOver); + displayList->draw(&transformCanvas); + } + + sk_sp<SkImage> maskImage = mMaskSurface->makeImageSnapshot(); + sk_sp<SkShader> maskStretchShader = stretch.getShader( + width, height, maskImage); + + SkPaint maskPaint; + maskPaint.setShader(maskStretchShader); + maskPaint.setBlendMode(SkBlendMode::kDstOut); + canvas->drawRect(bounds, maskPaint); + + mIsDirty = false; +}
\ No newline at end of file diff --git a/libs/hwui/pipeline/skia/StretchMask.h b/libs/hwui/pipeline/skia/StretchMask.h new file mode 100644 index 000000000000..dc698b8e57ff --- /dev/null +++ b/libs/hwui/pipeline/skia/StretchMask.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "GrRecordingContext.h" +#include <effects/StretchEffect.h> +#include <SkSurface.h> +#include "SkiaDisplayList.h" + +namespace android::uirenderer { + +/** + * Helper class used to create/cache an SkSurface instance + * to create a mask that is used to draw a stretched hole punch + */ +class StretchMask { + public: + /** + * Release the current surface used for the stretch mask + */ + void clear() { + mMaskSurface = nullptr; + } + + /** + * Reset the dirty flag to re-create the stretch mask on the next draw + * pass + */ + void markDirty() { + mIsDirty = true; + } + + /** + * Draws the stretch mask into the given target canvas + * @param context GrRecordingContext used to create the surface if necessary + * @param stretch StretchEffect to apply to the mask + * @param bounds Target bounds to draw into the given canvas + * @param displayList List of drawing commands to render into the stretch mask + * @param canvas Target canvas to draw the mask into + */ + void draw(GrRecordingContext* context, + const StretchEffect& stretch, const SkRect& bounds, + skiapipeline::SkiaDisplayList* displayList, SkCanvas* canvas); +private: + sk_sp<SkSurface> mMaskSurface; + bool mIsDirty = true; +}; + +} diff --git a/libs/hwui/pipeline/skia/TransformCanvas.cpp b/libs/hwui/pipeline/skia/TransformCanvas.cpp index a6e4c4cf9ca7..6777c00c4655 100644 --- a/libs/hwui/pipeline/skia/TransformCanvas.cpp +++ b/libs/hwui/pipeline/skia/TransformCanvas.cpp @@ -28,8 +28,8 @@ void TransformCanvas::onDrawAnnotation(const SkRect& rect, const char* key, SkDa SkRRect roundRect = SkRRect::MakeRectXY(rect, radiusX, radiusY); SkPaint paint; - paint.setColor(0); - paint.setBlendMode(SkBlendMode::kClear); + paint.setColor(SkColors::kBlack); + paint.setBlendMode(mHolePunchBlendMode); mWrappedCanvas->drawRRect(roundRect, paint); } } diff --git a/libs/hwui/pipeline/skia/TransformCanvas.h b/libs/hwui/pipeline/skia/TransformCanvas.h index 47f77f107441..685b71d017e9 100644 --- a/libs/hwui/pipeline/skia/TransformCanvas.h +++ b/libs/hwui/pipeline/skia/TransformCanvas.h @@ -17,10 +17,12 @@ #include <include/core/SkCanvas.h> #include "SkPaintFilterCanvas.h" +#include <effects/StretchEffect.h> class TransformCanvas : public SkPaintFilterCanvas { public: - TransformCanvas(SkCanvas* target) : SkPaintFilterCanvas(target), mWrappedCanvas(target) {} + TransformCanvas(SkCanvas* target, SkBlendMode blendmode) : + SkPaintFilterCanvas(target), mWrappedCanvas(target), mHolePunchBlendMode(blendmode) {} protected: bool onFilter(SkPaint& paint) const override; @@ -32,4 +34,5 @@ protected: private: // We don't own the canvas so just maintain a raw pointer to it SkCanvas* mWrappedCanvas; + const SkBlendMode mHolePunchBlendMode; }; |