blob: 36bfb1e7d6e153de446c4e06744a755bef19749c [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
bungemanf3c15b72015-08-19 11:56:48 -07007
8#include "SkBitmapProcShader.h"
9#include "SkBitmapProcState.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkColorPriv.h"
bungemanf3c15b72015-08-19 11:56:48 -070011#include "SkErrorInternals.h"
12#include "SkPixelRef.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000013#include "SkReadBuffer.h"
14#include "SkWriteBuffer.h"
humper@google.com3aad3b02013-09-04 19:23:53 +000015
humper@google.com30df03c2013-09-04 19:57:11 +000016#if SK_SUPPORT_GPU
humper@google.com3aad3b02013-09-04 19:23:53 +000017#include "effects/GrBicubicEffect.h"
bsalomonc21b09e2015-08-28 18:46:56 -070018#include "effects/GrExtractAlphaFragmentProcessor.h"
bungemanf3c15b72015-08-19 11:56:48 -070019#include "effects/GrSimpleTextureEffect.h"
humper@google.com30df03c2013-09-04 19:57:11 +000020#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +000021
reed7a4d8472015-09-15 13:33:58 -070022size_t SkBitmapProcShader::ContextSize() {
23 // The SkBitmapProcState is stored outside of the context object, with the context holding
24 // a pointer to it.
25 return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
26}
27
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +000028SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
29 const SkMatrix* localMatrix)
30 : INHERITED(localMatrix) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031 fRawBitmap = src;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000032 fTileModeX = (uint8_t)tmx;
33 fTileModeY = (uint8_t)tmy;
reed@android.com8a1c16f2008-12-17 15:59:43 +000034}
35
reed0f0af232015-09-08 11:02:04 -070036bool SkBitmapProcShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode xy[]) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 if (texture) {
38 *texture = fRawBitmap;
39 }
40 if (texM) {
41 texM->reset();
42 }
43 if (xy) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000044 xy[0] = (TileMode)fTileModeX;
45 xy[1] = (TileMode)fTileModeY;
reed@android.com8a1c16f2008-12-17 15:59:43 +000046 }
reed0f0af232015-09-08 11:02:04 -070047 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
reed9fa60da2014-08-21 07:59:51 -070050SkFlattenable* SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) {
51 SkMatrix lm;
52 buffer.readMatrix(&lm);
53 SkBitmap bm;
54 if (!buffer.readBitmap(&bm)) {
halcanary96fcdcc2015-08-27 07:41:13 -070055 return nullptr;
reed9fa60da2014-08-21 07:59:51 -070056 }
57 bm.setImmutable();
58 TileMode mx = (TileMode)buffer.readUInt();
59 TileMode my = (TileMode)buffer.readUInt();
60 return SkShader::CreateBitmapShader(bm, mx, my, &lm);
61}
reed@android.com8a1c16f2008-12-17 15:59:43 +000062
reed9fa60da2014-08-21 07:59:51 -070063void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const {
64 buffer.writeMatrix(this->getLocalMatrix());
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000065 buffer.writeBitmap(fRawBitmap);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000066 buffer.writeUInt(fTileModeX);
67 buffer.writeUInt(fTileModeY);
reed@android.com8a1c16f2008-12-17 15:59:43 +000068}
69
reed@android.com5119bdb2009-06-12 21:27:03 +000070static bool only_scale_and_translate(const SkMatrix& matrix) {
71 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
72 return (matrix.getType() & ~mask) == 0;
73}
74
junov@chromium.orgb6e16192011-12-09 15:48:03 +000075bool SkBitmapProcShader::isOpaque() const {
76 return fRawBitmap.isOpaque();
77}
78
reed7a4d8472015-09-15 13:33:58 -070079SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader,
80 TileMode tmx, TileMode tmy,
81 const SkBitmap& bitmap,
82 const ContextRec& rec, void* storage) {
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +000083 SkMatrix totalInverse;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000084 // Do this first, so we know the matrix can be inverted.
reed7a4d8472015-09-15 13:33:58 -070085 if (!shader.computeTotalInverse(rec, &totalInverse)) {
halcanary96fcdcc2015-08-27 07:41:13 -070086 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 }
skia.committer@gmail.comedda70e2014-05-06 03:06:53 +000088
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +000089 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
reed7a4d8472015-09-15 13:33:58 -070090 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(SkBitmapProvider(bitmap),
91 tmx, tmy);
reed@android.com8a1c16f2008-12-17 15:59:43 +000092
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000093 SkASSERT(state);
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +000094 if (!state->chooseProcs(totalInverse, *rec.fPaint)) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000095 state->~SkBitmapProcState();
halcanary96fcdcc2015-08-27 07:41:13 -070096 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000097 }
98
reed7a4d8472015-09-15 13:33:58 -070099 return new (storage) BitmapProcShaderContext(shader, rec, state);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000100}
101
reed7a4d8472015-09-15 13:33:58 -0700102SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
103 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, fRawBitmap, rec, storage);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000104}
105
reed7a4d8472015-09-15 13:33:58 -0700106SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(const SkShader& shader,
107 const ContextRec& rec,
108 SkBitmapProcState* state)
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000109 : INHERITED(shader, rec)
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000110 , fState(state)
111{
reedad7ae6c2015-06-04 14:12:25 -0700112 const SkPixmap& pixmap = fState->fPixmap;
113 bool isOpaque = pixmap.isOpaque();
reed@google.com7c2f27d2011-03-07 19:29:00 +0000114
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115 // update fFlags
reed@android.comcafc9f92009-08-22 03:44:57 +0000116 uint32_t flags = 0;
reedad7ae6c2015-06-04 14:12:25 -0700117 if (isOpaque && (255 == this->getPaintAlpha())) {
reed@android.comcafc9f92009-08-22 03:44:57 +0000118 flags |= kOpaqueAlpha_Flag;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119 }
120
reedad7ae6c2015-06-04 14:12:25 -0700121 switch (pixmap.colorType()) {
reed@google.com900ecf22014-02-20 20:55:37 +0000122 case kRGB_565_SkColorType:
reed@android.comcafc9f92009-08-22 03:44:57 +0000123 flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 break;
reed@google.com900ecf22014-02-20 20:55:37 +0000125 case kIndex_8_SkColorType:
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000126 case kN32_SkColorType:
reedad7ae6c2015-06-04 14:12:25 -0700127 if (isOpaque) {
reed@android.comcafc9f92009-08-22 03:44:57 +0000128 flags |= kHasSpan16_Flag;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 }
130 break;
reed@google.com900ecf22014-02-20 20:55:37 +0000131 case kAlpha_8_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 break; // never set kHasSpan16_Flag
133 default:
134 break;
135 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000136
reedad7ae6c2015-06-04 14:12:25 -0700137 if (rec.fPaint->isDither() && pixmap.colorType() != kRGB_565_SkColorType) {
reed@android.comcafc9f92009-08-22 03:44:57 +0000138 // gradients can auto-dither in their 16bit sampler, but we don't so
reed@android.com7f6e1e92009-10-14 21:06:29 +0000139 // we clear the flag here.
reed@android.comcafc9f92009-08-22 03:44:57 +0000140 flags &= ~kHasSpan16_Flag;
141 }
142
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000143 // if we're only 1-pixel high, and we don't rotate, then we can claim this
reedad7ae6c2015-06-04 14:12:25 -0700144 if (1 == pixmap.height() &&
reed@android.com5119bdb2009-06-12 21:27:03 +0000145 only_scale_and_translate(this->getTotalInverse())) {
reed@android.com3c9b2a42009-08-27 19:28:37 +0000146 flags |= kConstInY32_Flag;
147 if (flags & kHasSpan16_Flag) {
148 flags |= kConstInY16_Flag;
149 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000150 }
reed@android.comcafc9f92009-08-22 03:44:57 +0000151
152 fFlags = flags;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153}
154
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000155SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() {
156 // The bitmap proc state has been created outside of the context on memory that will be freed
157 // elsewhere. Only call the destructor but leave the freeing of the memory to the caller.
158 fState->~SkBitmapProcState();
reed@google.coma641f3f2012-12-13 22:16:30 +0000159}
160
commit-bot@chromium.orgf21991b2014-05-23 19:13:56 +0000161#define BUF_MAX 128
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162
reed@android.com258cb222010-04-14 13:36:33 +0000163#define TEST_BUFFER_OVERRITEx
164
165#ifdef TEST_BUFFER_OVERRITE
166 #define TEST_BUFFER_EXTRA 32
commit-bot@chromium.orgf21991b2014-05-23 19:13:56 +0000167 #define TEST_PATTERN 0x88888888
reed@android.com258cb222010-04-14 13:36:33 +0000168#else
169 #define TEST_BUFFER_EXTRA 0
170#endif
171
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000172void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMColor dstC[],
173 int count) {
174 const SkBitmapProcState& state = *fState;
reed@google.com9fe287b2012-03-27 15:54:28 +0000175 if (state.getShaderProc32()) {
176 state.getShaderProc32()(state, x, y, dstC, count);
reed@android.com7a99eb12009-07-16 01:13:14 +0000177 return;
178 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179
commit-bot@chromium.orgf21991b2014-05-23 19:13:56 +0000180 uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
reed@google.com9fe287b2012-03-27 15:54:28 +0000181 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
182 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000183 int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184
reedad7ae6c2015-06-04 14:12:25 -0700185 SkASSERT(state.fPixmap.addr());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186
187 for (;;) {
188 int n = count;
189 if (n > max) {
190 n = max;
191 }
reed@android.com258cb222010-04-14 13:36:33 +0000192 SkASSERT(n > 0 && n < BUF_MAX*2);
193#ifdef TEST_BUFFER_OVERRITE
194 for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
195 buffer[BUF_MAX + i] = TEST_PATTERN;
196 }
197#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198 mproc(state, buffer, n, x, y);
reed@android.com258cb222010-04-14 13:36:33 +0000199#ifdef TEST_BUFFER_OVERRITE
200 for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
201 SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
202 }
203#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204 sproc(state, buffer, n, dstC);
reed@google.com7c2f27d2011-03-07 19:29:00 +0000205
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206 if ((count -= n) == 0) {
207 break;
208 }
reed@android.com258cb222010-04-14 13:36:33 +0000209 SkASSERT(count > 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 x += n;
211 dstC += n;
212 }
213}
214
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000215SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asAShadeProc(void** ctx) {
216 if (fState->getShaderProc32()) {
217 *ctx = fState;
218 return (ShadeProc)fState->getShaderProc32();
reed@google.com3bafe742012-10-12 18:56:18 +0000219 }
halcanary96fcdcc2015-08-27 07:41:13 -0700220 return nullptr;
reed@google.com3bafe742012-10-12 18:56:18 +0000221}
222
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000223void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan16(int x, int y, uint16_t dstC[],
224 int count) {
225 const SkBitmapProcState& state = *fState;
reed@google.com9fe287b2012-03-27 15:54:28 +0000226 if (state.getShaderProc16()) {
227 state.getShaderProc16()(state, x, y, dstC, count);
reed@android.com7a99eb12009-07-16 01:13:14 +0000228 return;
229 }
reed@google.com7c2f27d2011-03-07 19:29:00 +0000230
commit-bot@chromium.orgf21991b2014-05-23 19:13:56 +0000231 uint32_t buffer[BUF_MAX];
reed@google.com9fe287b2012-03-27 15:54:28 +0000232 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
233 SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000234 int max = state.maxCountForBufferSize(sizeof(buffer));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000235
reedad7ae6c2015-06-04 14:12:25 -0700236 SkASSERT(state.fPixmap.addr());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237
238 for (;;) {
239 int n = count;
240 if (n > max) {
241 n = max;
242 }
243 mproc(state, buffer, n, x, y);
244 sproc(state, buffer, n, dstC);
reed@google.com7c2f27d2011-03-07 19:29:00 +0000245
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246 if ((count -= n) == 0) {
247 break;
248 }
249 x += n;
250 dstC += n;
251 }
252}
253
254///////////////////////////////////////////////////////////////////////////////
255
reed@android.comc6459962009-08-25 19:15:31 +0000256#include "SkUnPreMultiply.h"
257#include "SkColorShader.h"
reed@google.com37a20122011-07-05 18:54:12 +0000258#include "SkEmptyShader.h"
reed@android.comc6459962009-08-25 19:15:31 +0000259
260// returns true and set color if the bitmap can be drawn as a single color
261// (for efficiency)
robertphillips5f865b92015-07-29 12:28:04 -0700262static bool can_use_color_shader(const SkBitmap& bm, SkColor* color) {
djsollenab51cbd2015-07-14 10:59:28 -0700263#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
264 // HWUI does not support color shaders (see b/22390304)
265 return false;
266#endif
267
reed@android.comc6459962009-08-25 19:15:31 +0000268 if (1 != bm.width() || 1 != bm.height()) {
269 return false;
270 }
271
272 SkAutoLockPixels alp(bm);
273 if (!bm.readyToDraw()) {
274 return false;
275 }
276
reed@google.com900ecf22014-02-20 20:55:37 +0000277 switch (bm.colorType()) {
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +0000278 case kN32_SkColorType:
reed@android.comc6459962009-08-25 19:15:31 +0000279 *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
280 return true;
reed@google.com900ecf22014-02-20 20:55:37 +0000281 case kRGB_565_SkColorType:
reed@android.comc6459962009-08-25 19:15:31 +0000282 *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
283 return true;
reed@google.com900ecf22014-02-20 20:55:37 +0000284 case kIndex_8_SkColorType:
reed@android.comc6459962009-08-25 19:15:31 +0000285 *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
286 return true;
287 default: // just skip the other configs for now
288 break;
289 }
290 return false;
291}
292
robertphillips5f865b92015-07-29 12:28:04 -0700293static bool bitmap_is_too_big(const SkBitmap& bm) {
reed@google.com99c114e2012-05-03 20:14:26 +0000294 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
295 // communicates between its matrix-proc and its sampler-proc. Until we can
296 // widen that, we have to reject bitmaps that are larger.
297 //
robertphillips5f865b92015-07-29 12:28:04 -0700298 static const int kMaxSize = 65535;
reed@google.com99c114e2012-05-03 20:14:26 +0000299
robertphillips5f865b92015-07-29 12:28:04 -0700300 return bm.width() > kMaxSize || bm.height() > kMaxSize;
reed@google.com99c114e2012-05-03 20:14:26 +0000301}
302
mtklein7ef849d2014-11-24 09:11:45 -0800303SkShader* SkCreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
304 SkShader::TileMode tmy, const SkMatrix* localMatrix,
305 SkTBlitterAllocator* allocator) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000306 SkShader* shader;
reed@android.comc6459962009-08-25 19:15:31 +0000307 SkColor color;
robertphillips5f865b92015-07-29 12:28:04 -0700308 if (src.isNull() || bitmap_is_too_big(src)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700309 if (nullptr == allocator) {
halcanary385fe4d2015-08-26 13:07:48 -0700310 shader = new SkEmptyShader;
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000311 } else {
312 shader = allocator->createT<SkEmptyShader>();
313 }
robertphillips5f865b92015-07-29 12:28:04 -0700314 } else if (can_use_color_shader(src, &color)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700315 if (nullptr == allocator) {
halcanary385fe4d2015-08-26 13:07:48 -0700316 shader = new SkColorShader(color);
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000317 } else {
318 shader = allocator->createT<SkColorShader>(color);
319 }
reed@android.comc6459962009-08-25 19:15:31 +0000320 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700321 if (nullptr == allocator) {
halcanary385fe4d2015-08-26 13:07:48 -0700322 shader = new SkBitmapProcShader(src, tmx, tmy, localMatrix);
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000323 } else {
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000324 shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, localMatrix);
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000325 }
reed@android.comc6459962009-08-25 19:15:31 +0000326 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000327 return shader;
328}
329
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330///////////////////////////////////////////////////////////////////////////////
331
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000332#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000333void SkBitmapProcShader::toString(SkString* str) const {
334 static const char* gTileModeName[SkShader::kTileModeCount] = {
335 "clamp", "repeat", "mirror"
336 };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000337
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000338 str->append("BitmapShader: (");
reed@google.com7c2f27d2011-03-07 19:29:00 +0000339
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000340 str->appendf("(%s, %s)",
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000341 gTileModeName[fTileModeX],
342 gTileModeName[fTileModeY]);
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000343
344 str->append(" ");
345 fRawBitmap.toString(str);
346
347 this->INHERITED::toString(str);
348
349 str->append(")");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350}
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000351#endif
352
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000353///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000354
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000355#if SK_SUPPORT_GPU
356
357#include "GrTextureAccess.h"
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000358#include "SkGr.h"
joshualitt9bc39542015-08-12 12:57:54 -0700359#include "effects/GrSimpleTextureEffect.h"
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000360
bsalomonc21b09e2015-08-28 18:46:56 -0700361const GrFragmentProcessor* SkBitmapProcShader::asFragmentProcessor(GrContext* context,
362 const SkMatrix& viewM, const SkMatrix* localMatrix,
363 SkFilterQuality filterQuality,
364 GrProcessorDataManager* procDataManager) const {
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000365 SkMatrix matrix;
366 matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
367
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000368 SkMatrix lmInverse;
369 if (!this->getLocalMatrix().invert(&lmInverse)) {
bsalomonc21b09e2015-08-28 18:46:56 -0700370 return nullptr;
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000371 }
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +0000372 if (localMatrix) {
373 SkMatrix inv;
374 if (!localMatrix->invert(&inv)) {
bsalomonc21b09e2015-08-28 18:46:56 -0700375 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +0000376 }
377 lmInverse.postConcat(inv);
378 }
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000379 matrix.preConcat(lmInverse);
commit-bot@chromium.orgcea9abb2013-12-09 19:15:37 +0000380
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000381 SkShader::TileMode tm[] = {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000382 (TileMode)fTileModeX,
383 (TileMode)fTileModeY,
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000384 };
385
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000386 // Must set wrap and filter on the sampler before requesting a texture. In two places below
387 // we check the matrix scale factors to determine how to interpret the filter quality setting.
388 // This completely ignores the complexity of the drawVertices case where explicit local coords
389 // are provided by the caller.
joshualitt9bc39542015-08-12 12:57:54 -0700390 bool doBicubic;
391 GrTextureParams::FilterMode textureFilterMode =
bsalomonc21b09e2015-08-28 18:46:56 -0700392 GrSkFilterQualityToGrFilterMode(filterQuality, viewM, this->getLocalMatrix(),
joshualitt9bc39542015-08-12 12:57:54 -0700393 &doBicubic);
humper@google.comb86add12013-07-25 18:49:07 +0000394 GrTextureParams params(tm, textureFilterMode);
bsalomonbcf0a522014-10-08 08:40:09 -0700395 SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, fRawBitmap, &params));
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000396
bsalomonbcf0a522014-10-08 08:40:09 -0700397 if (!texture) {
humper@google.com3aad3b02013-09-04 19:23:53 +0000398 SkErrorInternals::SetError( kInternalError_SkError,
399 "Couldn't convert bitmap to texture.");
bsalomonc21b09e2015-08-28 18:46:56 -0700400 return nullptr;
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000401 }
mtklein7ef849d2014-11-24 09:11:45 -0800402
bsalomonc21b09e2015-08-28 18:46:56 -0700403 SkAutoTUnref<GrFragmentProcessor> inner;
joshualitt9bc39542015-08-12 12:57:54 -0700404 if (doBicubic) {
bsalomonc21b09e2015-08-28 18:46:56 -0700405 inner.reset(GrBicubicEffect::Create(procDataManager, texture, matrix, tm));
humper@google.com3aad3b02013-09-04 19:23:53 +0000406 } else {
bsalomonc21b09e2015-08-28 18:46:56 -0700407 inner.reset(GrSimpleTextureEffect::Create(procDataManager, texture, matrix, params));
humper@google.com3aad3b02013-09-04 19:23:53 +0000408 }
dandov9de5b512014-06-10 14:38:28 -0700409
bsalomonc21b09e2015-08-28 18:46:56 -0700410 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) {
411 return SkRef(inner.get());
412 }
413 return GrExtractAlphaFragmentProcessor::Create(inner);
dandov9de5b512014-06-10 14:38:28 -0700414}
415
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000416#endif