Home | History | Annotate | Download | only in core
      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     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 
    486 bool 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