Draw gainmaps in HDR

Test: manual
Bug: 266628247
Change-Id: Iad0234089913637f9cddcb39d8fc32badabf3865
This commit is contained in:
John Reck
2023-02-01 20:57:44 -05:00
parent 255dc584a2
commit 115195e356
7 changed files with 259 additions and 98 deletions

View File

@@ -511,6 +511,7 @@ cc_defaults {
"canvas/CanvasOpBuffer.cpp",
"canvas/CanvasOpRasterizer.cpp",
"effects/StretchEffect.cpp",
"effects/GainmapRenderer.cpp",
"pipeline/skia/HolePunch.cpp",
"pipeline/skia/SkiaDisplayList.cpp",
"pipeline/skia/SkiaRecordingCanvas.cpp",

View File

@@ -19,9 +19,9 @@
#include <GrRecordingContext.h>
#include <SkMesh.h>
#include <hwui/Paint.h>
#include <log/log.h>
#include <experimental/type_traits>
#include <log/log.h>
#include <utility>
#include "SkAndroidFrameworkUtils.h"
@@ -45,7 +45,8 @@
#include "SkVertices.h"
#include "Tonemapper.h"
#include "VectorDrawable.h"
#include "include/gpu/GpuTypes.h" // from Skia
#include "effects/GainmapRenderer.h"
#include "include/gpu/GpuTypes.h" // from Skia
#include "include/gpu/GrDirectContext.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/FunctorDrawable.h"
@@ -332,9 +333,15 @@ struct DrawPicture final : Op {
struct DrawImage final : Op {
static const auto kType = Type::DrawImage;
DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint, BitmapPalette palette)
: image(std::move(image)), x(x), y(y), sampling(sampling), palette(palette) {
DrawImage(DrawImagePayload&& payload, SkScalar x, SkScalar y, const SkSamplingOptions& sampling,
const SkPaint* paint)
: image(std::move(payload.image))
, x(x)
, y(y)
, sampling(sampling)
, palette(payload.palette)
, gainmap(std::move(payload.gainmapImage))
, gainmapInfo(payload.gainmapInfo) {
if (paint) {
this->paint = *paint;
}
@@ -344,19 +351,34 @@ struct DrawImage final : Op {
SkSamplingOptions sampling;
SkPaint paint;
BitmapPalette palette;
sk_sp<const SkImage> gainmap;
SkGainmapInfo gainmapInfo;
void draw(SkCanvas* c, const SkMatrix&) const {
SkPaint newPaint = paint;
tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
c->drawImage(image.get(), x, y, sampling, &newPaint);
if (gainmap) {
SkRect src = SkRect::MakeWH(image->width(), image->height());
SkRect dst = SkRect::MakeXYWH(x, y, src.width(), src.height());
DrawGainmapBitmap(c, image, src, dst, sampling, &paint,
SkCanvas::kFast_SrcRectConstraint, gainmap, gainmapInfo);
} else {
SkPaint newPaint = paint;
tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
c->drawImage(image.get(), x, y, sampling, &newPaint);
}
}
};
struct DrawImageRect final : Op {
static const auto kType = Type::DrawImageRect;
DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
DrawImageRect(DrawImagePayload&& payload, const SkRect* src, const SkRect& dst,
const SkSamplingOptions& sampling, const SkPaint* paint,
SkCanvas::SrcRectConstraint constraint, BitmapPalette palette)
: image(std::move(image)), dst(dst), sampling(sampling), constraint(constraint)
, palette(palette) {
SkCanvas::SrcRectConstraint constraint)
: image(std::move(payload.image))
, dst(dst)
, sampling(sampling)
, constraint(constraint)
, palette(payload.palette)
, gainmap(std::move(payload.gainmapImage))
, gainmapInfo(payload.gainmapInfo) {
this->src = src ? *src : SkRect::MakeIWH(this->image->width(), this->image->height());
if (paint) {
this->paint = *paint;
@@ -368,25 +390,32 @@ struct DrawImageRect final : Op {
SkPaint paint;
SkCanvas::SrcRectConstraint constraint;
BitmapPalette palette;
sk_sp<const SkImage> gainmap;
SkGainmapInfo gainmapInfo;
void draw(SkCanvas* c, const SkMatrix&) const {
SkPaint newPaint = paint;
tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
c->drawImageRect(image.get(), src, dst, sampling, &newPaint, constraint);
if (gainmap) {
DrawGainmapBitmap(c, image, src, dst, sampling, &paint, constraint, gainmap,
gainmapInfo);
} else {
SkPaint newPaint = paint;
tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
c->drawImageRect(image.get(), src, dst, sampling, &newPaint, constraint);
}
}
};
struct DrawImageLattice final : Op {
static const auto kType = Type::DrawImageLattice;
DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs, const SkIRect& src,
const SkRect& dst, SkFilterMode filter, const SkPaint* paint,
BitmapPalette palette)
: image(std::move(image))
DrawImageLattice(DrawImagePayload&& payload, int xs, int ys, int fs, const SkIRect& src,
const SkRect& dst, SkFilterMode filter, const SkPaint* paint)
: image(std::move(payload.image))
, xs(xs)
, ys(ys)
, fs(fs)
, src(src)
, dst(dst)
, filter(filter)
, palette(palette) {
, palette(payload.palette) {
if (paint) {
this->paint = *paint;
}
@@ -399,6 +428,8 @@ struct DrawImageLattice final : Op {
SkPaint paint;
BitmapPalette palette;
void draw(SkCanvas* c, const SkMatrix&) const {
// TODO: Support drawing a gainmap 9-patch?
auto xdivs = pod<int>(this, 0), ydivs = pod<int>(this, xs * sizeof(int));
auto colors = (0 == fs) ? nullptr : pod<SkColor>(this, (xs + ys) * sizeof(int));
auto flags =
@@ -781,27 +812,25 @@ void DisplayListData::drawPicture(const SkPicture* picture, const SkMatrix* matr
const SkPaint* paint) {
this->push<DrawPicture>(0, picture, matrix, paint);
}
void DisplayListData::drawImage(sk_sp<const SkImage> image, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint,
BitmapPalette palette) {
this->push<DrawImage>(0, std::move(image), x, y, sampling, paint, palette);
void DisplayListData::drawImage(DrawImagePayload&& payload, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint) {
this->push<DrawImage>(0, std::move(payload), x, y, sampling, paint);
}
void DisplayListData::drawImageRect(sk_sp<const SkImage> image, const SkRect* src,
void DisplayListData::drawImageRect(DrawImagePayload&& payload, const SkRect* src,
const SkRect& dst, const SkSamplingOptions& sampling,
const SkPaint* paint, SkCanvas::SrcRectConstraint constraint,
BitmapPalette palette) {
this->push<DrawImageRect>(0, std::move(image), src, dst, sampling, paint, constraint, palette);
const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
this->push<DrawImageRect>(0, std::move(payload), src, dst, sampling, paint, constraint);
}
void DisplayListData::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice,
const SkRect& dst, SkFilterMode filter, const SkPaint* paint,
BitmapPalette palette) {
void DisplayListData::drawImageLattice(DrawImagePayload&& payload, const SkCanvas::Lattice& lattice,
const SkRect& dst, SkFilterMode filter,
const SkPaint* paint) {
int xs = lattice.fXCount, ys = lattice.fYCount;
int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0;
size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType) +
fs * sizeof(SkColor);
LOG_FATAL_IF(!lattice.fBounds);
void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds,
dst, filter, paint, palette);
void* pod = this->push<DrawImageLattice>(bytes, std::move(payload), xs, ys, fs,
*lattice.fBounds, dst, filter, paint);
copy_v(pod, lattice.fXDivs, xs, lattice.fYDivs, ys, lattice.fColors, fs, lattice.fRectTypes,
fs);
}
@@ -1108,57 +1137,55 @@ void RecordingCanvas::drawRippleDrawable(const skiapipeline::RippleDrawableParam
fDL->drawRippleDrawable(params);
}
void RecordingCanvas::drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint,
BitmapPalette palette) {
fDL->drawImage(image, x, y, sampling, paint, palette);
void RecordingCanvas::drawImage(DrawImagePayload&& payload, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint) {
fDL->drawImage(std::move(payload), x, y, sampling, paint);
}
void RecordingCanvas::drawImageRect(const sk_sp<SkImage>& image, const SkRect& src,
void RecordingCanvas::drawImageRect(DrawImagePayload&& payload, const SkRect& src,
const SkRect& dst, const SkSamplingOptions& sampling,
const SkPaint* paint, SrcRectConstraint constraint,
BitmapPalette palette) {
fDL->drawImageRect(image, &src, dst, sampling, paint, constraint, palette);
const SkPaint* paint, SrcRectConstraint constraint) {
fDL->drawImageRect(std::move(payload), &src, dst, sampling, paint, constraint);
}
void RecordingCanvas::drawImageLattice(const sk_sp<SkImage>& image, const Lattice& lattice,
const SkRect& dst, SkFilterMode filter, const SkPaint* paint,
BitmapPalette palette) {
if (!image || dst.isEmpty()) {
void RecordingCanvas::drawImageLattice(DrawImagePayload&& payload, const Lattice& lattice,
const SkRect& dst, SkFilterMode filter,
const SkPaint* paint) {
if (!payload.image || dst.isEmpty()) {
return;
}
SkIRect bounds;
Lattice latticePlusBounds = lattice;
if (!latticePlusBounds.fBounds) {
bounds = SkIRect::MakeWH(image->width(), image->height());
bounds = SkIRect::MakeWH(payload.image->width(), payload.image->height());
latticePlusBounds.fBounds = &bounds;
}
if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
fDL->drawImageLattice(image, latticePlusBounds, dst, filter, paint, palette);
if (SkLatticeIter::Valid(payload.image->width(), payload.image->height(), latticePlusBounds)) {
fDL->drawImageLattice(std::move(payload), latticePlusBounds, dst, filter, paint);
} else {
SkSamplingOptions sampling(filter, SkMipmapMode::kNone);
fDL->drawImageRect(image, nullptr, dst, sampling, paint, kFast_SrcRectConstraint, palette);
fDL->drawImageRect(std::move(payload), nullptr, dst, sampling, paint,
kFast_SrcRectConstraint);
}
}
void RecordingCanvas::onDrawImage2(const SkImage* img, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint) {
fDL->drawImage(sk_ref_sp(img), x, y, sampling, paint, BitmapPalette::Unknown);
fDL->drawImage(DrawImagePayload(img), x, y, sampling, paint);
}
void RecordingCanvas::onDrawImageRect2(const SkImage* img, const SkRect& src, const SkRect& dst,
const SkSamplingOptions& sampling, const SkPaint* paint,
SrcRectConstraint constraint) {
fDL->drawImageRect(sk_ref_sp(img), &src, dst, sampling, paint, constraint,
BitmapPalette::Unknown);
fDL->drawImageRect(DrawImagePayload(img), &src, dst, sampling, paint, constraint);
}
void RecordingCanvas::onDrawImageLattice2(const SkImage* img, const SkCanvas::Lattice& lattice,
const SkRect& dst, SkFilterMode filter,
const SkPaint* paint) {
fDL->drawImageLattice(sk_ref_sp(img), lattice, dst, filter, paint, BitmapPalette::Unknown);
fDL->drawImageLattice(DrawImagePayload(img), lattice, dst, filter, paint);
}
void RecordingCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],

View File

@@ -16,6 +16,14 @@
#pragma once
#include <SkCanvas.h>
#include <SkCanvasVirtualEnforcer.h>
#include <SkDrawable.h>
#include <SkGainmapInfo.h>
#include <SkNoDrawCanvas.h>
#include <SkPaint.h>
#include <SkPath.h>
#include <SkRect.h>
#include <SkRuntimeEffect.h>
#include <log/log.h>
@@ -23,13 +31,7 @@
#include <vector>
#include "CanvasTransform.h"
#include "SkCanvas.h"
#include "SkCanvasVirtualEnforcer.h"
#include "SkDrawable.h"
#include "SkNoDrawCanvas.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRect.h"
#include "Gainmap.h"
#include "hwui/Bitmap.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "utils/AutoMalloc.h"
@@ -64,6 +66,32 @@ struct DisplayListOp {
static_assert(sizeof(DisplayListOp) == 4);
struct DrawImagePayload {
explicit DrawImagePayload(Bitmap& bitmap)
: image(bitmap.makeImage()), palette(bitmap.palette()) {
if (bitmap.hasGainmap()) {
auto gainmap = bitmap.gainmap();
gainmapInfo = gainmap->info;
gainmapImage = gainmap->bitmap->makeImage();
}
}
explicit DrawImagePayload(const SkImage* image)
: image(sk_ref_sp(image)), palette(BitmapPalette::Unknown) {}
DrawImagePayload(const DrawImagePayload&) = default;
DrawImagePayload(DrawImagePayload&&) = default;
DrawImagePayload& operator=(const DrawImagePayload&) = default;
DrawImagePayload& operator=(DrawImagePayload&&) = default;
~DrawImagePayload() = default;
sk_sp<SkImage> image;
BitmapPalette palette;
sk_sp<SkImage> gainmapImage;
SkGainmapInfo gainmapInfo;
};
class RecordingCanvas;
class DisplayListData final {
@@ -122,13 +150,12 @@ private:
void drawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&);
void drawImage(sk_sp<const SkImage>, SkScalar, SkScalar, const SkSamplingOptions&,
const SkPaint*, BitmapPalette palette);
void drawImageNine(sk_sp<const SkImage>, const SkIRect&, const SkRect&, const SkPaint*);
void drawImageRect(sk_sp<const SkImage>, const SkRect*, const SkRect&, const SkSamplingOptions&,
const SkPaint*, SkCanvas::SrcRectConstraint, BitmapPalette palette);
void drawImageLattice(sk_sp<const SkImage>, const SkCanvas::Lattice&, const SkRect&,
SkFilterMode, const SkPaint*, BitmapPalette);
void drawImage(DrawImagePayload&&, SkScalar, SkScalar, const SkSamplingOptions&,
const SkPaint*);
void drawImageRect(DrawImagePayload&&, const SkRect*, const SkRect&, const SkSamplingOptions&,
const SkPaint*, SkCanvas::SrcRectConstraint);
void drawImageLattice(DrawImagePayload&&, const SkCanvas::Lattice&, const SkRect&, SkFilterMode,
const SkPaint*);
void drawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
const SkPaint&);
@@ -195,14 +222,14 @@ public:
void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
void drawImage(const sk_sp<SkImage>&, SkScalar left, SkScalar top, const SkSamplingOptions&,
const SkPaint* paint, BitmapPalette pallete);
void drawRippleDrawable(const skiapipeline::RippleDrawableParams& params);
void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
const SkSamplingOptions&, const SkPaint*, SrcRectConstraint, BitmapPalette);
void drawImageLattice(const sk_sp<SkImage>& image, const Lattice& lattice, const SkRect& dst,
SkFilterMode, const SkPaint* paint, BitmapPalette palette);
void drawImage(DrawImagePayload&&, SkScalar, SkScalar, const SkSamplingOptions&,
const SkPaint*);
void drawImageRect(DrawImagePayload&&, const SkRect&, const SkRect&, const SkSamplingOptions&,
const SkPaint*, SrcRectConstraint);
void drawImageLattice(DrawImagePayload&&, const Lattice& lattice, const SkRect&, SkFilterMode,
const SkPaint*);
void onDrawImage2(const SkImage*, SkScalar, SkScalar, const SkSamplingOptions&,
const SkPaint*) override;

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 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 "GainmapRenderer.h"
#include <SkGainmapShader.h>
#include "Gainmap.h"
#include "Rect.h"
#include "utils/Trace.h"
#ifdef __ANDROID__
#include "renderthread/CanvasContext.h"
#endif
namespace android::uirenderer {
using namespace renderthread;
void DrawGainmapBitmap(SkCanvas* c, const sk_sp<const SkImage>& image, const SkRect& src,
const SkRect& dst, const SkSamplingOptions& sampling, const SkPaint* paint,
SkCanvas::SrcRectConstraint constraint,
const sk_sp<const SkImage>& gainmapImage, const SkGainmapInfo& gainmapInfo) {
ATRACE_CALL();
#ifdef __ANDROID__
CanvasContext* context = CanvasContext::getActiveContext();
float targetSdrHdrRatio = context ? context->targetSdrHdrRatio() : 1.f;
if (targetSdrHdrRatio > 1.f && gainmapImage) {
SkPaint gainmapPaint = *paint;
float sX = gainmapImage->width() / (float)image->width();
float sY = gainmapImage->height() / (float)image->height();
SkRect gainmapSrc = src;
// TODO: Tweak rounding?
gainmapSrc.fLeft *= sX;
gainmapSrc.fRight *= sX;
gainmapSrc.fTop *= sY;
gainmapSrc.fBottom *= sY;
// TODO: Temporary workaround for SkGainmapShader::Make not having a const variant
sk_sp<SkImage> mutImage = sk_ref_sp(const_cast<SkImage*>(image.get()));
sk_sp<SkImage> mutGainmap = sk_ref_sp(const_cast<SkImage*>(gainmapImage.get()));
auto shader = SkGainmapShader::Make(mutImage, src, sampling, mutGainmap, gainmapSrc,
sampling, gainmapInfo, dst, targetSdrHdrRatio,
c->imageInfo().refColorSpace());
gainmapPaint.setShader(shader);
c->drawRect(dst, gainmapPaint);
} else
#endif
c->drawImageRect(image.get(), src, dst, sampling, paint, constraint);
}
} // namespace android::uirenderer

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2023 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 <SkCanvas.h>
#include <SkGainmapInfo.h>
#include <SkImage.h>
#include <SkPaint.h>
#include "hwui/Bitmap.h"
namespace android::uirenderer {
void DrawGainmapBitmap(SkCanvas* c, const sk_sp<const SkImage>& image, const SkRect& src,
const SkRect& dst, const SkSamplingOptions& sampling, const SkPaint* paint,
SkCanvas::SrcRectConstraint constraint,
const sk_sp<const SkImage>& gainmapImage, const SkGainmapInfo& gainmapInfo);
} // namespace android::uirenderer

View File

@@ -208,40 +208,52 @@ void SkiaRecordingCanvas::FilterForImage(SkPaint& paint) {
}
}
void SkiaRecordingCanvas::handleMutableImages(Bitmap& bitmap, DrawImagePayload& payload) {
// 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
// when this function ends.
if (!bitmap.isImmutable() && payload.image.get() && !payload.image->unique()) {
mDisplayList->mMutableImages.push_back(payload.image.get());
}
if (bitmap.hasGainmap()) {
auto gainmapBitmap = bitmap.gainmap()->bitmap;
// Not all DrawImagePayload receivers will store the gainmap (such as DrawImageLattice),
// so only store it in the mutable list if it was actually recorded
if (!gainmapBitmap->isImmutable() && payload.gainmapImage.get() &&
!payload.gainmapImage->unique()) {
mDisplayList->mMutableImages.push_back(payload.gainmapImage.get());
}
}
}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) {
sk_sp<SkImage> image = bitmap.makeImage();
auto payload = DrawImagePayload(bitmap);
applyLooper(
paint,
[&](const Paint& p) {
mRecorder.drawImage(image, left, top, p.sampling(), &p, bitmap.palette());
mRecorder.drawImage(DrawImagePayload(payload), left, top, p.sampling(), &p);
},
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
// when this function ends.
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
mDisplayList->mMutableImages.push_back(image.get());
}
handleMutableImages(bitmap, payload);
}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) {
SkAutoCanvasRestore acr(&mRecorder, true);
concat(matrix);
sk_sp<SkImage> image = bitmap.makeImage();
auto payload = DrawImagePayload(bitmap);
applyLooper(
paint,
[&](const Paint& p) {
mRecorder.drawImage(image, 0, 0, p.sampling(), &p, bitmap.palette());
mRecorder.drawImage(DrawImagePayload(payload), 0, 0, p.sampling(), &p);
},
FilterForImage);
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
mDisplayList->mMutableImages.push_back(image.get());
}
handleMutableImages(bitmap, payload);
}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
@@ -250,20 +262,17 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
sk_sp<SkImage> image = bitmap.makeImage();
auto payload = DrawImagePayload(bitmap);
applyLooper(
paint,
[&](const Paint& p) {
mRecorder.drawImageRect(image, srcRect, dstRect, p.sampling(), &p,
SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
mRecorder.drawImageRect(DrawImagePayload(payload), srcRect, dstRect, p.sampling(),
&p, SkCanvas::kFast_SrcRectConstraint);
},
FilterForImage);
if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
!dstRect.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
}
handleMutableImages(bitmap, payload);
}
void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
@@ -291,7 +300,7 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
sk_sp<SkImage> image = bitmap.makeImage();
auto payload = DrawImagePayload(bitmap);
// HWUI always draws 9-patches with linear filtering, regardless of the Paint.
const SkFilterMode filter = SkFilterMode::kLinear;
@@ -299,13 +308,11 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
applyLooper(
paint,
[&](const SkPaint& p) {
mRecorder.drawImageLattice(image, lattice, dst, filter, &p, bitmap.palette());
mRecorder.drawImageLattice(DrawImagePayload(payload), lattice, dst, filter, &p);
},
FilterForImage);
if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
}
handleMutableImages(bitmap, payload);
}
double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedImage) {

View File

@@ -102,6 +102,8 @@ private:
*/
void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
void handleMutableImages(Bitmap& bitmap, DrawImagePayload& payload);
using INHERITED = SkiaCanvas;
};