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