Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2010 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 
      9 
     10 
     11 #include "SkGr.h"
     12 
     13 /*  Fill out buffer with the compressed format Ganesh expects from a colortable
     14  based bitmap. [palette (colortable) + indices].
     15 
     16  At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
     17  we could detect that the colortable.count is <= 16, and then repack the
     18  indices as nibbles to save RAM, but it would take more time (i.e. a lot
     19  slower than memcpy), so skipping that for now.
     20 
     21  Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
     22  as the colortable.count says it is.
     23  */
     24 static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
     25     SkASSERT(SkBitmap::kIndex8_Config == bitmap.config());
     26 
     27     SkAutoLockPixels apl(bitmap);
     28     if (!bitmap.readyToDraw()) {
     29         SkDEBUGFAIL("bitmap not ready to draw!");
     30         return;
     31     }
     32 
     33     SkColorTable* ctable = bitmap.getColorTable();
     34     char* dst = (char*)buffer;
     35 
     36     memcpy(dst, ctable->lockColors(), ctable->count() * sizeof(SkPMColor));
     37     ctable->unlockColors(false);
     38 
     39     // always skip a full 256 number of entries, even if we memcpy'd fewer
     40     dst += kGrColorTableSize;
     41 
     42     if (bitmap.width() == bitmap.rowBytes()) {
     43         memcpy(dst, bitmap.getPixels(), bitmap.getSize());
     44     } else {
     45         // need to trim off the extra bytes per row
     46         size_t width = bitmap.width();
     47         size_t rowBytes = bitmap.rowBytes();
     48         const char* src = (const char*)bitmap.getPixels();
     49         for (int y = 0; y < bitmap.height(); y++) {
     50             memcpy(dst, src, width);
     51             src += rowBytes;
     52             dst += width;
     53         }
     54     }
     55 }
     56 
     57 ////////////////////////////////////////////////////////////////////////////////
     58 
     59 GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx,
     60                                                 GrContext::TextureKey key,
     61                                                 const GrSamplerState* sampler,
     62                                                 const SkBitmap& origBitmap) {
     63     SkAutoLockPixels alp(origBitmap);
     64     GrContext::TextureCacheEntry entry;
     65 
     66     if (!origBitmap.readyToDraw()) {
     67         return entry;
     68     }
     69 
     70     SkBitmap tmpBitmap;
     71 
     72     const SkBitmap* bitmap = &origBitmap;
     73 
     74     GrTextureDesc desc = {
     75         kNone_GrTextureFlags,
     76         bitmap->width(),
     77         bitmap->height(),
     78         SkGr::Bitmap2PixelConfig(*bitmap),
     79         {0} // samples
     80     };
     81 
     82     if (SkBitmap::kIndex8_Config == bitmap->config()) {
     83         // build_compressed_data doesn't do npot->pot expansion
     84         // and paletted textures can't be sub-updated
     85         if (ctx->supportsIndex8PixelConfig(sampler,
     86                                            bitmap->width(), bitmap->height())) {
     87             size_t imagesize = bitmap->width() * bitmap->height() +
     88                                 kGrColorTableSize;
     89             SkAutoMalloc storage(imagesize);
     90 
     91             build_compressed_data(storage.get(), origBitmap);
     92 
     93             // our compressed data will be trimmed, so pass width() for its
     94             // "rowBytes", since they are the same now.
     95 
     96             if (gUNCACHED_KEY != key) {
     97                 return ctx->createAndLockTexture(key, sampler, desc, storage.get(),
     98                                                  bitmap->width());
     99             } else {
    100                 entry = ctx->lockScratchTexture(desc,
    101                                         GrContext::kExact_ScratchTexMatch);
    102                 entry.texture()->writePixels(0, 0, bitmap->width(),
    103                                              bitmap->height(), desc.fConfig,
    104                                              storage.get(), 0);
    105                 return entry;
    106             }
    107 
    108         } else {
    109             origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config);
    110             // now bitmap points to our temp, which has been promoted to 32bits
    111             bitmap = &tmpBitmap;
    112         }
    113     }
    114 
    115     desc.fConfig = SkGr::Bitmap2PixelConfig(*bitmap);
    116     if (gUNCACHED_KEY != key) {
    117         return ctx->createAndLockTexture(key, sampler, desc,
    118                                          bitmap->getPixels(),
    119                                          bitmap->rowBytes());
    120     } else {
    121         entry = ctx->lockScratchTexture(desc,
    122                                         GrContext::kExact_ScratchTexMatch);
    123         entry.texture()->writePixels(0, 0,
    124                                      bitmap->width(), bitmap->height(),
    125                                      desc.fConfig,
    126                                      bitmap->getPixels(),
    127                                      bitmap->rowBytes());
    128         return entry;
    129     }
    130 }
    131 
    132 ///////////////////////////////////////////////////////////////////////////////
    133 
    134 void SkGrClipIterator::reset(const SkClipStack& clipStack) {
    135     fClipStack = &clipStack;
    136     fIter.reset(clipStack);
    137     // Gr has no notion of replace, skip to the
    138     // last replace in the clip stack.
    139     int lastReplace = 0;
    140     int curr = 0;
    141     while (NULL != (fCurr = fIter.next())) {
    142         if (SkRegion::kReplace_Op == fCurr->fOp) {
    143             lastReplace = curr;
    144         }
    145         ++curr;
    146     }
    147     fIter.reset(clipStack);
    148     for (int i = 0; i < lastReplace+1; ++i) {
    149         fCurr = fIter.next();
    150     }
    151 }
    152 
    153 GrClipType SkGrClipIterator::getType() const {
    154     GrAssert(!this->isDone());
    155     if (NULL == fCurr->fPath) {
    156         return kRect_ClipType;
    157     } else {
    158         return kPath_ClipType;
    159     }
    160 }
    161 
    162 GrSetOp SkGrClipIterator::getOp() const {
    163     // we skipped to the last "replace" op
    164     // when this iter was reset.
    165     // GrClip doesn't allow replace, so treat it as
    166     // intersect.
    167     GrSetOp skToGrOps[] = {
    168         kDifference_SetOp,         // kDifference_Op
    169         kIntersect_SetOp,          // kIntersect_Op
    170         kUnion_SetOp,              // kUnion_Op
    171         kXor_SetOp,                // kXOR_Op
    172         kReverseDifference_SetOp,  // kReverseDifference_Op
    173         kIntersect_SetOp           // kReplace_op
    174     };
    175     GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
    176     GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
    177     GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
    178     GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
    179     GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
    180     GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
    181     return skToGrOps[fCurr->fOp];
    182 }
    183 
    184 GrPathFill SkGrClipIterator::getPathFill() const {
    185     switch (fCurr->fPath->getFillType()) {
    186         case SkPath::kWinding_FillType:
    187             return kWinding_PathFill;
    188         case SkPath::kEvenOdd_FillType:
    189             return  kEvenOdd_PathFill;
    190         case SkPath::kInverseWinding_FillType:
    191             return kInverseWinding_PathFill;
    192         case SkPath::kInverseEvenOdd_FillType:
    193             return kInverseEvenOdd_PathFill;
    194         default:
    195             GrCrash("Unsupported path fill in clip.");
    196             return kWinding_PathFill; // suppress warning
    197     }
    198 }
    199 
    200 ///////////////////////////////////////////////////////////////////////////////
    201 
    202 GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config,
    203                                                     bool isOpaque) {
    204     switch (config) {
    205         case SkBitmap::kA8_Config:
    206             return kAlpha_8_GrPixelConfig;
    207         case SkBitmap::kIndex8_Config:
    208             return kIndex_8_GrPixelConfig;
    209         case SkBitmap::kRGB_565_Config:
    210             return kRGB_565_GrPixelConfig;
    211         case SkBitmap::kARGB_4444_Config:
    212             return kRGBA_4444_GrPixelConfig;
    213         case SkBitmap::kARGB_8888_Config:
    214             return kSkia8888_PM_GrPixelConfig;
    215         default:
    216             return kUnknown_GrPixelConfig;
    217     }
    218 }
    219 
    220