diff options
author | 2020-11-25 15:30:20 -0800 | |
---|---|---|
committer | 2020-12-02 19:30:20 -0800 | |
commit | 55f197660ca3812a813f483bf49993333bcc8af8 (patch) | |
tree | 8c587f35e0f532a2c555060b55ae4eebdf190af5 | |
parent | 645a8573557932d1ef0a1a2078ab999e7bc58d31 (diff) |
Add support for drawLayer CanvasOps
Introdcued DrawLayer CanvasOp and implementation
Test in progress with support for GrRecrodingContext backed
SkDevices.
Test: In progress
Change-Id: I53c58233536a78c20b867d659eae2dae2adc54b2
-rw-r--r-- | libs/hwui/Layer.cpp | 86 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 3 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOpRasterizer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOpTypes.h | 1 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOps.h | 6 |
5 files changed, 101 insertions, 1 deletions
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index c174c240ff22..f4c633fbe58f 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -18,6 +18,7 @@ #include "renderstate/RenderState.h" #include "utils/Color.h" +#include "utils/MathUtils.h" namespace android { namespace uirenderer { @@ -52,5 +53,90 @@ SkBlendMode Layer::getMode() const { } } +static inline SkScalar isIntegerAligned(SkScalar x) { + return fabsf(roundf(x) - x) <= NON_ZERO_EPSILON; +} + +// Disable filtering when there is no scaling in screen coordinates and the corners have the same +// fraction (for translate) or zero fraction (for any other rect-to-rect transform). +static bool shouldFilterRect(const SkMatrix& matrix, const SkRect& srcRect, const SkRect& dstRect) { + if (!matrix.rectStaysRect()) return true; + SkRect dstDevRect = matrix.mapRect(dstRect); + float dstW, dstH; + if (MathUtils::isZero(matrix.getScaleX()) && MathUtils::isZero(matrix.getScaleY())) { + // Has a 90 or 270 degree rotation, although total matrix may also have scale factors + // in m10 and m01. Those scalings are automatically handled by mapRect so comparing + // dimensions is sufficient, but swap width and height comparison. + dstW = dstDevRect.height(); + dstH = dstDevRect.width(); + } else { + // Handle H/V flips or 180 rotation matrices. Axes may have been mirrored, but + // dimensions are still safe to compare directly. + dstW = dstDevRect.width(); + dstH = dstDevRect.height(); + } + if (!(MathUtils::areEqual(dstW, srcRect.width()) && + MathUtils::areEqual(dstH, srcRect.height()))) { + return true; + } + // Device rect and source rect should be integer aligned to ensure there's no difference + // in how nearest-neighbor sampling is resolved. + return !(isIntegerAligned(srcRect.x()) && + isIntegerAligned(srcRect.y()) && + isIntegerAligned(dstDevRect.x()) && + isIntegerAligned(dstDevRect.y())); +} + +void Layer::draw(SkCanvas* canvas) { + GrRecordingContext* context = canvas->recordingContext(); + if (context == nullptr) { + SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface")); + return; + } + SkMatrix layerTransform = getTransform(); + //sk_sp<SkImage> layerImage = getImage(); + const int layerWidth = getWidth(); + const int layerHeight = getHeight(); + if (layerImage) { + SkMatrix textureMatrixInv; + textureMatrixInv = getTexTransform(); + // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed + // use bottom left origin and remove flipV and invert transformations. + SkMatrix flipV; + flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1); + textureMatrixInv.preConcat(flipV); + textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight); + textureMatrixInv.postScale(layerImage->width(), layerImage->height()); + SkMatrix textureMatrix; + if (!textureMatrixInv.invert(&textureMatrix)) { + textureMatrix = textureMatrixInv; + } + + SkMatrix matrix; + matrix = SkMatrix::Concat(layerTransform, textureMatrix); + + SkPaint paint; + paint.setAlpha(getAlpha()); + paint.setBlendMode(getMode()); + paint.setColorFilter(getColorFilter()); + const bool nonIdentityMatrix = !matrix.isIdentity(); + if (nonIdentityMatrix) { + canvas->save(); + canvas->concat(matrix); + } + const SkMatrix& totalMatrix = canvas->getTotalMatrix(); + + SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height()); + if (getForceFilter() || shouldFilterRect(totalMatrix, imageRect, imageRect)) { + paint.setFilterQuality(kLow_SkFilterQuality); + } + canvas->drawImage(layerImage.get(), 0, 0, &paint); + // restore the original matrix + if (nonIdentityMatrix) { + canvas->restore(); + } + } +} + } // namespace uirenderer } // namespace android diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index ea3bfc9e80cb..e99e76299317 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -21,6 +21,7 @@ #include <SkBlendMode.h> #include <SkColorFilter.h> #include <SkColorSpace.h> +#include <SkCanvas.h> #include <SkPaint.h> #include <SkImage.h> #include <SkMatrix.h> @@ -87,6 +88,8 @@ public: inline sk_sp<SkImage> getImage() const { return this->layerImage; } + void draw(SkCanvas* canvas); + protected: RenderState& mRenderState; diff --git a/libs/hwui/canvas/CanvasOpRasterizer.cpp b/libs/hwui/canvas/CanvasOpRasterizer.cpp index 25129f641c00..0093c38cf8a8 100644 --- a/libs/hwui/canvas/CanvasOpRasterizer.cpp +++ b/libs/hwui/canvas/CanvasOpRasterizer.cpp @@ -33,7 +33,11 @@ void rasterizeCanvasBuffer(const CanvasOpBuffer& source, SkCanvas* destination) SkMatrix& currentGlobalTransform = globalMatrixStack.emplace_back(SkMatrix::I()); source.for_each([&]<CanvasOpType T>(const CanvasOpContainer<T> * op) { - if constexpr (T == CanvasOpType::BeginZ || T == CanvasOpType::EndZ) { + if constexpr ( + T == CanvasOpType::BeginZ || + T == CanvasOpType::EndZ || + T == CanvasOpType::DrawLayer + ) { // Do beginZ or endZ LOG_ALWAYS_FATAL("TODO"); return; diff --git a/libs/hwui/canvas/CanvasOpTypes.h b/libs/hwui/canvas/CanvasOpTypes.h index f9df2f7aa5ba..2dfddaca0919 100644 --- a/libs/hwui/canvas/CanvasOpTypes.h +++ b/libs/hwui/canvas/CanvasOpTypes.h @@ -55,6 +55,7 @@ enum class CanvasOpType : int8_t { // DrawImageLattice also used to draw 9 patches DrawImageLattice, DrawPicture, + DrawLayer, // TODO: Rest diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index 8c7113d5d075..b499733757a8 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -28,6 +28,7 @@ #include "CanvasProperty.h" #include "CanvasOpTypes.h" +#include "Layer.h" #include <experimental/type_traits> #include <utility> @@ -364,6 +365,11 @@ struct CanvasOp<CanvasOpType::DrawPicture> { } }; +template<> +struct CanvasOp<CanvasOpType::DrawLayer> { + sp<Layer> layer; +}; + // cleanup our macros #undef ASSERT_DRAWABLE |