Loading libs/hwui/SkiaCanvas.cpp +25 −37 Original line number Diff line number Diff line Loading @@ -188,7 +188,7 @@ void SkiaCanvas::restoreUnclippedLayer(int restoreCount, const SkPaint& paint) { } if (mCanvas->getSaveCount() == restoreCount + 1) { SkCanvasPriv::DrawBehind(mCanvas, *filterPaint(paint)); SkCanvasPriv::DrawBehind(mCanvas, filterPaint(paint)); this->restore(); } } Loading Loading @@ -431,15 +431,14 @@ void SkiaCanvas::drawColor(int color, SkBlendMode mode) { mCanvas->drawColor(color, mode); } SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const { void SkiaCanvas::onFilterPaint(SkPaint& paint) { if (mPaintFilter) { mPaintFilter->filter(&paint.writeable()); mPaintFilter->filter(&paint); } return std::move(paint); } void SkiaCanvas::drawPaint(const SkPaint& paint) { mCanvas->drawPaint(*filterPaint(paint)); mCanvas->drawPaint(filterPaint(paint)); } // ---------------------------------------------------------------------------- Loading @@ -457,13 +456,11 @@ void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint, points += 2; } apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPoints(mode, count, pts.get(), p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPoints(mode, count, pts.get(), p); }); } void SkiaCanvas::drawPoint(float x, float y, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPoint(x, y, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPoint(x, y, p); }); } void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint) { Loading @@ -472,9 +469,8 @@ void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint) void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); }); } void SkiaCanvas::drawLines(const float* points, int count, const Paint& paint) { Loading @@ -484,46 +480,44 @@ void SkiaCanvas::drawLines(const float* points, int count, const Paint& paint) { void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; apply_looper(&paint, [&](const SkPaint& p) { applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRect({left, top, right, bottom}, p); }); } void SkiaCanvas::drawRegion(const SkRegion& region, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawRegion(region, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRegion(region, p); }); } void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawRoundRect(rect, rx, ry, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRoundRect(rect, rx, ry, p); }); } void SkiaCanvas::drawDoubleRoundRect(const SkRRect& outer, const SkRRect& inner, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawDRRect(outer, inner, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawDRRect(outer, inner, p); }); } void SkiaCanvas::drawCircle(float x, float y, float radius, const Paint& paint) { if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return; apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawCircle(x, y, radius, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawCircle(x, y, radius, p); }); } void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawOval(oval, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawOval(oval, p); }); } void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); apply_looper(&paint, [&](const SkPaint& p) { applyLooper(&paint, [&](const SkPaint& p) { if (fabs(sweepAngle) >= 360.0f) { mCanvas->drawOval(arc, p); } else { Loading @@ -537,13 +531,11 @@ void SkiaCanvas::drawPath(const SkPath& path, const Paint& paint) { if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { return; } apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPath(path, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPath(path, p); }); } void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); }); } // ---------------------------------------------------------------------------- Loading @@ -552,7 +544,7 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { auto image = bitmap.makeImage(); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto sampling = SkSamplingOptions(p.getFilterQuality()); mCanvas->drawImage(image, left, top, sampling, &p); }); Loading @@ -562,7 +554,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* auto image = bitmap.makeImage(); SkAutoCanvasRestore acr(mCanvas, true); mCanvas->concat(matrix); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto sampling = SkSamplingOptions(p.getFilterQuality()); mCanvas->drawImage(image, 0, 0, sampling, &p); }); Loading @@ -575,7 +567,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto sampling = SkSamplingOptions(p.getFilterQuality()); mCanvas->drawImageRect(image, srcRect, dstRect, sampling, &p, SkCanvas::kFast_SrcRectConstraint); Loading Loading @@ -672,11 +664,11 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, pnt.setShader(image->makeShader(sampling)); auto v = builder.detach(); apply_looper(&pnt, [&](const SkPaint& p) { applyLooper(&pnt, [&](const SkPaint& p) { SkPaint copy(p); auto s = SkSamplingOptions(p.getFilterQuality()); if (s != sampling) { // apply_looper changed the quality? // applyLooper changed the quality? copy.setShader(image->makeShader(s)); } mCanvas->drawVertices(v, SkBlendMode::kModulate, copy); Loading Loading @@ -707,7 +699,7 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa lattice.fBounds = nullptr; SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); auto image = bitmap.makeImage(); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto filter = SkSamplingOptions(p.getFilterQuality()).filter; mCanvas->drawImageLattice(image.get(), lattice, dst, filter, &p); }); Loading Loading @@ -746,9 +738,7 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const Paint& pai sk_sp<SkTextBlob> textBlob(builder.make()); apply_looper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); drawTextDecorations(x, y, totalAdvance, paintCopy); } Loading Loading @@ -788,9 +778,7 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, sk_sp<SkTextBlob> textBlob(builder.make()); apply_looper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); } // ---------------------------------------------------------------------------- Loading libs/hwui/SkiaCanvas.h +14 −44 Original line number Diff line number Diff line Loading @@ -169,53 +169,24 @@ protected: const Paint& paint, const SkPath& path, size_t start, size_t end) override; /** This class acts as a copy on write SkPaint. * * Initially this will be the SkPaint passed to the contructor. * The first time writable() is called this will become a copy of the * initial SkPaint (or a default SkPaint if nullptr). */ struct PaintCoW { PaintCoW(const SkPaint& that) : mPtr(&that) {} PaintCoW(const SkPaint* ptr) : mPtr(ptr) {} PaintCoW(const PaintCoW&) = delete; PaintCoW(PaintCoW&&) = delete; PaintCoW& operator=(const PaintCoW&) = delete; PaintCoW& operator=(PaintCoW&&) = delete; SkPaint& writeable() { if (!mStorage) { if (!mPtr) { mStorage.emplace(); } else { mStorage.emplace(*mPtr); } mPtr = &*mStorage; } return *mStorage; } operator const SkPaint*() const { return mPtr; } const SkPaint* operator->() const { assert(mPtr); return mPtr; } explicit operator bool() { return mPtr != nullptr; } private: const SkPaint* mPtr; std::optional<SkPaint> mStorage; }; void onFilterPaint(SkPaint& paint); /** Filters the paint using the current paint filter. * * @param paint the paint to filter. Will be initialized with the default * SkPaint before filtering if filtering is required. */ PaintCoW&& filterPaint(PaintCoW&& paint) const; SkPaint filterPaint(const SkPaint& src) { SkPaint dst(src); this->onFilterPaint(dst); return dst; } // proc(const SkPaint& modifiedPaint) template <typename Proc> void apply_looper(const Paint* paint, Proc proc) { SkPaint skp; BlurDrawLooper* looper = nullptr; if (paint) { skp = *filterPaint(paint); looper = paint->getLooper(); template <typename Proc> void applyLooper(const Paint* paint, Proc proc, void (*preFilter)(SkPaint&) = nullptr) { BlurDrawLooper* looper = paint ? paint->getLooper() : nullptr; const SkPaint* skpPtr = paint; SkPaint skp = skpPtr ? *skpPtr : SkPaint(); if (preFilter) { preFilter(skp); } this->onFilterPaint(skp); if (looper) { looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) { mCanvas->save(); Loading @@ -228,7 +199,6 @@ protected: } } private: struct SaveRec { int saveCount; Loading libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +36 −38 Original line number Diff line number Diff line Loading @@ -170,36 +170,23 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { // Recording Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) { bool fixBlending = false; bool fixAA = false; if (paint) { void SkiaRecordingCanvas::FilterForImage(SkPaint& paint) { // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and // older. fixBlending = sApiLevel <= 27 && paint->getBlendMode() == SkBlendMode::kClear; fixAA = paint->isAntiAlias(); } if (fixBlending || fixAA) { SkPaint& tmpPaint = paint.writeable(); if (fixBlending) { tmpPaint.setBlendMode(SkBlendMode::kDstOut); if (sApiLevel <= 27 && paint.getBlendMode() == SkBlendMode::kClear) { paint.setBlendMode(SkBlendMode::kDstOut); } // disabling AA on bitmap draws matches legacy HWUI behavior tmpPaint.setAntiAlias(false); } return filterPaint(std::move(paint)); paint.setAntiAlias(false); } static SkFilterMode Paint_to_filter(const SkPaint* paint) { return paint && paint->getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear static SkFilterMode Paint_to_filter(const SkPaint& paint) { return paint.getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear : SkFilterMode::kNearest; } static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) { static SkSamplingOptions Paint_to_sampling(const SkPaint& paint) { // Android only has 1-bit for "filter", so we don't try to cons-up mipmaps or cubics return SkSamplingOptions(Paint_to_filter(paint), SkMipmapMode::kNone); } Loading @@ -207,9 +194,12 @@ static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) { void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { sk_sp<SkImage> image = bitmap.makeImage(); applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImage(image, left + x, top + y, Paint_to_sampling(p), p, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImage(image, left, top, Paint_to_sampling(p), &p, bitmap.palette()); }, FilterForImage); // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means // it is not safe to store a raw SkImage pointer, because the image object will be destroyed Loading @@ -225,9 +215,12 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con sk_sp<SkImage> image = bitmap.makeImage(); applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImage(image, x, y, Paint_to_sampling(p), p, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImage(image, 0, 0, Paint_to_sampling(p), &p, bitmap.palette()); }, FilterForImage); if (!bitmap.isImmutable() && image.get() && !image->unique()) { mDisplayList->mMutableImages.push_back(image.get()); Loading @@ -242,10 +235,13 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop sk_sp<SkImage> image = bitmap.makeImage(); applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImageRect(image, srcRect, dstRect.makeOffset(x, y), Paint_to_sampling(p), p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImageRect(image, srcRect, dstRect, Paint_to_sampling(p), &p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette()); }, FilterForImage); if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() && !dstRect.isEmpty()) { Loading Loading @@ -281,10 +277,12 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch // HWUI always draws 9-patches with linear filtering, regardless of the Paint. const SkFilterMode filter = SkFilterMode::kLinear; applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), filter, p, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImageLattice(image, lattice, dst, filter, &p, bitmap.palette()); }, FilterForImage); if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) { mDisplayList->mMutableImages.push_back(image.get()); Loading libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +2 −17 Original line number Diff line number Diff line Loading @@ -87,22 +87,7 @@ private: std::unique_ptr<SkiaDisplayList> mDisplayList; StartReorderBarrierDrawable* mCurrentBarrier; template <typename Proc> void applyLooper(const Paint* paint, Proc proc) { SkPaint skp; BlurDrawLooper* looper = nullptr; if (paint) { skp = *filterBitmap(paint); looper = paint->getLooper(); } if (looper) { looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) { proc(offset.fX, offset.fY, &modifiedPaint); }); } else { proc(0, 0, &skp); } } static void FilterForImage(SkPaint&); /** * A new SkiaDisplayList is created or recycled if available. Loading @@ -113,7 +98,7 @@ private: */ void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height); PaintCoW&& filterBitmap(PaintCoW&& paint); using INHERITED = SkiaCanvas; }; } // namespace skiapipeline Loading Loading
libs/hwui/SkiaCanvas.cpp +25 −37 Original line number Diff line number Diff line Loading @@ -188,7 +188,7 @@ void SkiaCanvas::restoreUnclippedLayer(int restoreCount, const SkPaint& paint) { } if (mCanvas->getSaveCount() == restoreCount + 1) { SkCanvasPriv::DrawBehind(mCanvas, *filterPaint(paint)); SkCanvasPriv::DrawBehind(mCanvas, filterPaint(paint)); this->restore(); } } Loading Loading @@ -431,15 +431,14 @@ void SkiaCanvas::drawColor(int color, SkBlendMode mode) { mCanvas->drawColor(color, mode); } SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const { void SkiaCanvas::onFilterPaint(SkPaint& paint) { if (mPaintFilter) { mPaintFilter->filter(&paint.writeable()); mPaintFilter->filter(&paint); } return std::move(paint); } void SkiaCanvas::drawPaint(const SkPaint& paint) { mCanvas->drawPaint(*filterPaint(paint)); mCanvas->drawPaint(filterPaint(paint)); } // ---------------------------------------------------------------------------- Loading @@ -457,13 +456,11 @@ void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint, points += 2; } apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPoints(mode, count, pts.get(), p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPoints(mode, count, pts.get(), p); }); } void SkiaCanvas::drawPoint(float x, float y, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPoint(x, y, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPoint(x, y, p); }); } void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint) { Loading @@ -472,9 +469,8 @@ void SkiaCanvas::drawPoints(const float* points, int count, const Paint& paint) void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); }); } void SkiaCanvas::drawLines(const float* points, int count, const Paint& paint) { Loading @@ -484,46 +480,44 @@ void SkiaCanvas::drawLines(const float* points, int count, const Paint& paint) { void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; apply_looper(&paint, [&](const SkPaint& p) { applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRect({left, top, right, bottom}, p); }); } void SkiaCanvas::drawRegion(const SkRegion& region, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawRegion(region, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRegion(region, p); }); } void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawRoundRect(rect, rx, ry, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawRoundRect(rect, rx, ry, p); }); } void SkiaCanvas::drawDoubleRoundRect(const SkRRect& outer, const SkRRect& inner, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawDRRect(outer, inner, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawDRRect(outer, inner, p); }); } void SkiaCanvas::drawCircle(float x, float y, float radius, const Paint& paint) { if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return; apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawCircle(x, y, radius, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawCircle(x, y, radius, p); }); } void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawOval(oval, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawOval(oval, p); }); } void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const Paint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); apply_looper(&paint, [&](const SkPaint& p) { applyLooper(&paint, [&](const SkPaint& p) { if (fabs(sweepAngle) >= 360.0f) { mCanvas->drawOval(arc, p); } else { Loading @@ -537,13 +531,11 @@ void SkiaCanvas::drawPath(const SkPath& path, const Paint& paint) { if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { return; } apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawPath(path, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawPath(path, p); }); } void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const Paint& paint) { apply_looper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); }); applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); }); } // ---------------------------------------------------------------------------- Loading @@ -552,7 +544,7 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { auto image = bitmap.makeImage(); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto sampling = SkSamplingOptions(p.getFilterQuality()); mCanvas->drawImage(image, left, top, sampling, &p); }); Loading @@ -562,7 +554,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* auto image = bitmap.makeImage(); SkAutoCanvasRestore acr(mCanvas, true); mCanvas->concat(matrix); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto sampling = SkSamplingOptions(p.getFilterQuality()); mCanvas->drawImage(image, 0, 0, sampling, &p); }); Loading @@ -575,7 +567,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto sampling = SkSamplingOptions(p.getFilterQuality()); mCanvas->drawImageRect(image, srcRect, dstRect, sampling, &p, SkCanvas::kFast_SrcRectConstraint); Loading Loading @@ -672,11 +664,11 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, pnt.setShader(image->makeShader(sampling)); auto v = builder.detach(); apply_looper(&pnt, [&](const SkPaint& p) { applyLooper(&pnt, [&](const SkPaint& p) { SkPaint copy(p); auto s = SkSamplingOptions(p.getFilterQuality()); if (s != sampling) { // apply_looper changed the quality? // applyLooper changed the quality? copy.setShader(image->makeShader(s)); } mCanvas->drawVertices(v, SkBlendMode::kModulate, copy); Loading Loading @@ -707,7 +699,7 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa lattice.fBounds = nullptr; SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); auto image = bitmap.makeImage(); apply_looper(paint, [&](const SkPaint& p) { applyLooper(paint, [&](const SkPaint& p) { auto filter = SkSamplingOptions(p.getFilterQuality()).filter; mCanvas->drawImageLattice(image.get(), lattice, dst, filter, &p); }); Loading Loading @@ -746,9 +738,7 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const Paint& pai sk_sp<SkTextBlob> textBlob(builder.make()); apply_looper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); drawTextDecorations(x, y, totalAdvance, paintCopy); } Loading Loading @@ -788,9 +778,7 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, sk_sp<SkTextBlob> textBlob(builder.make()); apply_looper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); }); } // ---------------------------------------------------------------------------- Loading
libs/hwui/SkiaCanvas.h +14 −44 Original line number Diff line number Diff line Loading @@ -169,53 +169,24 @@ protected: const Paint& paint, const SkPath& path, size_t start, size_t end) override; /** This class acts as a copy on write SkPaint. * * Initially this will be the SkPaint passed to the contructor. * The first time writable() is called this will become a copy of the * initial SkPaint (or a default SkPaint if nullptr). */ struct PaintCoW { PaintCoW(const SkPaint& that) : mPtr(&that) {} PaintCoW(const SkPaint* ptr) : mPtr(ptr) {} PaintCoW(const PaintCoW&) = delete; PaintCoW(PaintCoW&&) = delete; PaintCoW& operator=(const PaintCoW&) = delete; PaintCoW& operator=(PaintCoW&&) = delete; SkPaint& writeable() { if (!mStorage) { if (!mPtr) { mStorage.emplace(); } else { mStorage.emplace(*mPtr); } mPtr = &*mStorage; } return *mStorage; } operator const SkPaint*() const { return mPtr; } const SkPaint* operator->() const { assert(mPtr); return mPtr; } explicit operator bool() { return mPtr != nullptr; } private: const SkPaint* mPtr; std::optional<SkPaint> mStorage; }; void onFilterPaint(SkPaint& paint); /** Filters the paint using the current paint filter. * * @param paint the paint to filter. Will be initialized with the default * SkPaint before filtering if filtering is required. */ PaintCoW&& filterPaint(PaintCoW&& paint) const; SkPaint filterPaint(const SkPaint& src) { SkPaint dst(src); this->onFilterPaint(dst); return dst; } // proc(const SkPaint& modifiedPaint) template <typename Proc> void apply_looper(const Paint* paint, Proc proc) { SkPaint skp; BlurDrawLooper* looper = nullptr; if (paint) { skp = *filterPaint(paint); looper = paint->getLooper(); template <typename Proc> void applyLooper(const Paint* paint, Proc proc, void (*preFilter)(SkPaint&) = nullptr) { BlurDrawLooper* looper = paint ? paint->getLooper() : nullptr; const SkPaint* skpPtr = paint; SkPaint skp = skpPtr ? *skpPtr : SkPaint(); if (preFilter) { preFilter(skp); } this->onFilterPaint(skp); if (looper) { looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) { mCanvas->save(); Loading @@ -228,7 +199,6 @@ protected: } } private: struct SaveRec { int saveCount; Loading
libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +36 −38 Original line number Diff line number Diff line Loading @@ -170,36 +170,23 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { // Recording Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) { bool fixBlending = false; bool fixAA = false; if (paint) { void SkiaRecordingCanvas::FilterForImage(SkPaint& paint) { // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and // older. fixBlending = sApiLevel <= 27 && paint->getBlendMode() == SkBlendMode::kClear; fixAA = paint->isAntiAlias(); } if (fixBlending || fixAA) { SkPaint& tmpPaint = paint.writeable(); if (fixBlending) { tmpPaint.setBlendMode(SkBlendMode::kDstOut); if (sApiLevel <= 27 && paint.getBlendMode() == SkBlendMode::kClear) { paint.setBlendMode(SkBlendMode::kDstOut); } // disabling AA on bitmap draws matches legacy HWUI behavior tmpPaint.setAntiAlias(false); } return filterPaint(std::move(paint)); paint.setAntiAlias(false); } static SkFilterMode Paint_to_filter(const SkPaint* paint) { return paint && paint->getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear static SkFilterMode Paint_to_filter(const SkPaint& paint) { return paint.getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear : SkFilterMode::kNearest; } static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) { static SkSamplingOptions Paint_to_sampling(const SkPaint& paint) { // Android only has 1-bit for "filter", so we don't try to cons-up mipmaps or cubics return SkSamplingOptions(Paint_to_filter(paint), SkMipmapMode::kNone); } Loading @@ -207,9 +194,12 @@ static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) { void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { sk_sp<SkImage> image = bitmap.makeImage(); applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImage(image, left + x, top + y, Paint_to_sampling(p), p, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImage(image, left, top, Paint_to_sampling(p), &p, bitmap.palette()); }, FilterForImage); // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means // it is not safe to store a raw SkImage pointer, because the image object will be destroyed Loading @@ -225,9 +215,12 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con sk_sp<SkImage> image = bitmap.makeImage(); applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImage(image, x, y, Paint_to_sampling(p), p, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImage(image, 0, 0, Paint_to_sampling(p), &p, bitmap.palette()); }, FilterForImage); if (!bitmap.isImmutable() && image.get() && !image->unique()) { mDisplayList->mMutableImages.push_back(image.get()); Loading @@ -242,10 +235,13 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop sk_sp<SkImage> image = bitmap.makeImage(); applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImageRect(image, srcRect, dstRect.makeOffset(x, y), Paint_to_sampling(p), p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImageRect(image, srcRect, dstRect, Paint_to_sampling(p), &p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette()); }, FilterForImage); if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() && !dstRect.isEmpty()) { Loading Loading @@ -281,10 +277,12 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch // HWUI always draws 9-patches with linear filtering, regardless of the Paint. const SkFilterMode filter = SkFilterMode::kLinear; applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), filter, p, bitmap.palette()); }); applyLooper( paint, [&](const SkPaint& p) { mRecorder.drawImageLattice(image, lattice, dst, filter, &p, bitmap.palette()); }, FilterForImage); if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) { mDisplayList->mMutableImages.push_back(image.get()); Loading
libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +2 −17 Original line number Diff line number Diff line Loading @@ -87,22 +87,7 @@ private: std::unique_ptr<SkiaDisplayList> mDisplayList; StartReorderBarrierDrawable* mCurrentBarrier; template <typename Proc> void applyLooper(const Paint* paint, Proc proc) { SkPaint skp; BlurDrawLooper* looper = nullptr; if (paint) { skp = *filterBitmap(paint); looper = paint->getLooper(); } if (looper) { looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) { proc(offset.fX, offset.fY, &modifiedPaint); }); } else { proc(0, 0, &skp); } } static void FilterForImage(SkPaint&); /** * A new SkiaDisplayList is created or recycled if available. Loading @@ -113,7 +98,7 @@ private: */ void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height); PaintCoW&& filterBitmap(PaintCoW&& paint); using INHERITED = SkiaCanvas; }; } // namespace skiapipeline Loading