diff options
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 62 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.h | 58 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 74 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.h | 19 |
4 files changed, 77 insertions, 136 deletions
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 1fddac4cd05d..28d2b4cec0e1 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -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(); } } @@ -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)); } // ---------------------------------------------------------------------------- @@ -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) { @@ -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) { @@ -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 { @@ -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); }); } // ---------------------------------------------------------------------------- @@ -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); }); @@ -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); }); @@ -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); @@ -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); @@ -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); }); @@ -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); } @@ -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); }); } // ---------------------------------------------------------------------------- diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index eac3f2217bd8..9ab2b106dbfa 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -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(); @@ -228,7 +199,6 @@ protected: } } - private: struct SaveRec { int saveCount; diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 04e3a1cb887e..af7271e96cb9 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -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) { - // 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(); +void SkiaRecordingCanvas::FilterForImage(SkPaint& paint) { + // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and + // older. + if (sApiLevel <= 27 && paint.getBlendMode() == SkBlendMode::kClear) { + paint.setBlendMode(SkBlendMode::kDstOut); } - if (fixBlending || fixAA) { - SkPaint& tmpPaint = paint.writeable(); - - if (fixBlending) { - tmpPaint.setBlendMode(SkBlendMode::kDstOut); - } - - // disabling AA on bitmap draws matches legacy HWUI behavior - tmpPaint.setAntiAlias(false); - } - - return filterPaint(std::move(paint)); + // disabling AA on bitmap draws matches legacy HWUI behavior + paint.setAntiAlias(false); } -static SkFilterMode Paint_to_filter(const SkPaint* paint) { - return paint && paint->getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear - : SkFilterMode::kNearest; +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); } @@ -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 @@ -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()); @@ -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()) { @@ -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()); diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index 1e404b845084..ff03e0c5f6d6 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -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. @@ -113,7 +98,7 @@ private: */ void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height); - PaintCoW&& filterBitmap(PaintCoW&& paint); + using INHERITED = SkiaCanvas; }; } // namespace skiapipeline |