gfx/skia/trunk/src/gpu/SkGr.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/gpu/SkGr.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,314 @@
     1.4 +/*
     1.5 + * Copyright 2010 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#include "SkGr.h"
    1.12 +#include "SkConfig8888.h"
    1.13 +#include "SkMessageBus.h"
    1.14 +#include "SkPixelRef.h"
    1.15 +#include "GrResourceCache.h"
    1.16 +
    1.17 +/*  Fill out buffer with the compressed format Ganesh expects from a colortable
    1.18 + based bitmap. [palette (colortable) + indices].
    1.19 +
    1.20 + At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
    1.21 + we could detect that the colortable.count is <= 16, and then repack the
    1.22 + indices as nibbles to save RAM, but it would take more time (i.e. a lot
    1.23 + slower than memcpy), so skipping that for now.
    1.24 +
    1.25 + Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
    1.26 + as the colortable.count says it is.
    1.27 + */
    1.28 +static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
    1.29 +    SkASSERT(SkBitmap::kIndex8_Config == bitmap.config());
    1.30 +
    1.31 +    SkAutoLockPixels alp(bitmap);
    1.32 +    if (!bitmap.readyToDraw()) {
    1.33 +        SkDEBUGFAIL("bitmap not ready to draw!");
    1.34 +        return;
    1.35 +    }
    1.36 +
    1.37 +    SkColorTable* ctable = bitmap.getColorTable();
    1.38 +    char* dst = (char*)buffer;
    1.39 +
    1.40 +    uint32_t* colorTableDst = reinterpret_cast<uint32_t*>(dst);
    1.41 +    const uint32_t* colorTableSrc = reinterpret_cast<const uint32_t*>(ctable->lockColors());
    1.42 +    SkConvertConfig8888Pixels(colorTableDst, 0, SkCanvas::kRGBA_Premul_Config8888,
    1.43 +                              colorTableSrc, 0, SkCanvas::kNative_Premul_Config8888,
    1.44 +                              ctable->count(), 1);
    1.45 +    ctable->unlockColors();
    1.46 +
    1.47 +    // always skip a full 256 number of entries, even if we memcpy'd fewer
    1.48 +    dst += kGrColorTableSize;
    1.49 +
    1.50 +    if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
    1.51 +        memcpy(dst, bitmap.getPixels(), bitmap.getSize());
    1.52 +    } else {
    1.53 +        // need to trim off the extra bytes per row
    1.54 +        size_t width = bitmap.width();
    1.55 +        size_t rowBytes = bitmap.rowBytes();
    1.56 +        const char* src = (const char*)bitmap.getPixels();
    1.57 +        for (int y = 0; y < bitmap.height(); y++) {
    1.58 +            memcpy(dst, src, width);
    1.59 +            src += rowBytes;
    1.60 +            dst += width;
    1.61 +        }
    1.62 +    }
    1.63 +}
    1.64 +
    1.65 +////////////////////////////////////////////////////////////////////////////////
    1.66 +
    1.67 +static void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) {
    1.68 +    // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
    1.69 +    // are unique.
    1.70 +    uint32_t genID = bitmap.getGenerationID();
    1.71 +    SkIPoint origin = bitmap.pixelRefOrigin();
    1.72 +    int16_t width = SkToS16(bitmap.width());
    1.73 +    int16_t height = SkToS16(bitmap.height());
    1.74 +
    1.75 +    GrCacheID::Key key;
    1.76 +    memcpy(key.fData8 +  0, &genID,     4);
    1.77 +    memcpy(key.fData8 +  4, &origin.fX, 4);
    1.78 +    memcpy(key.fData8 +  8, &origin.fY, 4);
    1.79 +    memcpy(key.fData8 + 12, &width,     2);
    1.80 +    memcpy(key.fData8 + 14, &height,    2);
    1.81 +    static const size_t kKeyDataSize = 16;
    1.82 +    memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize);
    1.83 +    GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize);
    1.84 +    static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain();
    1.85 +    id->reset(gBitmapTextureDomain, key);
    1.86 +}
    1.87 +
    1.88 +static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrTextureDesc* desc) {
    1.89 +    desc->fFlags = kNone_GrTextureFlags;
    1.90 +    desc->fWidth = bitmap.width();
    1.91 +    desc->fHeight = bitmap.height();
    1.92 +    desc->fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config());
    1.93 +    desc->fSampleCnt = 0;
    1.94 +}
    1.95 +
    1.96 +namespace {
    1.97 +
    1.98 +// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
    1.99 +class GrResourceInvalidator : public SkPixelRef::GenIDChangeListener {
   1.100 +public:
   1.101 +    explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {}
   1.102 +private:
   1.103 +    GrResourceKey fKey;
   1.104 +
   1.105 +    virtual void onChange() SK_OVERRIDE {
   1.106 +        const GrResourceInvalidatedMessage message = { fKey };
   1.107 +        SkMessageBus<GrResourceInvalidatedMessage>::Post(message);
   1.108 +    }
   1.109 +};
   1.110 +
   1.111 +}  // namespace
   1.112 +
   1.113 +static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) {
   1.114 +    SkASSERT(NULL != pixelRef);
   1.115 +    pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
   1.116 +}
   1.117 +
   1.118 +static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
   1.119 +                                              bool cache,
   1.120 +                                              const GrTextureParams* params,
   1.121 +                                              const SkBitmap& origBitmap) {
   1.122 +    SkBitmap tmpBitmap;
   1.123 +
   1.124 +    const SkBitmap* bitmap = &origBitmap;
   1.125 +
   1.126 +    GrTextureDesc desc;
   1.127 +    generate_bitmap_texture_desc(*bitmap, &desc);
   1.128 +
   1.129 +    if (SkBitmap::kIndex8_Config == bitmap->config()) {
   1.130 +        // build_compressed_data doesn't do npot->pot expansion
   1.131 +        // and paletted textures can't be sub-updated
   1.132 +        if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) {
   1.133 +            size_t imagesize = bitmap->width() * bitmap->height() + kGrColorTableSize;
   1.134 +            SkAutoMalloc storage(imagesize);
   1.135 +
   1.136 +            build_compressed_data(storage.get(), origBitmap);
   1.137 +
   1.138 +            // our compressed data will be trimmed, so pass width() for its
   1.139 +            // "rowBytes", since they are the same now.
   1.140 +
   1.141 +            if (cache) {
   1.142 +                GrCacheID cacheID;
   1.143 +                generate_bitmap_cache_id(origBitmap, &cacheID);
   1.144 +
   1.145 +                GrResourceKey key;
   1.146 +                GrTexture* result = ctx->createTexture(params, desc, cacheID,
   1.147 +                                                       storage.get(), bitmap->width(), &key);
   1.148 +                if (NULL != result) {
   1.149 +                    add_genID_listener(key, origBitmap.pixelRef());
   1.150 +                }
   1.151 +                return result;
   1.152 +            } else {
   1.153 +                GrTexture* result = ctx->lockAndRefScratchTexture(desc,
   1.154 +                                                            GrContext::kExact_ScratchTexMatch);
   1.155 +                result->writePixels(0, 0, bitmap->width(),
   1.156 +                                    bitmap->height(), desc.fConfig,
   1.157 +                                    storage.get());
   1.158 +                return result;
   1.159 +            }
   1.160 +        } else {
   1.161 +            origBitmap.copyTo(&tmpBitmap, kPMColor_SkColorType);
   1.162 +            // now bitmap points to our temp, which has been promoted to 32bits
   1.163 +            bitmap = &tmpBitmap;
   1.164 +            desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config());
   1.165 +        }
   1.166 +    }
   1.167 +
   1.168 +    SkAutoLockPixels alp(*bitmap);
   1.169 +    if (!bitmap->readyToDraw()) {
   1.170 +        return NULL;
   1.171 +    }
   1.172 +    if (cache) {
   1.173 +        // This texture is likely to be used again so leave it in the cache
   1.174 +        GrCacheID cacheID;
   1.175 +        generate_bitmap_cache_id(origBitmap, &cacheID);
   1.176 +
   1.177 +        GrResourceKey key;
   1.178 +        GrTexture* result = ctx->createTexture(params, desc, cacheID,
   1.179 +                                               bitmap->getPixels(), bitmap->rowBytes(), &key);
   1.180 +        if (NULL != result) {
   1.181 +            add_genID_listener(key, origBitmap.pixelRef());
   1.182 +        }
   1.183 +        return result;
   1.184 +   } else {
   1.185 +        // This texture is unlikely to be used again (in its present form) so
   1.186 +        // just use a scratch texture. This will remove the texture from the
   1.187 +        // cache so no one else can find it. Additionally, once unlocked, the
   1.188 +        // scratch texture will go to the end of the list for purging so will
   1.189 +        // likely be available for this volatile bitmap the next time around.
   1.190 +        GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
   1.191 +        result->writePixels(0, 0,
   1.192 +                            bitmap->width(), bitmap->height(),
   1.193 +                            desc.fConfig,
   1.194 +                            bitmap->getPixels(),
   1.195 +                            bitmap->rowBytes());
   1.196 +        return result;
   1.197 +    }
   1.198 +}
   1.199 +
   1.200 +bool GrIsBitmapInCache(const GrContext* ctx,
   1.201 +                       const SkBitmap& bitmap,
   1.202 +                       const GrTextureParams* params) {
   1.203 +    GrCacheID cacheID;
   1.204 +    generate_bitmap_cache_id(bitmap, &cacheID);
   1.205 +
   1.206 +    GrTextureDesc desc;
   1.207 +    generate_bitmap_texture_desc(bitmap, &desc);
   1.208 +    return ctx->isTextureInCache(desc, cacheID, params);
   1.209 +}
   1.210 +
   1.211 +GrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx,
   1.212 +                                           const SkBitmap& bitmap,
   1.213 +                                           const GrTextureParams* params) {
   1.214 +    GrTexture* result = NULL;
   1.215 +
   1.216 +    bool cache = !bitmap.isVolatile();
   1.217 +
   1.218 +    if (cache) {
   1.219 +        // If the bitmap isn't changing try to find a cached copy first.
   1.220 +
   1.221 +        GrCacheID cacheID;
   1.222 +        generate_bitmap_cache_id(bitmap, &cacheID);
   1.223 +
   1.224 +        GrTextureDesc desc;
   1.225 +        generate_bitmap_texture_desc(bitmap, &desc);
   1.226 +
   1.227 +        result = ctx->findAndRefTexture(desc, cacheID, params);
   1.228 +    }
   1.229 +    if (NULL == result) {
   1.230 +        result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
   1.231 +    }
   1.232 +    if (NULL == result) {
   1.233 +        GrPrintf("---- failed to create texture for cache [%d %d]\n",
   1.234 +                    bitmap.width(), bitmap.height());
   1.235 +    }
   1.236 +    return result;
   1.237 +}
   1.238 +
   1.239 +void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) {
   1.240 +    SkASSERT(NULL != texture->getContext());
   1.241 +
   1.242 +    texture->getContext()->unlockScratchTexture(texture);
   1.243 +    texture->unref();
   1.244 +}
   1.245 +
   1.246 +///////////////////////////////////////////////////////////////////////////////
   1.247 +
   1.248 +GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
   1.249 +    switch (config) {
   1.250 +        case SkBitmap::kA8_Config:
   1.251 +            return kAlpha_8_GrPixelConfig;
   1.252 +        case SkBitmap::kIndex8_Config:
   1.253 +            return kIndex_8_GrPixelConfig;
   1.254 +        case SkBitmap::kRGB_565_Config:
   1.255 +            return kRGB_565_GrPixelConfig;
   1.256 +        case SkBitmap::kARGB_4444_Config:
   1.257 +            return kRGBA_4444_GrPixelConfig;
   1.258 +        case SkBitmap::kARGB_8888_Config:
   1.259 +            return kSkia8888_GrPixelConfig;
   1.260 +        default:
   1.261 +            // kNo_Config, kA1_Config missing
   1.262 +            return kUnknown_GrPixelConfig;
   1.263 +    }
   1.264 +}
   1.265 +
   1.266 +// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
   1.267 +// alpha info, that will be considered.
   1.268 +GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
   1.269 +    switch (ct) {
   1.270 +        case kUnknown_SkColorType:
   1.271 +            return kUnknown_GrPixelConfig;
   1.272 +        case kAlpha_8_SkColorType:
   1.273 +            return kAlpha_8_GrPixelConfig;
   1.274 +        case kRGB_565_SkColorType:
   1.275 +            return kRGB_565_GrPixelConfig;
   1.276 +        case kARGB_4444_SkColorType:
   1.277 +            return kRGBA_4444_GrPixelConfig;
   1.278 +        case kRGBA_8888_SkColorType:
   1.279 +            return kRGBA_8888_GrPixelConfig;
   1.280 +        case kBGRA_8888_SkColorType:
   1.281 +            return kBGRA_8888_GrPixelConfig;
   1.282 +        case kIndex_8_SkColorType:
   1.283 +            return kIndex_8_GrPixelConfig;
   1.284 +    }
   1.285 +    SkASSERT(0);    // shouldn't get here
   1.286 +    return kUnknown_GrPixelConfig;
   1.287 +}
   1.288 +
   1.289 +bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
   1.290 +    SkColorType ct;
   1.291 +    switch (config) {
   1.292 +        case kAlpha_8_GrPixelConfig:
   1.293 +            ct = kAlpha_8_SkColorType;
   1.294 +            break;
   1.295 +        case kIndex_8_GrPixelConfig:
   1.296 +            ct = kIndex_8_SkColorType;
   1.297 +            break;
   1.298 +        case kRGB_565_GrPixelConfig:
   1.299 +            ct = kRGB_565_SkColorType;
   1.300 +            break;
   1.301 +        case kRGBA_4444_GrPixelConfig:
   1.302 +            ct = kARGB_4444_SkColorType;
   1.303 +            break;
   1.304 +        case kRGBA_8888_GrPixelConfig:
   1.305 +            ct = kRGBA_8888_SkColorType;
   1.306 +            break;
   1.307 +        case kBGRA_8888_GrPixelConfig:
   1.308 +            ct = kBGRA_8888_SkColorType;
   1.309 +            break;
   1.310 +        default:
   1.311 +            return false;
   1.312 +    }
   1.313 +    if (ctOut) {
   1.314 +        *ctOut = ct;
   1.315 +    }
   1.316 +    return true;
   1.317 +}

mercurial