Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkBitmapProcShader.cpp
1
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  */
8 #include "SkColorPriv.h"
9 #include "SkReadBuffer.h"
10 #include "SkWriteBuffer.h"
11 #include "SkPixelRef.h"
12 #include "SkErrorInternals.h"
13 #include "SkBitmapProcShader.h"
14
15 #if SK_SUPPORT_GPU
16 #include "effects/GrSimpleTextureEffect.h"
17 #include "effects/GrBicubicEffect.h"
18 #endif
19
20 bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
21     switch (bm.colorType()) {
22         case kAlpha_8_SkColorType:
23         case kRGB_565_SkColorType:
24         case kIndex_8_SkColorType:
25         case kN32_SkColorType:
26     //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
27                 return true;
28         default:
29             break;
30     }
31     return false;
32 }
33
34 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
35                                        const SkMatrix* localMatrix)
36         : INHERITED(localMatrix) {
37     fRawBitmap = src;
38     fTileModeX = (uint8_t)tmx;
39     fTileModeY = (uint8_t)tmy;
40 }
41
42 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
43 SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer) : INHERITED(buffer) {
44     buffer.readBitmap(&fRawBitmap);
45     fRawBitmap.setImmutable();
46     fTileModeX = buffer.readUInt();
47     fTileModeY = buffer.readUInt();
48 }
49 #endif
50
51 SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
52                                                    SkMatrix* texM,
53                                                    TileMode xy[]) const {
54     if (texture) {
55         *texture = fRawBitmap;
56     }
57     if (texM) {
58         texM->reset();
59     }
60     if (xy) {
61         xy[0] = (TileMode)fTileModeX;
62         xy[1] = (TileMode)fTileModeY;
63     }
64     return kDefault_BitmapType;
65 }
66
67 SkFlattenable* SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) {
68     SkMatrix lm;
69     buffer.readMatrix(&lm);
70     SkBitmap bm;
71     if (!buffer.readBitmap(&bm)) {
72         return NULL;
73     }
74     bm.setImmutable();
75     TileMode mx = (TileMode)buffer.readUInt();
76     TileMode my = (TileMode)buffer.readUInt();
77     return SkShader::CreateBitmapShader(bm, mx, my, &lm);
78 }
79
80 void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const {
81     buffer.writeMatrix(this->getLocalMatrix());
82     buffer.writeBitmap(fRawBitmap);
83     buffer.writeUInt(fTileModeX);
84     buffer.writeUInt(fTileModeY);
85 }
86
87 static bool only_scale_and_translate(const SkMatrix& matrix) {
88     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
89     return (matrix.getType() & ~mask) == 0;
90 }
91
92 bool SkBitmapProcShader::isOpaque() const {
93     return fRawBitmap.isOpaque();
94 }
95
96 static bool valid_for_drawing(const SkBitmap& bm) {
97     if (0 == bm.width() || 0 == bm.height()) {
98         return false;   // nothing to draw
99     }
100     if (NULL == bm.pixelRef()) {
101         return false;   // no pixels to read
102     }
103     if (kIndex_8_SkColorType == bm.colorType()) {
104         // ugh, I have to lock-pixels to inspect the colortable
105         SkAutoLockPixels alp(bm);
106         if (!bm.getColorTable()) {
107             return false;
108         }
109     }
110     return true;
111 }
112
113 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
114     if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) {
115         return NULL;
116     }
117
118     SkMatrix totalInverse;
119     // Do this first, so we know the matrix can be inverted.
120     if (!this->computeTotalInverse(rec, &totalInverse)) {
121         return NULL;
122     }
123
124     void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
125     SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState);
126
127     SkASSERT(state);
128     state->fTileModeX = fTileModeX;
129     state->fTileModeY = fTileModeY;
130     state->fOrigBitmap = fRawBitmap;
131     if (!state->chooseProcs(totalInverse, *rec.fPaint)) {
132         state->~SkBitmapProcState();
133         return NULL;
134     }
135
136     return SkNEW_PLACEMENT_ARGS(storage, BitmapProcShaderContext, (*this, rec, state));
137 }
138
139 size_t SkBitmapProcShader::contextSize() const {
140     // The SkBitmapProcState is stored outside of the context object, with the context holding
141     // a pointer to it.
142     return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
143 }
144
145 SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(
146         const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state)
147     : INHERITED(shader, rec)
148     , fState(state)
149 {
150     const SkBitmap& bitmap = *fState->fBitmap;
151     bool bitmapIsOpaque = bitmap.isOpaque();
152
153     // update fFlags
154     uint32_t flags = 0;
155     if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
156         flags |= kOpaqueAlpha_Flag;
157     }
158
159     switch (bitmap.colorType()) {
160         case kRGB_565_SkColorType:
161             flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
162             break;
163         case kIndex_8_SkColorType:
164         case kN32_SkColorType:
165             if (bitmapIsOpaque) {
166                 flags |= kHasSpan16_Flag;
167             }
168             break;
169         case kAlpha_8_SkColorType:
170             break;  // never set kHasSpan16_Flag
171         default:
172             break;
173     }
174
175     if (rec.fPaint->isDither() && bitmap.colorType() != kRGB_565_SkColorType) {
176         // gradients can auto-dither in their 16bit sampler, but we don't so
177         // we clear the flag here.
178         flags &= ~kHasSpan16_Flag;
179     }
180
181     // if we're only 1-pixel high, and we don't rotate, then we can claim this
182     if (1 == bitmap.height() &&
183             only_scale_and_translate(this->getTotalInverse())) {
184         flags |= kConstInY32_Flag;
185         if (flags & kHasSpan16_Flag) {
186             flags |= kConstInY16_Flag;
187         }
188     }
189
190     fFlags = flags;
191 }
192
193 SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() {
194     // The bitmap proc state has been created outside of the context on memory that will be freed
195     // elsewhere. Only call the destructor but leave the freeing of the memory to the caller.
196     fState->~SkBitmapProcState();
197 }
198
199 #define BUF_MAX     128
200
201 #define TEST_BUFFER_OVERRITEx
202
203 #ifdef TEST_BUFFER_OVERRITE
204     #define TEST_BUFFER_EXTRA   32
205     #define TEST_PATTERN    0x88888888
206 #else
207     #define TEST_BUFFER_EXTRA   0
208 #endif
209
210 void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMColor dstC[],
211                                                             int count) {
212     const SkBitmapProcState& state = *fState;
213     if (state.getShaderProc32()) {
214         state.getShaderProc32()(state, x, y, dstC, count);
215         return;
216     }
217
218     uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
219     SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
220     SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
221     int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
222
223     SkASSERT(state.fBitmap->getPixels());
224     SkASSERT(state.fBitmap->pixelRef() == NULL ||
225              state.fBitmap->pixelRef()->isLocked());
226
227     for (;;) {
228         int n = count;
229         if (n > max) {
230             n = max;
231         }
232         SkASSERT(n > 0 && n < BUF_MAX*2);
233 #ifdef TEST_BUFFER_OVERRITE
234         for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
235             buffer[BUF_MAX + i] = TEST_PATTERN;
236         }
237 #endif
238         mproc(state, buffer, n, x, y);
239 #ifdef TEST_BUFFER_OVERRITE
240         for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
241             SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
242         }
243 #endif
244         sproc(state, buffer, n, dstC);
245
246         if ((count -= n) == 0) {
247             break;
248         }
249         SkASSERT(count > 0);
250         x += n;
251         dstC += n;
252     }
253 }
254
255 SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asAShadeProc(void** ctx) {
256     if (fState->getShaderProc32()) {
257         *ctx = fState;
258         return (ShadeProc)fState->getShaderProc32();
259     }
260     return NULL;
261 }
262
263 void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan16(int x, int y, uint16_t dstC[],
264                                                               int count) {
265     const SkBitmapProcState& state = *fState;
266     if (state.getShaderProc16()) {
267         state.getShaderProc16()(state, x, y, dstC, count);
268         return;
269     }
270
271     uint32_t buffer[BUF_MAX];
272     SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
273     SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
274     int max = state.maxCountForBufferSize(sizeof(buffer));
275
276     SkASSERT(state.fBitmap->getPixels());
277     SkASSERT(state.fBitmap->pixelRef() == NULL ||
278              state.fBitmap->pixelRef()->isLocked());
279
280     for (;;) {
281         int n = count;
282         if (n > max) {
283             n = max;
284         }
285         mproc(state, buffer, n, x, y);
286         sproc(state, buffer, n, dstC);
287
288         if ((count -= n) == 0) {
289             break;
290         }
291         x += n;
292         dstC += n;
293     }
294 }
295
296 ///////////////////////////////////////////////////////////////////////////////
297
298 #include "SkUnPreMultiply.h"
299 #include "SkColorShader.h"
300 #include "SkEmptyShader.h"
301
302 // returns true and set color if the bitmap can be drawn as a single color
303 // (for efficiency)
304 static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
305     if (1 != bm.width() || 1 != bm.height()) {
306         return false;
307     }
308
309     SkAutoLockPixels alp(bm);
310     if (!bm.readyToDraw()) {
311         return false;
312     }
313
314     switch (bm.colorType()) {
315         case kN32_SkColorType:
316             *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
317             return true;
318         case kRGB_565_SkColorType:
319             *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
320             return true;
321         case kIndex_8_SkColorType:
322             *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
323             return true;
324         default: // just skip the other configs for now
325             break;
326     }
327     return false;
328 }
329
330 static bool bitmapIsTooBig(const SkBitmap& bm) {
331     // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
332     // communicates between its matrix-proc and its sampler-proc. Until we can
333     // widen that, we have to reject bitmaps that are larger.
334     //
335     const int maxSize = 65535;
336
337     return bm.width() > maxSize || bm.height() > maxSize;
338 }
339
340 SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
341         SkShader::TileMode tmy, const SkMatrix* localMatrix, SkTBlitterAllocator* allocator) {
342     SkShader* shader;
343     SkColor color;
344     if (src.isNull() || bitmapIsTooBig(src)) {
345         if (NULL == allocator) {
346             shader = SkNEW(SkEmptyShader);
347         } else {
348             shader = allocator->createT<SkEmptyShader>();
349         }
350     }
351     else if (canUseColorShader(src, &color)) {
352         if (NULL == allocator) {
353             shader = SkNEW_ARGS(SkColorShader, (color));
354         } else {
355             shader = allocator->createT<SkColorShader>(color);
356         }
357     } else {
358         if (NULL == allocator) {
359             shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy, localMatrix));
360         } else {
361             shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, localMatrix);
362         }
363     }
364     return shader;
365 }
366
367 ///////////////////////////////////////////////////////////////////////////////
368
369 #ifndef SK_IGNORE_TO_STRING
370 void SkBitmapProcShader::toString(SkString* str) const {
371     static const char* gTileModeName[SkShader::kTileModeCount] = {
372         "clamp", "repeat", "mirror"
373     };
374
375     str->append("BitmapShader: (");
376
377     str->appendf("(%s, %s)",
378                  gTileModeName[fTileModeX],
379                  gTileModeName[fTileModeY]);
380
381     str->append(" ");
382     fRawBitmap.toString(str);
383
384     this->INHERITED::toString(str);
385
386     str->append(")");
387 }
388 #endif
389
390 ///////////////////////////////////////////////////////////////////////////////
391
392 #if SK_SUPPORT_GPU
393
394 #include "GrTextureAccess.h"
395 #include "effects/GrSimpleTextureEffect.h"
396 #include "SkGr.h"
397
398 bool SkBitmapProcShader::asFragmentProcessor(GrContext* context, const SkPaint& paint,
399                                              const SkMatrix* localMatrix, GrColor* paintColor,
400                                              GrFragmentProcessor** fp) const {
401     SkMatrix matrix;
402     matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
403
404     SkMatrix lmInverse;
405     if (!this->getLocalMatrix().invert(&lmInverse)) {
406         return false;
407     }
408     if (localMatrix) {
409         SkMatrix inv;
410         if (!localMatrix->invert(&inv)) {
411             return false;
412         }
413         lmInverse.postConcat(inv);
414     }
415     matrix.preConcat(lmInverse);
416
417     SkShader::TileMode tm[] = {
418         (TileMode)fTileModeX,
419         (TileMode)fTileModeY,
420     };
421
422     // Must set wrap and filter on the sampler before requesting a texture. In two places below
423     // we check the matrix scale factors to determine how to interpret the filter quality setting.
424     // This completely ignores the complexity of the drawVertices case where explicit local coords
425     // are provided by the caller.
426     bool useBicubic = false;
427     GrTextureParams::FilterMode textureFilterMode;
428     switch(paint.getFilterLevel()) {
429         case SkPaint::kNone_FilterLevel:
430             textureFilterMode = GrTextureParams::kNone_FilterMode;
431             break;
432         case SkPaint::kLow_FilterLevel:
433             textureFilterMode = GrTextureParams::kBilerp_FilterMode;
434             break;
435         case SkPaint::kMedium_FilterLevel: {
436             SkMatrix matrix;
437             matrix.setConcat(context->getMatrix(), this->getLocalMatrix());
438             if (matrix.getMinScale() < SK_Scalar1) {
439                 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
440             } else {
441                 // Don't trigger MIP level generation unnecessarily.
442                 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
443             }
444             break;
445         }
446         case SkPaint::kHigh_FilterLevel: {
447             SkMatrix matrix;
448             matrix.setConcat(context->getMatrix(), this->getLocalMatrix());
449             useBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
450             break;
451         }
452         default:
453             SkErrorInternals::SetError( kInvalidPaint_SkError,
454                                         "Sorry, I don't understand the filtering "
455                                         "mode you asked for.  Falling back to "
456                                         "MIPMaps.");
457             textureFilterMode = GrTextureParams::kMipMap_FilterMode;
458             break;
459
460     }
461     GrTextureParams params(tm, textureFilterMode);
462     SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, fRawBitmap, &params));
463
464     if (!texture) {
465         SkErrorInternals::SetError( kInternalError_SkError,
466                                     "Couldn't convert bitmap to texture.");
467         return false;
468     }
469     
470     *paintColor = (kAlpha_8_SkColorType == fRawBitmap.colorType()) ?
471                                                 SkColor2GrColor(paint.getColor()) :
472                                                 SkColor2GrColorJustAlpha(paint.getColor());
473
474     if (useBicubic) {
475         *fp = GrBicubicEffect::Create(texture, matrix, tm);
476     } else {
477         *fp = GrSimpleTextureEffect::Create(texture, matrix, params);
478     }
479
480     return true;
481 }
482
483 #else 
484
485 bool SkBitmapProcShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*,
486                                              GrFragmentProcessor**) const {
487     SkDEBUGFAIL("Should not call in GPU-less build");
488     return false;
489 }
490
491 #endif