180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBitmapProcShader.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFlattenableBuffers.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPixelRef.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (bm.config()) {
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kA8_Config:
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kRGB_565_Config:
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kIndex8_Config:
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_8888_Config:
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return true;
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       TileMode tmx, TileMode tmy) {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRawBitmap = src;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fState.fTileModeX = (uint8_t)tmx;
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fState.fTileModeY = (uint8_t)tmy;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFlags = 0; // computed in setContext
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : INHERITED(buffer) {
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.readBitmap(&fRawBitmap);
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fRawBitmap.setImmutable();
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fState.fTileModeX = buffer.readUInt();
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fState.fTileModeY = buffer.readUInt();
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFlags = 0; // computed in setContext
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                   SkMatrix* texM,
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                   TileMode xy[]) const {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (texture) {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *texture = fRawBitmap;
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (texM) {
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        texM->reset();
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (xy) {
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        xy[0] = (TileMode)fState.fTileModeX;
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        xy[1] = (TileMode)fState.fTileModeY;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return kDefault_BitmapType;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::flatten(buffer);
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeBitmap(fRawBitmap);
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeUInt(fState.fTileModeX);
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeUInt(fState.fTileModeY);
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool only_scale_and_translate(const SkMatrix& matrix) {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (matrix.getType() & ~mask) == 0;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBitmapProcShader::isOpaque() const {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fRawBitmap.isOpaque();
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBitmapProcShader::setContext(const SkBitmap& device,
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    const SkPaint& paint,
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    const SkMatrix& matrix) {
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // do this first, so we have a correct inverse matrix
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!this->INHERITED::setContext(device, paint, matrix)) {
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fState.fOrigBitmap = fRawBitmap;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fState.fOrigBitmap.lockPixels();
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fState.fOrigBitmap.unlockPixels();
89d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->INHERITED::endContext();
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fState.fOrigBitmap.unlockPixels();
95d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        this->INHERITED::endContext();
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkBitmap& bitmap = *fState.fBitmap;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool bitmapIsOpaque = bitmap.isOpaque();
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // update fFlags
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t flags = 0;
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        flags |= kOpaqueAlpha_Flag;
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (bitmap.config()) {
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kRGB_565_Config:
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kIndex8_Config:
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_8888_Config:
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (bitmapIsOpaque) {
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                flags |= kHasSpan16_Flag;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kA8_Config:
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;  // never set kHasSpan16_Flag
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // gradients can auto-dither in their 16bit sampler, but we don't so
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // we clear the flag here.
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        flags &= ~kHasSpan16_Flag;
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
130d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // if we're only 1-pixel high, and we don't rotate, then we can claim this
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (1 == bitmap.height() &&
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            only_scale_and_translate(this->getTotalInverse())) {
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        flags |= kConstInY32_Flag;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (flags & kHasSpan16_Flag) {
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            flags |= kConstInY16_Flag;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFlags = flags;
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkBitmapProcShader::endContext() {
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fState.fOrigBitmap.unlockPixels();
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    this->INHERITED::endContext();
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define BUF_MAX     128
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define TEST_BUFFER_OVERRITEx
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TEST_BUFFER_OVERRITE
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define TEST_BUFFER_EXTRA   32
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define TEST_PATTERN    0x88888888
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define TEST_BUFFER_EXTRA   0
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkBitmapProcState& state = fState;
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (state.getShaderProc32()) {
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        state.getShaderProc32()(state, x, y, dstC, count);
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(state.fBitmap->getPixels());
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(state.fBitmap->pixelRef() == NULL ||
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             state.fBitmap->pixelRef()->isLocked());
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int n = count;
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (n > max) {
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = max;
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(n > 0 && n < BUF_MAX*2);
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TEST_BUFFER_OVERRITE
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            buffer[BUF_MAX + i] = TEST_PATTERN;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mproc(state, buffer, n, x, y);
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TEST_BUFFER_OVERRITE
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sproc(state, buffer, n, dstC);
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((count -= n) == 0) {
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(count > 0);
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x += n;
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dstC += n;
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fState.getShaderProc32()) {
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *ctx = &fState;
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (ShadeProc)fState.getShaderProc32();
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkBitmapProcState& state = fState;
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (state.getShaderProc16()) {
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        state.getShaderProc16()(state, x, y, dstC, count);
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t buffer[BUF_MAX];
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int max = fState.maxCountForBufferSize(sizeof(buffer));
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(state.fBitmap->getPixels());
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(state.fBitmap->pixelRef() == NULL ||
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             state.fBitmap->pixelRef()->isLocked());
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (;;) {
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int n = count;
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (n > max) {
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            n = max;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        mproc(state, buffer, n, x, y);
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sproc(state, buffer, n, dstC);
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((count -= n) == 0) {
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x += n;
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dstC += n;
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUnPreMultiply.h"
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorShader.h"
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkEmptyShader.h"
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// returns true and set color if the bitmap can be drawn as a single color
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// (for efficiency)
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (1 != bm.width() || 1 != bm.height()) {
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(bm);
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!bm.readyToDraw()) {
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (bm.config()) {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_8888_Config:
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kRGB_565_Config:
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kIndex8_Config:
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default: // just skip the other configs for now
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplatesPriv.h"
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool bitmapIsTooBig(const SkBitmap& bm) {
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // communicates between its matrix-proc and its sampler-proc. Until we can
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // widen that, we have to reject bitmaps that are larger.
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int maxSize = 65535;
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return bm.width() > maxSize || bm.height() > maxSize;
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       TileMode tmx, TileMode tmy,
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       void* storage, size_t storageSize) {
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkShader* shader;
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkColor color;
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src.isNull() || bitmapIsTooBig(src)) {
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (canUseColorShader(src, &color)) {
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              (color));
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              storageSize, (src, tmx, tmy));
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return shader;
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
309d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
310d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkBitmapProcShader::toString(SkString* str) const {
311d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    static const char* gTileModeName[SkShader::kTileModeCount] = {
312d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        "clamp", "repeat", "mirror"
313d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    };
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
315d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append("BitmapShader: (");
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
317d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->appendf("(%s, %s)",
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 gTileModeName[fState.fTileModeX],
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                 gTileModeName[fState.fTileModeY]);
320d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
321d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append(" ");
322d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    fRawBitmap.toString(str);
323d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
324d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    this->INHERITED::toString(str);
325d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
326d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append(")");
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
328d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
329d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
330d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
331d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
332d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#if SK_SUPPORT_GPU
333d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
334d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "GrTextureAccess.h"
335d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "effects/GrSimpleTextureEffect.h"
336d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "SkGr.h"
337d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
338d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
339d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkMatrix matrix;
340d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
341d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
342d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (this->hasLocalMatrix()) {
343d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkMatrix inverse;
344d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!this->getLocalMatrix().invert(&inverse)) {
345d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            return NULL;
346d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
347d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        matrix.preConcat(inverse);
348d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
349d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkShader::TileMode tm[] = {
350d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        (TileMode)fState.fTileModeX,
351d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        (TileMode)fState.fTileModeY,
352d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    };
353d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
354d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // Must set wrap and filter on the sampler before requesting a texture.
355d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrTextureParams params(tm, paint.isFilterBitmap());
356d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, &params);
357d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
358d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (NULL == texture) {
359d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkDebugf("Couldn't convert bitmap to texture.\n");
360d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return NULL;
361d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
363d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
364d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrUnlockAndUnrefCachedBitmapTexture(texture);
365d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return effect;
366d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
367d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
368