SkGr.cpp revision 1f47f4f7325971dd53991e2bb02da94fa7c6d962
1ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 10ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "SkGr.h" 12ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/* Fill out buffer with the compressed format Ganesh expects from a colortable 14ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com based bitmap. [palette (colortable) + indices]. 155782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 165782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com At the moment Ganesh only supports 8bit version. If Ganesh allowed we others 17ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com we could detect that the colortable.count is <= 16, and then repack the 18ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com indices as nibbles to save RAM, but it would take more time (i.e. a lot 19ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com slower than memcpy), so skipping that for now. 205782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 21ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big 22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com as the colortable.count says it is. 23ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void build_compressed_data(void* buffer, const SkBitmap& bitmap) { 25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com SkASSERT(SkBitmap::kIndex8_Config == bitmap.config()); 265782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com SkAutoLockPixels apl(bitmap); 28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!bitmap.readyToDraw()) { 290c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("bitmap not ready to draw!"); 30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return; 31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com SkColorTable* ctable = bitmap.getColorTable(); 34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com char* dst = (char*)buffer; 355782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com memcpy(dst, ctable->lockColors(), ctable->count() * sizeof(SkPMColor)); 37ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com ctable->unlockColors(false); 385782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // always skip a full 256 number of entries, even if we memcpy'd fewer 40fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com dst += kGrColorTableSize; 41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (bitmap.width() == bitmap.rowBytes()) { 43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com memcpy(dst, bitmap.getPixels(), bitmap.getSize()); 44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // need to trim off the extra bytes per row 46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com size_t width = bitmap.width(); 47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com size_t rowBytes = bitmap.rowBytes(); 48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const char* src = (const char*)bitmap.getPixels(); 49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com for (int y = 0; y < bitmap.height(); y++) { 50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com memcpy(dst, src, width); 51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com src += rowBytes; 52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com dst += width; 53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com//////////////////////////////////////////////////////////////////////////////// 58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 591f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comstatic GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, 601f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com uint64_t key, 611f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com const GrTextureParams* params, 621f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com const SkBitmap& origBitmap) { 63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com SkAutoLockPixels alp(origBitmap); 6450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com 65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!origBitmap.readyToDraw()) { 661f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return NULL; 67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com SkBitmap tmpBitmap; 70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const SkBitmap* bitmap = &origBitmap; 725782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 7375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrTextureDesc desc; 7475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fWidth = bitmap->width(); 7575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fHeight = bitmap->height(); 7624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config()); 779c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com 789c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrCacheData cacheData(key); 795782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (SkBitmap::kIndex8_Config == bitmap->config()) { 81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // build_compressed_data doesn't do npot->pot expansion 82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // and paletted textures can't be sub-updated 83b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com if (ctx->supportsIndex8PixelConfig(params, 84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com bitmap->width(), bitmap->height())) { 855782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com size_t imagesize = bitmap->width() * bitmap->height() + 86fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com kGrColorTableSize; 87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com SkAutoMalloc storage(imagesize); 885782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com 89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com build_compressed_data(storage.get(), origBitmap); 90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // our compressed data will be trimmed, so pass width() for its 92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // "rowBytes", since they are the same now. 934ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com 949c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com if (GrCacheData::kScratch_CacheID != key) { 959c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com return ctx->createAndLockTexture(params, desc, cacheData, 969c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com storage.get(), 974ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com bitmap->width()); 984ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com } else { 991f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrTexture* result = ctx->lockScratchTexture(desc, 1001f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrContext::kExact_ScratchTexMatch); 1011f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com result->writePixels(0, 0, bitmap->width(), 1021f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com bitmap->height(), desc.fConfig, 1031f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com storage.get(), 0); 1041f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return result; 1054ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com } 106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config); 109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // now bitmap points to our temp, which has been promoted to 32bits 110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com bitmap = &tmpBitmap; 111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 1125782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com } 113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 11424f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config()); 1159c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com if (GrCacheData::kScratch_CacheID != key) { 1169c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // This texture is likely to be used again so leave it in the cache 1179c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // but locked. 1189c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com return ctx->createAndLockTexture(params, desc, cacheData, 11950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com bitmap->getPixels(), 12050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com bitmap->rowBytes()); 1214ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com } else { 1229c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // This texture is unlikely to be used again (in its present form) so 1239c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // just use a scratch texture. This will remove the texture from the 1249c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // cache so no one else can find it. Additionally, once unlocked, the 1259c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // scratch texture will go to the end of the list for purging so will 1269c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // likely be available for this volatile bitmap the next time around. 1271f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrTexture* result = ctx->lockScratchTexture(desc, 1281f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrContext::kExact_ScratchTexMatch); 1291f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com result->writePixels(0, 0, 1301f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com bitmap->width(), bitmap->height(), 1311f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com desc.fConfig, 1321f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com bitmap->getPixels(), 1331f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com bitmap->rowBytes()); 1341f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return result; 1354ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com } 136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 138ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/////////////////////////////////////////////////////////////////////////////// 139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 1401f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrLockCachedBitmapTexture(GrContext* ctx, 1411f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com const SkBitmap& bitmap, 1421f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com const GrTextureParams* params) { 1431f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrTexture* result = NULL; 14424f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com 14524f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com if (!bitmap.isVolatile()) { 1469c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com // If the bitmap isn't changing try to find a cached copy first 14724f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com uint64_t key = bitmap.getGenerationID(); 14824f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com key |= ((uint64_t) bitmap.pixelRefOffset()) << 32; 14924f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com 15024f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com GrTextureDesc desc; 15124f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com desc.fWidth = bitmap.width(); 15224f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com desc.fHeight = bitmap.height(); 15324f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); 15424f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com 1559c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrCacheData cacheData(key); 1569c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com 1571f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com result = ctx->findAndLockTexture(desc, cacheData, params); 1581f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL == result) { 1591f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com result = sk_gr_create_bitmap_texture(ctx, key, params, bitmap); 16024f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com } 16124f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com } else { 1621f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com result = sk_gr_create_bitmap_texture(ctx, GrCacheData::kScratch_CacheID, params, bitmap); 16324f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com } 1641f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL == result) { 16524f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com GrPrintf("---- failed to create texture for cache [%d %d]\n", 16624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com bitmap.width(), bitmap.height()); 16724f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com } 1681f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return result; 16924f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com} 17024f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com 1711f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrUnlockCachedBitmapTexture(GrTexture* texture) { 1721f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrAssert(NULL != texture->getContext()); 1731f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com 1741f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com texture->getContext()->unlockTexture(texture); 17524f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com} 17624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com 17724f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com/////////////////////////////////////////////////////////////////////////////// 17824f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com 17924f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.comGrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) { 180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com switch (config) { 181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com case SkBitmap::kA8_Config: 182669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return kAlpha_8_GrPixelConfig; 183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com case SkBitmap::kIndex8_Config: 184669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return kIndex_8_GrPixelConfig; 185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com case SkBitmap::kRGB_565_Config: 186669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return kRGB_565_GrPixelConfig; 187ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com case SkBitmap::kARGB_4444_Config: 188669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return kRGBA_4444_GrPixelConfig; 189ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com case SkBitmap::kARGB_8888_Config: 190c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com return kSkia8888_PM_GrPixelConfig; 191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com default: 192a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com // kNo_Config, kA1_Config missing, and kRLE_Index8_Config 193669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return kUnknown_GrPixelConfig; 194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 197