skia2/src/core/SkPictureImageGenerator.cpp
Brian Osman e1552a5914 Always require a color space on picture-backed images
Now that picture backed images always play back their contents to a
tagged surface, we can always construct them with either the destination
surface color space or the xform canvas color space, and get the same
results. To ensure that they always behave sensibly, fallback to sRGB if
neither color space is present.

With those changes, the caching and setup can be much simpler: the
source of the color space is irrelevant. Also, switch to using our new
hash data, rather than the suspicious caching based on pointers.

Finally, now that we enforce a color space on all of these generators,
the back-door factory can go away, along with the header.

PS: Fix a spelling error.

Bug: skia:
Change-Id: I40fd2d35f2b3e6f8a1657d47f57127adacb80a80
Reviewed-on: https://skia-review.googlesource.com/c/163249
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
2018-10-18 15:13:39 +00:00

120 lines
4.1 KiB
C++

/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkImage_Base.h"
#include "SkImageGenerator.h"
#include "SkCanvas.h"
#include "SkMakeUnique.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkSurface.h"
#include "SkTLazy.h"
class SkPictureImageGenerator : public SkImageGenerator {
public:
SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture>, const SkMatrix*,
const SkPaint*);
protected:
bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options& opts)
override;
#if SK_SUPPORT_GPU
TexGenType onCanGenerateTexture() const override { return TexGenType::kExpensive; }
sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
bool willNeedMipMaps) override;
#endif
private:
sk_sp<SkPicture> fPicture;
SkMatrix fMatrix;
SkTLazy<SkPaint> fPaint;
typedef SkImageGenerator INHERITED;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<SkImageGenerator>
SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
const SkMatrix* matrix, const SkPaint* paint,
SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
if (!picture || !colorSpace || size.isEmpty()) {
return nullptr;
}
SkColorType colorType = kN32_SkColorType;
if (SkImage::BitDepth::kF16 == bitDepth) {
colorType = kRGBA_F16_SkColorType;
}
SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType,
kPremul_SkAlphaType, std::move(colorSpace));
return std::unique_ptr<SkImageGenerator>(
new SkPictureImageGenerator(info, std::move(picture), matrix, paint));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
const SkMatrix* matrix, const SkPaint* paint)
: INHERITED(info)
, fPicture(std::move(picture)) {
if (matrix) {
fMatrix = *matrix;
} else {
fMatrix.reset();
}
if (paint) {
fPaint.set(*paint);
}
}
bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
const Options& opts) {
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, rowBytes, &props);
if (!canvas) {
return false;
}
canvas->clear(0);
canvas->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
sk_sp<GrTextureProxy> SkPictureImageGenerator::onGenerateTexture(
GrContext* ctx, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
SkASSERT(ctx);
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, info, 0,
kTopLeft_GrSurfaceOrigin, &props,
willNeedMipMaps));
if (!surface) {
return nullptr;
}
SkMatrix matrix = fMatrix;
matrix.postTranslate(-origin.x(), -origin.y());
surface->getCanvas()->clear(0);
surface->getCanvas()->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
sk_sp<SkImage> image(surface->makeImageSnapshot());
if (!image) {
return nullptr;
}
sk_sp<GrTextureProxy> proxy = as_IB(image)->asTextureProxyRef();
SkASSERT(!willNeedMipMaps || GrMipMapped::kYes == proxy->mipMapped());
return proxy;
}
#endif