blob: 9c2c77b9506c6fd0f8107df5fe297d845abddaa9 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkColorPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +00009#include "SkReadBuffer.h"
10#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000011#include "SkPixelRef.h"
humper@google.comb86add12013-07-25 18:49:07 +000012#include "SkErrorInternals.h"
humper@google.com3aad3b02013-09-04 19:23:53 +000013#include "SkBitmapProcShader.h"
14
humper@google.com30df03c2013-09-04 19:57:11 +000015#if SK_SUPPORT_GPU
humper@google.com3aad3b02013-09-04 19:23:53 +000016#include "effects/GrSimpleTextureEffect.h"
17#include "effects/GrBicubicEffect.h"
humper@google.com30df03c2013-09-04 19:57:11 +000018#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +000019
20bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
reed@google.com900ecf22014-02-20 20:55:37 +000021 switch (bm.colorType()) {
22 case kAlpha_8_SkColorType:
23 case kRGB_565_SkColorType:
24 case kIndex_8_SkColorType:
commit-bot@chromium.org757ebd22014-04-10 22:36:34 +000025 case kPMColor_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +000026 // if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
27 return true;
28 default:
29 break;
30 }
31 return false;
32}
33
34SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
35 TileMode tmx, TileMode tmy) {
36 fRawBitmap = src;
37 fState.fTileModeX = (uint8_t)tmx;
38 fState.fTileModeY = (uint8_t)tmy;
reed@android.com89bb83a2009-05-29 21:30:42 +000039 fFlags = 0; // computed in setContext
reed@android.com8a1c16f2008-12-17 15:59:43 +000040}
41
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000042SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer)
reed@android.com8a1c16f2008-12-17 15:59:43 +000043 : INHERITED(buffer) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000044 buffer.readBitmap(&fRawBitmap);
reed@google.com84239fb2012-12-10 16:10:33 +000045 fRawBitmap.setImmutable();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000046 fState.fTileModeX = buffer.readUInt();
47 fState.fTileModeY = buffer.readUInt();
reed@android.com89bb83a2009-05-29 21:30:42 +000048 fFlags = 0; // computed in setContext
reed@android.com8a1c16f2008-12-17 15:59:43 +000049}
50
reed@google.com7c2f27d2011-03-07 19:29:00 +000051SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
52 SkMatrix* texM,
rileya@google.com91f319c2012-07-25 17:18:31 +000053 TileMode xy[]) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 if (texture) {
55 *texture = fRawBitmap;
56 }
57 if (texM) {
58 texM->reset();
59 }
60 if (xy) {
61 xy[0] = (TileMode)fState.fTileModeX;
62 xy[1] = (TileMode)fState.fTileModeY;
63 }
reed@android.comf2b98d62010-12-20 18:26:13 +000064 return kDefault_BitmapType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000065}
66
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000067void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000068 this->INHERITED::flatten(buffer);
69
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000070 buffer.writeBitmap(fRawBitmap);
71 buffer.writeUInt(fState.fTileModeX);
72 buffer.writeUInt(fState.fTileModeY);
reed@android.com8a1c16f2008-12-17 15:59:43 +000073}
74
reed@android.com5119bdb2009-06-12 21:27:03 +000075static bool only_scale_and_translate(const SkMatrix& matrix) {
76 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
77 return (matrix.getType() & ~mask) == 0;
78}
79
junov@chromium.orgb6e16192011-12-09 15:48:03 +000080bool SkBitmapProcShader::isOpaque() const {
81 return fRawBitmap.isOpaque();
82}
83
reed@google.comcee9dcb2013-09-13 16:04:49 +000084static bool valid_for_drawing(const SkBitmap& bm) {
85 if (0 == bm.width() || 0 == bm.height()) {
86 return false; // nothing to draw
87 }
88 if (NULL == bm.pixelRef()) {
89 return false; // no pixels to read
90 }
reed@google.com900ecf22014-02-20 20:55:37 +000091 if (kIndex_8_SkColorType == bm.colorType()) {
reed@google.comcee9dcb2013-09-13 16:04:49 +000092 // ugh, I have to lock-pixels to inspect the colortable
93 SkAutoLockPixels alp(bm);
94 if (!bm.getColorTable()) {
95 return false;
96 }
97 }
98 return true;
99}
100
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101bool SkBitmapProcShader::setContext(const SkBitmap& device,
102 const SkPaint& paint,
103 const SkMatrix& matrix) {
reed@google.comcee9dcb2013-09-13 16:04:49 +0000104 if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) {
105 return false;
106 }
107
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108 // do this first, so we have a correct inverse matrix
109 if (!this->INHERITED::setContext(device, paint, matrix)) {
110 return false;
111 }
112
113 fState.fOrigBitmap = fRawBitmap;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114 if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
mike@reedtribe.orge7591bb2013-01-15 03:28:22 +0000115 this->INHERITED::endContext();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 return false;
117 }
118
reed@android.com7f6e1e92009-10-14 21:06:29 +0000119 const SkBitmap& bitmap = *fState.fBitmap;
120 bool bitmapIsOpaque = bitmap.isOpaque();
reed@google.com7c2f27d2011-03-07 19:29:00 +0000121
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 // update fFlags
reed@android.comcafc9f92009-08-22 03:44:57 +0000123 uint32_t flags = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
reed@android.comcafc9f92009-08-22 03:44:57 +0000125 flags |= kOpaqueAlpha_Flag;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126 }
127
reed@google.com900ecf22014-02-20 20:55:37 +0000128 switch (bitmap.colorType()) {
129 case kRGB_565_SkColorType:
reed@android.comcafc9f92009-08-22 03:44:57 +0000130 flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 break;
reed@google.com900ecf22014-02-20 20:55:37 +0000132 case kIndex_8_SkColorType:
commit-bot@chromium.org757ebd22014-04-10 22:36:34 +0000133 case kPMColor_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 if (bitmapIsOpaque) {
reed@android.comcafc9f92009-08-22 03:44:57 +0000135 flags |= kHasSpan16_Flag;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 }
137 break;
reed@google.com900ecf22014-02-20 20:55:37 +0000138 case kAlpha_8_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 break; // never set kHasSpan16_Flag
140 default:
141 break;
142 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000143
reed@google.com900ecf22014-02-20 20:55:37 +0000144 if (paint.isDither() && bitmap.colorType() != kRGB_565_SkColorType) {
reed@android.comcafc9f92009-08-22 03:44:57 +0000145 // gradients can auto-dither in their 16bit sampler, but we don't so
reed@android.com7f6e1e92009-10-14 21:06:29 +0000146 // we clear the flag here.
reed@android.comcafc9f92009-08-22 03:44:57 +0000147 flags &= ~kHasSpan16_Flag;
148 }
149
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000150 // if we're only 1-pixel high, and we don't rotate, then we can claim this
reed@android.com7f6e1e92009-10-14 21:06:29 +0000151 if (1 == bitmap.height() &&
reed@android.com5119bdb2009-06-12 21:27:03 +0000152 only_scale_and_translate(this->getTotalInverse())) {
reed@android.com3c9b2a42009-08-27 19:28:37 +0000153 flags |= kConstInY32_Flag;
154 if (flags & kHasSpan16_Flag) {
155 flags |= kConstInY16_Flag;
156 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000157 }
reed@android.comcafc9f92009-08-22 03:44:57 +0000158
159 fFlags = flags;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 return true;
161}
162
reed@google.coma641f3f2012-12-13 22:16:30 +0000163void SkBitmapProcShader::endContext() {
humper@google.com9c96d4b2013-07-14 01:44:59 +0000164 fState.endContext();
reed@google.coma641f3f2012-12-13 22:16:30 +0000165 this->INHERITED::endContext();
166}
167
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168#define BUF_MAX 128
169
reed@android.com258cb222010-04-14 13:36:33 +0000170#define TEST_BUFFER_OVERRITEx
171
172#ifdef TEST_BUFFER_OVERRITE
173 #define TEST_BUFFER_EXTRA 32
174 #define TEST_PATTERN 0x88888888
175#else
176 #define TEST_BUFFER_EXTRA 0
177#endif
178
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
reed@android.com7a99eb12009-07-16 01:13:14 +0000180 const SkBitmapProcState& state = fState;
reed@google.com9fe287b2012-03-27 15:54:28 +0000181 if (state.getShaderProc32()) {
182 state.getShaderProc32()(state, x, y, dstC, count);
reed@android.com7a99eb12009-07-16 01:13:14 +0000183 return;
184 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185
reed@android.com258cb222010-04-14 13:36:33 +0000186 uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
reed@google.com9fe287b2012-03-27 15:54:28 +0000187 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
188 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
reed@android.com258cb222010-04-14 13:36:33 +0000189 int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190
191 SkASSERT(state.fBitmap->getPixels());
192 SkASSERT(state.fBitmap->pixelRef() == NULL ||
reed@google.comff0da4f2012-05-17 13:14:52 +0000193 state.fBitmap->pixelRef()->isLocked());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194
195 for (;;) {
196 int n = count;
197 if (n > max) {
198 n = max;
199 }
reed@android.com258cb222010-04-14 13:36:33 +0000200 SkASSERT(n > 0 && n < BUF_MAX*2);
201#ifdef TEST_BUFFER_OVERRITE
202 for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
203 buffer[BUF_MAX + i] = TEST_PATTERN;
204 }
205#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206 mproc(state, buffer, n, x, y);
reed@android.com258cb222010-04-14 13:36:33 +0000207#ifdef TEST_BUFFER_OVERRITE
208 for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
209 SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
210 }
211#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 sproc(state, buffer, n, dstC);
reed@google.com7c2f27d2011-03-07 19:29:00 +0000213
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 if ((count -= n) == 0) {
215 break;
216 }
reed@android.com258cb222010-04-14 13:36:33 +0000217 SkASSERT(count > 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218 x += n;
219 dstC += n;
220 }
221}
222
reed@google.com3bafe742012-10-12 18:56:18 +0000223SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
224 if (fState.getShaderProc32()) {
225 *ctx = &fState;
226 return (ShadeProc)fState.getShaderProc32();
227 }
228 return NULL;
229}
230
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
reed@android.com7a99eb12009-07-16 01:13:14 +0000232 const SkBitmapProcState& state = fState;
reed@google.com9fe287b2012-03-27 15:54:28 +0000233 if (state.getShaderProc16()) {
234 state.getShaderProc16()(state, x, y, dstC, count);
reed@android.com7a99eb12009-07-16 01:13:14 +0000235 return;
236 }
reed@google.com7c2f27d2011-03-07 19:29:00 +0000237
reed@android.com7a99eb12009-07-16 01:13:14 +0000238 uint32_t buffer[BUF_MAX];
reed@google.com9fe287b2012-03-27 15:54:28 +0000239 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
240 SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
reed@android.com4c128c42009-08-14 13:54:37 +0000241 int max = fState.maxCountForBufferSize(sizeof(buffer));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242
243 SkASSERT(state.fBitmap->getPixels());
244 SkASSERT(state.fBitmap->pixelRef() == NULL ||
reed@google.comff0da4f2012-05-17 13:14:52 +0000245 state.fBitmap->pixelRef()->isLocked());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246
247 for (;;) {
248 int n = count;
249 if (n > max) {
250 n = max;
251 }
252 mproc(state, buffer, n, x, y);
253 sproc(state, buffer, n, dstC);
reed@google.com7c2f27d2011-03-07 19:29:00 +0000254
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255 if ((count -= n) == 0) {
256 break;
257 }
258 x += n;
259 dstC += n;
260 }
261}
262
263///////////////////////////////////////////////////////////////////////////////
264
reed@android.comc6459962009-08-25 19:15:31 +0000265#include "SkUnPreMultiply.h"
266#include "SkColorShader.h"
reed@google.com37a20122011-07-05 18:54:12 +0000267#include "SkEmptyShader.h"
reed@android.comc6459962009-08-25 19:15:31 +0000268
269// returns true and set color if the bitmap can be drawn as a single color
270// (for efficiency)
271static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
272 if (1 != bm.width() || 1 != bm.height()) {
273 return false;
274 }
275
276 SkAutoLockPixels alp(bm);
277 if (!bm.readyToDraw()) {
278 return false;
279 }
280
reed@google.com900ecf22014-02-20 20:55:37 +0000281 switch (bm.colorType()) {
commit-bot@chromium.org757ebd22014-04-10 22:36:34 +0000282 case kPMColor_SkColorType:
reed@android.comc6459962009-08-25 19:15:31 +0000283 *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
284 return true;
reed@google.com900ecf22014-02-20 20:55:37 +0000285 case kRGB_565_SkColorType:
reed@android.comc6459962009-08-25 19:15:31 +0000286 *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
287 return true;
reed@google.com900ecf22014-02-20 20:55:37 +0000288 case kIndex_8_SkColorType:
reed@android.comc6459962009-08-25 19:15:31 +0000289 *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
290 return true;
291 default: // just skip the other configs for now
292 break;
293 }
294 return false;
295}
296
reed@google.com99c114e2012-05-03 20:14:26 +0000297static bool bitmapIsTooBig(const SkBitmap& bm) {
298 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
299 // communicates between its matrix-proc and its sampler-proc. Until we can
300 // widen that, we have to reject bitmaps that are larger.
301 //
302 const int maxSize = 65535;
303
304 return bm.width() > maxSize || bm.height() > maxSize;
305}
306
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000307SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
308 SkShader::TileMode tmy, SkTBlitterAllocator* allocator) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309 SkShader* shader;
reed@android.comc6459962009-08-25 19:15:31 +0000310 SkColor color;
reed@google.com99c114e2012-05-03 20:14:26 +0000311 if (src.isNull() || bitmapIsTooBig(src)) {
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000312 if (NULL == allocator) {
313 shader = SkNEW(SkEmptyShader);
314 } else {
315 shader = allocator->createT<SkEmptyShader>();
316 }
reed@google.com37a20122011-07-05 18:54:12 +0000317 }
318 else if (canUseColorShader(src, &color)) {
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000319 if (NULL == allocator) {
320 shader = SkNEW_ARGS(SkColorShader, (color));
321 } else {
322 shader = allocator->createT<SkColorShader>(color);
323 }
reed@android.comc6459962009-08-25 19:15:31 +0000324 } else {
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +0000325 if (NULL == allocator) {
326 shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy));
327 } else {
328 shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy);
329 }
reed@android.comc6459962009-08-25 19:15:31 +0000330 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331 return shader;
332}
333
reed@android.com8a1c16f2008-12-17 15:59:43 +0000334///////////////////////////////////////////////////////////////////////////////
335
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000336#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000337void SkBitmapProcShader::toString(SkString* str) const {
338 static const char* gTileModeName[SkShader::kTileModeCount] = {
339 "clamp", "repeat", "mirror"
340 };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000342 str->append("BitmapShader: (");
reed@google.com7c2f27d2011-03-07 19:29:00 +0000343
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000344 str->appendf("(%s, %s)",
reed@android.com8a1c16f2008-12-17 15:59:43 +0000345 gTileModeName[fState.fTileModeX],
346 gTileModeName[fState.fTileModeY]);
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000347
348 str->append(" ");
349 fRawBitmap.toString(str);
350
351 this->INHERITED::toString(str);
352
353 str->append(")");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000354}
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000355#endif
356
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000357///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000359#if SK_SUPPORT_GPU
360
361#include "GrTextureAccess.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000362#include "effects/GrSimpleTextureEffect.h"
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000363#include "SkGr.h"
364
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000365// Note that this will return -1 if either matrix is perspective.
366static SkScalar get_combined_min_stretch(const SkMatrix& viewMatrix, const SkMatrix& localMatrix) {
367 if (localMatrix.isIdentity()) {
368 return viewMatrix.getMinStretch();
369 } else {
370 SkMatrix combined;
371 combined.setConcat(viewMatrix, localMatrix);
372 return combined.getMinStretch();
373 }
374}
375
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000376GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000377 SkMatrix matrix;
378 matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
379
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000380 SkMatrix lmInverse;
381 if (!this->getLocalMatrix().invert(&lmInverse)) {
commit-bot@chromium.orgcea9abb2013-12-09 19:15:37 +0000382 return NULL;
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000383 }
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000384 matrix.preConcat(lmInverse);
commit-bot@chromium.orgcea9abb2013-12-09 19:15:37 +0000385
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000386 SkShader::TileMode tm[] = {
387 (TileMode)fState.fTileModeX,
388 (TileMode)fState.fTileModeY,
389 };
390
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000391 // Must set wrap and filter on the sampler before requesting a texture. In two places below
392 // we check the matrix scale factors to determine how to interpret the filter quality setting.
393 // This completely ignores the complexity of the drawVertices case where explicit local coords
394 // are provided by the caller.
humper@google.comb86add12013-07-25 18:49:07 +0000395 SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
396 GrTextureParams::FilterMode textureFilterMode;
397 switch(paintFilterLevel) {
398 case SkPaint::kNone_FilterLevel:
399 textureFilterMode = GrTextureParams::kNone_FilterMode;
400 break;
401 case SkPaint::kLow_FilterLevel:
402 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
403 break;
404 case SkPaint::kMedium_FilterLevel:
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000405 if (get_combined_min_stretch(context->getMatrix(), this->getLocalMatrix()) <
406 SK_Scalar1) {
407 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
408 } else {
409 // Don't trigger MIP level generation unnecessarily.
410 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
411 }
humper@google.comb86add12013-07-25 18:49:07 +0000412 break;
413 case SkPaint::kHigh_FilterLevel:
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000414 // Minification can look bad with bicubic filtering.
415 if (get_combined_min_stretch(context->getMatrix(), this->getLocalMatrix()) >=
416 SK_Scalar1) {
417 // fall back to no filtering here; we will install another shader that will do the
418 // HQ filtering.
commit-bot@chromium.orgcea9abb2013-12-09 19:15:37 +0000419 textureFilterMode = GrTextureParams::kNone_FilterMode;
420 } else {
commit-bot@chromium.org79b7eee2013-12-16 21:02:29 +0000421 // Fall back to MIP-mapping.
commit-bot@chromium.orgcea9abb2013-12-09 19:15:37 +0000422 paintFilterLevel = SkPaint::kMedium_FilterLevel;
423 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
424 }
humper@google.comb86add12013-07-25 18:49:07 +0000425 break;
humper@google.comf9ed6fe2013-07-25 19:09:47 +0000426 default:
427 SkErrorInternals::SetError( kInvalidPaint_SkError,
428 "Sorry, I don't understand the filtering "
429 "mode you asked for. Falling back to "
430 "MIPMaps.");
431 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
432 break;
skia.committer@gmail.com956b3102013-07-26 07:00:58 +0000433
humper@google.comb86add12013-07-25 18:49:07 +0000434 }
435 GrTextureParams params(tm, textureFilterMode);
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000436 GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, &params);
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000437
438 if (NULL == texture) {
humper@google.com3aad3b02013-09-04 19:23:53 +0000439 SkErrorInternals::SetError( kInternalError_SkError,
440 "Couldn't convert bitmap to texture.");
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000441 return NULL;
442 }
443
humper@google.com3aad3b02013-09-04 19:23:53 +0000444 GrEffectRef* effect = NULL;
445 if (paintFilterLevel == SkPaint::kHigh_FilterLevel) {
commit-bot@chromium.orgbc91fd72013-12-10 12:53:39 +0000446 effect = GrBicubicEffect::Create(texture, matrix, tm);
humper@google.com3aad3b02013-09-04 19:23:53 +0000447 } else {
448 effect = GrSimpleTextureEffect::Create(texture, matrix, params);
449 }
bsalomon@google.com95ed55a2013-01-24 14:46:47 +0000450 GrUnlockAndUnrefCachedBitmapTexture(texture);
bsalomon@google.come197cbf2013-01-14 16:46:26 +0000451 return effect;
452}
453#endif