blob: e7a8433fe24d895745f33a639480be626b0124b8 [file] [log] [blame]
reed856e9d92015-09-30 12:21:45 -07001/*
2 * Copyright 2015 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 "SkBitmapProcShader.h"
9#include "SkBitmapProvider.h"
10#include "SkImage_Base.h"
11#include "SkImageShader.h"
12#include "SkReadBuffer.h"
13#include "SkWriteBuffer.h"
14
15SkImageShader::SkImageShader(const SkImage* img, TileMode tmx, TileMode tmy, const SkMatrix* matrix)
16 : INHERITED(matrix)
17 , fImage(SkRef(img))
18 , fTileModeX(tmx)
19 , fTileModeY(tmy)
20{}
21
reed60c9b582016-04-03 09:11:13 -070022sk_sp<SkFlattenable> SkImageShader::CreateProc(SkReadBuffer& buffer) {
reed856e9d92015-09-30 12:21:45 -070023 const TileMode tx = (TileMode)buffer.readUInt();
24 const TileMode ty = (TileMode)buffer.readUInt();
25 SkMatrix matrix;
26 buffer.readMatrix(&matrix);
27 SkAutoTUnref<SkImage> img(buffer.readImage());
28 if (!img) {
29 return nullptr;
30 }
reed60c9b582016-04-03 09:11:13 -070031 return SkImageShader::Make(img, tx, ty, &matrix);
reed856e9d92015-09-30 12:21:45 -070032}
33
34void SkImageShader::flatten(SkWriteBuffer& buffer) const {
35 buffer.writeUInt(fTileModeX);
36 buffer.writeUInt(fTileModeY);
37 buffer.writeMatrix(this->getLocalMatrix());
38 buffer.writeImage(fImage);
39}
40
41bool SkImageShader::isOpaque() const {
42 return fImage->isOpaque();
43}
44
reed773ceda2016-03-03 18:18:25 -080045size_t SkImageShader::onContextSize(const ContextRec& rec) const {
reedd8829012016-03-04 11:07:43 -080046 return SkBitmapProcShader::ContextSize(rec, SkBitmapProvider(fImage).info());
reed856e9d92015-09-30 12:21:45 -070047}
48
49SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const {
50 return SkBitmapProcShader::MakeContext(*this, fTileModeX, fTileModeY,
51 SkBitmapProvider(fImage), rec, storage);
52}
53
reed5671c5b2016-03-09 14:47:34 -080054sk_sp<SkShader> SkImageShader::Make(const SkImage* image, TileMode tx, TileMode ty,
55 const SkMatrix* localMatrix) {
reed856e9d92015-09-30 12:21:45 -070056 if (!image) {
57 return nullptr;
58 }
reed5671c5b2016-03-09 14:47:34 -080059 return sk_sp<SkShader>(new SkImageShader(image, tx, ty, localMatrix));
reed856e9d92015-09-30 12:21:45 -070060}
61
62#ifndef SK_IGNORE_TO_STRING
63void SkImageShader::toString(SkString* str) const {
64 const char* gTileModeName[SkShader::kTileModeCount] = {
65 "clamp", "repeat", "mirror"
66 };
67
68 str->appendf("ImageShader: ((%s %s) ", gTileModeName[fTileModeX], gTileModeName[fTileModeY]);
69 fImage->toString(str);
70 this->INHERITED::toString(str);
71 str->append(")");
72}
73#endif
74
75///////////////////////////////////////////////////////////////////////////////////////////////////
76
77#if SK_SUPPORT_GPU
78
79#include "GrTextureAccess.h"
80#include "SkGr.h"
bsalomonf276ac52015-10-09 13:36:42 -070081#include "SkGrPriv.h"
reed856e9d92015-09-30 12:21:45 -070082#include "effects/GrSimpleTextureEffect.h"
83#include "effects/GrBicubicEffect.h"
84#include "effects/GrSimpleTextureEffect.h"
85
brianosman839345d2016-07-22 11:04:53 -070086sk_sp<GrFragmentProcessor> SkImageShader::asFragmentProcessor(const AsFPArgs& args) const {
reed856e9d92015-09-30 12:21:45 -070087 SkMatrix matrix;
88 matrix.setIDiv(fImage->width(), fImage->height());
89
90 SkMatrix lmInverse;
91 if (!this->getLocalMatrix().invert(&lmInverse)) {
92 return nullptr;
93 }
brianosman839345d2016-07-22 11:04:53 -070094 if (args.fLocalMatrix) {
reed856e9d92015-09-30 12:21:45 -070095 SkMatrix inv;
brianosman839345d2016-07-22 11:04:53 -070096 if (!args.fLocalMatrix->invert(&inv)) {
reed856e9d92015-09-30 12:21:45 -070097 return nullptr;
98 }
99 lmInverse.postConcat(inv);
100 }
101 matrix.preConcat(lmInverse);
102
103 SkShader::TileMode tm[] = { fTileModeX, fTileModeY };
104
105 // Must set wrap and filter on the sampler before requesting a texture. In two places below
106 // we check the matrix scale factors to determine how to interpret the filter quality setting.
107 // This completely ignores the complexity of the drawVertices case where explicit local coords
108 // are provided by the caller.
109 bool doBicubic;
110 GrTextureParams::FilterMode textureFilterMode =
brianosman839345d2016-07-22 11:04:53 -0700111 GrSkFilterQualityToGrFilterMode(args.fFilterQuality, *args.fViewMatrix, this->getLocalMatrix(),
112 &doBicubic);
reed856e9d92015-09-30 12:21:45 -0700113 GrTextureParams params(tm, textureFilterMode);
brianosman839345d2016-07-22 11:04:53 -0700114 SkAutoTUnref<GrTexture> texture(as_IB(fImage)->asTextureRef(args.fContext, params,
115 args.fGammaTreatment));
reed856e9d92015-09-30 12:21:45 -0700116 if (!texture) {
117 return nullptr;
118 }
119
bungeman06ca8ec2016-06-09 08:01:03 -0700120 sk_sp<GrFragmentProcessor> inner;
reed856e9d92015-09-30 12:21:45 -0700121 if (doBicubic) {
brianosman54f30c12016-07-18 10:53:52 -0700122 inner = GrBicubicEffect::Make(texture, nullptr, matrix, tm);
reed856e9d92015-09-30 12:21:45 -0700123 } else {
brianosman54f30c12016-07-18 10:53:52 -0700124 inner = GrSimpleTextureEffect::Make(texture, nullptr, matrix, params);
reed856e9d92015-09-30 12:21:45 -0700125 }
126
127 if (GrPixelConfigIsAlphaOnly(texture->config())) {
bungeman06ca8ec2016-06-09 08:01:03 -0700128 return inner;
reed856e9d92015-09-30 12:21:45 -0700129 }
bungeman06ca8ec2016-06-09 08:01:03 -0700130 return sk_sp<GrFragmentProcessor>(GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)));
reed856e9d92015-09-30 12:21:45 -0700131}
132
133#endif