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
20bool 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
34SkBitmapProcShader::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
43SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer) : INHERITED(buffer) {
44    buffer.readBitmap(&fRawBitmap);
45    fRawBitmap.setImmutable();
46    fTileModeX = buffer.readUInt();
47    fTileModeY = buffer.readUInt();
48}
49#endif
50
51SkShader::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
67SkFlattenable* 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
80void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const {
81    buffer.writeMatrix(this->getLocalMatrix());
82    buffer.writeBitmap(fRawBitmap);
83    buffer.writeUInt(fTileModeX);
84    buffer.writeUInt(fTileModeY);
85}
86
87static 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
92bool SkBitmapProcShader::isOpaque() const {
93    return fRawBitmap.isOpaque();
94}
95
96static 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
113SkShader::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
139size_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
145SkBitmapProcShader::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
193SkBitmapProcShader::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
210void 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
255SkShader::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
263void 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)
304static 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
330static 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
340SkShader* 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
370void 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
398bool 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    GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, &params);
463
464    if (NULL == 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    GrUnlockAndUnrefCachedBitmapTexture(texture);
480
481    return true;
482}
483
484#else
485
486bool SkBitmapProcShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*,
487                                             GrFragmentProcessor**) const {
488    SkDEBUGFAIL("Should not call in GPU-less build");
489    return false;
490}
491
492#endif
493