blob: bf1275ed6c0d0ef8cc841ee9083009748e0a14d2 [file] [log] [blame]
Matt Sarett3928ff82017-06-06 10:11:34 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkColorSpaceXformImageGenerator.h"
9
10std::unique_ptr<SkImageGenerator> SkColorSpaceXformImageGenerator::Make(
11 const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode mode) {
Matt Sarettdc792702017-06-08 09:37:01 -040012 return SkColorSpaceXformImageGenerator::Make(src, dst, mode, kNeedNewImageUniqueID);
13}
14
15std::unique_ptr<SkImageGenerator> SkColorSpaceXformImageGenerator::Make(
16 const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode mode, uint32_t id) {
Matt Sarett3928ff82017-06-06 10:11:34 -040017 if (!dst) {
18 return nullptr;
19 }
20
21 const SkBitmap* srcPtr = &src;
22 SkBitmap copy;
23 if (kAlways_SkCopyPixelsMode == mode ||
24 (kNever_SkCopyPixelsMode != mode && !src.isImmutable())) {
25 if (!copy.tryAllocPixels(src.info())) {
26 return nullptr;
27 }
28
29 SkAssertResult(src.readPixels(copy.info(), copy.getPixels(), copy.rowBytes(), 0, 0));
30 copy.setImmutable();
31 srcPtr = &copy;
32 }
33
Matt Sarett3928ff82017-06-06 10:11:34 -040034 return std::unique_ptr<SkImageGenerator>(
Matt Sarettdc792702017-06-08 09:37:01 -040035 new SkColorSpaceXformImageGenerator(*srcPtr, std::move(dst), id));
Matt Sarett3928ff82017-06-06 10:11:34 -040036}
37
38SkColorSpaceXformImageGenerator::SkColorSpaceXformImageGenerator(const SkBitmap& src,
Matt Sarettdc792702017-06-08 09:37:01 -040039 sk_sp<SkColorSpace> dst,
40 uint32_t id)
41 : INHERITED(src.info().makeColorSpace(dst), id)
Matt Sarett3928ff82017-06-06 10:11:34 -040042 , fSrc(src)
Mike Klein72f1a452017-06-06 19:23:03 -040043 , fDst(std::move(dst))
Matt Sarett3928ff82017-06-06 10:11:34 -040044{}
45
46bool SkColorSpaceXformImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels,
47 size_t rowBytes, const Options& opts) {
48 SkImageInfo dstInfo = info;
49 if (!info.colorSpace()) {
50 dstInfo = dstInfo.makeColorSpace(fDst);
51 }
52 return fSrc.readPixels(dstInfo, pixels, rowBytes, 0, 0, opts.fBehavior);
53}
54
55#if SK_SUPPORT_GPU
56
57#include "GrClip.h"
58#include "GrContext.h"
59#include "GrPaint.h"
60#include "GrRenderTargetContext.h"
61#include "GrTextureProxy.h"
62#include "SkGr.h"
63#include "effects/GrNonlinearColorSpaceXformEffect.h"
64
Christopher Cameron77e96662017-07-08 01:47:47 -070065sk_sp<GrTextureProxy> SkColorSpaceXformImageGenerator::onGenerateTexture(
66 GrContext* ctx, const SkImageInfo& info, const SkIPoint& origin,
67 SkTransferFunctionBehavior) {
Matt Sarett3928ff82017-06-06 10:11:34 -040068 // FIXME:
69 // This always operates as if SkTranferFunctionBehavior is kIgnore. Should we add
70 // options so that caller can also request kRespect?
71
72 SkASSERT(ctx);
73
Robert Phillipsfbcef6e2017-06-15 12:07:18 -040074 sk_sp<GrTextureProxy> proxy = GrUploadBitmapToTextureProxy(ctx->resourceProvider(),
75 fSrc, nullptr);
Matt Sarett3928ff82017-06-06 10:11:34 -040076
Brian Salomon8fe24272017-07-07 12:56:11 -040077 if (!proxy) {
78 return nullptr;
79 }
80
Matt Sarett3928ff82017-06-06 10:11:34 -040081 sk_sp<SkColorSpace> srcSpace =
82 fSrc.colorSpace() ? sk_ref_sp(fSrc.colorSpace()) : SkColorSpace::MakeSRGB();
83 auto xform = GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), fDst.get());
84 if (!xform) {
85 return nullptr;
86 }
87
88 sk_sp<GrRenderTargetContext> renderTargetContext = ctx->makeDeferredRenderTargetContext(
Brian Salomondd5ef782017-08-18 13:56:20 -040089 SkBackingFit::kExact, info.width(), info.height(), kRGBA_8888_GrPixelConfig, nullptr,
Robert Phillipse44ef102017-07-21 15:37:19 -040090 0, kTopLeft_GrSurfaceOrigin);
Matt Sarett3928ff82017-06-06 10:11:34 -040091 if (!renderTargetContext) {
92 return nullptr;
93 }
94
95 GrPaint paint;
96 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -040097 paint.addColorTextureProcessor(std::move(proxy), nullptr,
98 SkMatrix::MakeTrans(origin.fX, origin.fY));
Matt Sarett3928ff82017-06-06 10:11:34 -040099 paint.addColorFragmentProcessor(std::move(xform));
100
101 const SkRect rect = SkRect::MakeWH(info.width(), info.height());
102 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
103 return sk_ref_sp(renderTargetContext->asTextureProxy());
104}
105
106#endif