Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 115195e3 authored by John Reck's avatar John Reck
Browse files

Draw gainmaps in HDR

Test: manual
Bug: 266628247
Change-Id: Iad0234089913637f9cddcb39d8fc32badabf3865
parent 255dc584
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+80 −53
Original line number Diff line number Diff line
@@ -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,6 +45,7 @@
#include "SkVertices.h"
#include "Tonemapper.h"
#include "VectorDrawable.h"
#include "effects/GainmapRenderer.h"
#include "include/gpu/GpuTypes.h"  // from Skia
#include "include/gpu/GrDirectContext.h"
#include "pipeline/skia/AnimatedDrawables.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 {
        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 {
        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],
+47 −20
Original line number Diff line number Diff line
@@ -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;
+64 −0
Original line number Diff line number Diff line
/*
 * 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
 No newline at end of file
+33 −0
Original line number Diff line number Diff line
/*
 * 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
Loading