SkGr.cpp revision 9ed7f573491217079cccf1d81792cf4520a3c0d0
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "SkGr.h"
9378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
10378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrDrawTargetCaps.h"
11378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrGpu.h"
12378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrXferProcessor.h"
138dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org#include "SkColorFilter.h"
14ea476e1725f38688b79aadf4c5e36c10c3141927commit-bot@chromium.org#include "SkConfig8888.h"
159c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#include "SkData.h"
1650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkMessageBus.h"
1750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkPixelRef.h"
1840a1e11ebebe81586f3fec96408fdfd4b51123d2krajcevski#include "SkTextureCompressor.h"
19f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "effects/GrDitherEffect.h"
20378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "effects/GrPorterDuffXferProcessor.h"
21518d83dbc1c899e316e8c896af5defb58b83120fsugoi#include "effects/GrYUVtoRGBEffect.h"
229c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
238c111f783f40470e697310244426362132979ad9krajcevski#ifndef SK_IGNORE_ETC1_SUPPORT
2499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#  include "ktx.h"
259c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#  include "etc1.h"
269c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#endif
27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*  Fill out buffer with the compressed format Ganesh expects from a colortable
29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com based bitmap. [palette (colortable) + indices].
305782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
315782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com we could detect that the colortable.count is <= 16, and then repack the
33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com indices as nibbles to save RAM, but it would take more time (i.e. a lot
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com slower than memcpy), so skipping that for now.
355782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
37ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com as the colortable.count says it is.
38ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
39e79a2dab91a90e26b13bc1ec9b8c6264a1ab22e4bsalomonstatic void build_index8_data(void* buffer, const SkBitmap& bitmap) {
400689d7b12e7c427a077b003d3d8ae759d86f798freed    SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
415782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
427f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    SkAutoLockPixels alp(bitmap);
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!bitmap.readyToDraw()) {
440c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com        SkDEBUGFAIL("bitmap not ready to draw!");
45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return;
46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    SkColorTable* ctable = bitmap.getColorTable();
49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    char* dst = (char*)buffer;
505782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
517111d463cee893a479280c7af41757e709e33ef5reed@google.com    const int count = ctable->count();
527111d463cee893a479280c7af41757e709e33ef5reed@google.com
537111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkDstPixelInfo dstPI;
547111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fColorType = kRGBA_8888_SkColorType;
557111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fAlphaType = kPremul_SkAlphaType;
567111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fPixels = buffer;
577111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fRowBytes = count * sizeof(SkPMColor);
587111d463cee893a479280c7af41757e709e33ef5reed@google.com
597111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkSrcPixelInfo srcPI;
6028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    srcPI.fColorType = kN32_SkColorType;
617111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.fAlphaType = kPremul_SkAlphaType;
62775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein    srcPI.fPixels = ctable->readColors();
637111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.fRowBytes = count * sizeof(SkPMColor);
647111d463cee893a479280c7af41757e709e33ef5reed@google.com
657111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.convertPixelsTo(&dstPI, count, 1);
667111d463cee893a479280c7af41757e709e33ef5reed@google.com
67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // always skip a full 256 number of entries, even if we memcpy'd fewer
68d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon    dst += 256 * sizeof(GrColor);
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
700ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com    if ((unsigned)bitmap.width() == bitmap.rowBytes()) {
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        memcpy(dst, bitmap.getPixels(), bitmap.getSize());
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // need to trim off the extra bytes per row
74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        size_t width = bitmap.width();
75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        size_t rowBytes = bitmap.rowBytes();
76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        const char* src = (const char*)bitmap.getPixels();
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        for (int y = 0; y < bitmap.height(); y++) {
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            memcpy(dst, src, width);
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            src += rowBytes;
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            dst += width;
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com////////////////////////////////////////////////////////////////////////////////
86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
870797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.comstatic void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) {
880797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
890797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    // are unique.
900797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    uint32_t genID = bitmap.getGenerationID();
91672588b684d484dce6ae251e9e163e4a46924322reed@google.com    SkIPoint origin = bitmap.pixelRefOrigin();
92672588b684d484dce6ae251e9e163e4a46924322reed@google.com    int16_t width = SkToS16(bitmap.width());
93672588b684d484dce6ae251e9e163e4a46924322reed@google.com    int16_t height = SkToS16(bitmap.height());
940797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
952859eb74f9c87471b2429cd12b84144b97157efbskia.committer@gmail.com    GrCacheID::Key key;
96672588b684d484dce6ae251e9e163e4a46924322reed@google.com    memcpy(key.fData8 +  0, &genID,     4);
97672588b684d484dce6ae251e9e163e4a46924322reed@google.com    memcpy(key.fData8 +  4, &origin.fX, 4);
98672588b684d484dce6ae251e9e163e4a46924322reed@google.com    memcpy(key.fData8 +  8, &origin.fY, 4);
99672588b684d484dce6ae251e9e163e4a46924322reed@google.com    memcpy(key.fData8 + 12, &width,     2);
100672588b684d484dce6ae251e9e163e4a46924322reed@google.com    memcpy(key.fData8 + 14, &height,    2);
101672588b684d484dce6ae251e9e163e4a46924322reed@google.com    static const size_t kKeyDataSize = 16;
10210a9fb86a9cd11f7fd590410e2aa0906587555e6bsalomon@google.com    memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize);
103672588b684d484dce6ae251e9e163e4a46924322reed@google.com    GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize);
1040797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain();
1050797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    id->reset(gBitmapTextureDomain, key);
1060797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com}
1070797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
108f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomonstatic void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrSurfaceDesc* desc) {
109f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    desc->fFlags = kNone_GrSurfaceFlags;
1100797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    desc->fWidth = bitmap.width();
1110797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    desc->fHeight = bitmap.height();
1123adcc3403377c0b9a7afde6db8e0432325413a10commit-bot@chromium.org    desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
1130797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    desc->fSampleCnt = 0;
1140797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com}
1150797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
11650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgnamespace {
11750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
11850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
11950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgclass GrResourceInvalidator : public SkPixelRef::GenIDChangeListener {
12050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgpublic:
12150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    explicit GrResourceInvalidator(GrResourceKey key) : fKey(key) {}
12250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgprivate:
12350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    GrResourceKey fKey;
12450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
12550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    virtual void onChange() SK_OVERRIDE {
12650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        const GrResourceInvalidatedMessage message = { fKey };
12750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        SkMessageBus<GrResourceInvalidatedMessage>::Post(message);
12850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    }
12950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org};
13050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
13150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}  // namespace
13250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
13350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.orgstatic void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) {
13449f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(pixelRef);
13550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org    pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
13650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org}
13750a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
1380249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoistatic GrTexture* sk_gr_allocate_texture(GrContext* ctx,
1390249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                         bool cache,
1400249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                         const GrTextureParams* params,
1410249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                         const SkBitmap& bm,
142f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon                                         GrSurfaceDesc desc,
1430249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                         const void* pixels,
1440249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                         size_t rowBytes) {
1450249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    GrTexture* result;
1460249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    if (cache) {
1470249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        // This texture is likely to be used again so leave it in the cache
1480249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        GrCacheID cacheID;
1490249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        generate_bitmap_cache_id(bm, &cacheID);
1500249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi
1510249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        GrResourceKey key;
1520249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        result = ctx->createTexture(params, desc, cacheID, pixels, rowBytes, &key);
1530249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        if (result) {
1540249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi            add_genID_listener(key, bm.pixelRef());
1550249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        }
1560249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi   } else {
1570249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        // This texture is unlikely to be used again (in its present form) so
1580249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        // just use a scratch texture. This will remove the texture from the
1590249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        // cache so no one else can find it. Additionally, once unlocked, the
1600249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        // scratch texture will go to the end of the list for purging so will
1610249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        // likely be available for this volatile bitmap the next time around.
162e30597375c19dfb5197fd065a3d1768401eb00fabsalomon        result = ctx->refScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
1630249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        if (pixels) {
1640249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi            result->writePixels(0, 0, bm.width(), bm.height(), desc.fConfig, pixels, rowBytes);
1650249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        }
1660249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    }
1670249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    return result;
1680249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi}
1690249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi
1708c111f783f40470e697310244426362132979ad9krajcevski#ifndef SK_IGNORE_ETC1_SUPPORT
1710249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoistatic GrTexture *load_etc1_texture(GrContext* ctx, bool cache,
1729c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski                                    const GrTextureParams* params,
173f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon                                    const SkBitmap &bm, GrSurfaceDesc desc) {
17499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski    SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
1759c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
1769c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    // Is this even encoded data?
1779c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    if (NULL == data) {
1789c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        return NULL;
1799c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    }
1809c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
1819c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    // Is this a valid PKM encoded data?
1829c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    const uint8_t *bytes = data->bytes();
18399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski    if (etc1_pkm_is_valid(bytes)) {
18499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        uint32_t encodedWidth = etc1_pkm_get_width(bytes);
18599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        uint32_t encodedHeight = etc1_pkm_get_height(bytes);
18699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski
18799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // Does the data match the dimensions of the bitmap? If not,
18899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // then we don't know how to scale the image to match it...
18999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        if (encodedWidth != static_cast<uint32_t>(bm.width()) ||
19099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski            encodedHeight != static_cast<uint32_t>(bm.height())) {
19199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski            return NULL;
19299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        }
19399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski
19499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // Everything seems good... skip ahead to the data.
19599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        bytes += ETC_PKM_HEADER_SIZE;
19699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        desc.fConfig = kETC1_GrPixelConfig;
19799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski    } else if (SkKTXFile::is_ktx(bytes)) {
19899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        SkKTXFile ktx(data);
1999c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
20099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // Is it actually an ETC1 texture?
20140a1e11ebebe81586f3fec96408fdfd4b51123d2krajcevski        if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) {
20299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski            return NULL;
20399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        }
20499ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski
20599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // Does the data match the dimensions of the bitmap? If not,
20699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // then we don't know how to scale the image to match it...
20799ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        if (ktx.width() != bm.width() || ktx.height() != bm.height()) {
20899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski            return NULL;
209775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein        }
2109c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
21199ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        bytes = ktx.pixelData();
21299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        desc.fConfig = kETC1_GrPixelConfig;
21399ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski    } else {
2149c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        return NULL;
2159c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    }
2169c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
2170249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    return sk_gr_allocate_texture(ctx, cache, params, bm, desc, bytes, 0);
2189c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski}
2198c111f783f40470e697310244426362132979ad9krajcevski#endif   // SK_IGNORE_ETC1_SUPPORT
2209c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
2210249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoistatic GrTexture *load_yuv_texture(GrContext* ctx, bool cache, const GrTextureParams* params,
222f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon                                   const SkBitmap& bm, const GrSurfaceDesc& desc) {
223ff58e4679b9473ce19abb81a3e50fc6a18f0981dsugoi    // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
224ff58e4679b9473ce19abb81a3e50fc6a18f0981dsugoi    if ((bm.pixelRef()->info().width()  != bm.info().width()) ||
225ff58e4679b9473ce19abb81a3e50fc6a18f0981dsugoi        (bm.pixelRef()->info().height() != bm.info().height())) {
226ff58e4679b9473ce19abb81a3e50fc6a18f0981dsugoi        return NULL;
227ff58e4679b9473ce19abb81a3e50fc6a18f0981dsugoi    }
228ff58e4679b9473ce19abb81a3e50fc6a18f0981dsugoi
229518d83dbc1c899e316e8c896af5defb58b83120fsugoi    SkPixelRef* pixelRef = bm.pixelRef();
230518d83dbc1c899e316e8c896af5defb58b83120fsugoi    SkISize yuvSizes[3];
231abaef86f2b37d8a939506a2076da07f6db456951rileya    if ((NULL == pixelRef) || !pixelRef->getYUV8Planes(yuvSizes, NULL, NULL, NULL)) {
232518d83dbc1c899e316e8c896af5defb58b83120fsugoi        return NULL;
233518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
234518d83dbc1c899e316e8c896af5defb58b83120fsugoi
235518d83dbc1c899e316e8c896af5defb58b83120fsugoi    // Allocate the memory for YUV
236518d83dbc1c899e316e8c896af5defb58b83120fsugoi    size_t totalSize(0);
237518d83dbc1c899e316e8c896af5defb58b83120fsugoi    size_t sizes[3], rowBytes[3];
238518d83dbc1c899e316e8c896af5defb58b83120fsugoi    for (int i = 0; i < 3; ++i) {
239518d83dbc1c899e316e8c896af5defb58b83120fsugoi        rowBytes[i] = yuvSizes[i].fWidth;
240518d83dbc1c899e316e8c896af5defb58b83120fsugoi        totalSize  += sizes[i] = rowBytes[i] * yuvSizes[i].fHeight;
241518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
242518d83dbc1c899e316e8c896af5defb58b83120fsugoi    SkAutoMalloc storage(totalSize);
243518d83dbc1c899e316e8c896af5defb58b83120fsugoi    void* planes[3];
244518d83dbc1c899e316e8c896af5defb58b83120fsugoi    planes[0] = storage.get();
245518d83dbc1c899e316e8c896af5defb58b83120fsugoi    planes[1] = (uint8_t*)planes[0] + sizes[0];
246518d83dbc1c899e316e8c896af5defb58b83120fsugoi    planes[2] = (uint8_t*)planes[1] + sizes[1];
247518d83dbc1c899e316e8c896af5defb58b83120fsugoi
248abaef86f2b37d8a939506a2076da07f6db456951rileya    SkYUVColorSpace colorSpace;
249abaef86f2b37d8a939506a2076da07f6db456951rileya
250518d83dbc1c899e316e8c896af5defb58b83120fsugoi    // Get the YUV planes
251abaef86f2b37d8a939506a2076da07f6db456951rileya    if (!pixelRef->getYUV8Planes(yuvSizes, planes, rowBytes, &colorSpace)) {
252518d83dbc1c899e316e8c896af5defb58b83120fsugoi        return NULL;
253518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
254518d83dbc1c899e316e8c896af5defb58b83120fsugoi
255f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    GrSurfaceDesc yuvDesc;
256518d83dbc1c899e316e8c896af5defb58b83120fsugoi    yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
257e30597375c19dfb5197fd065a3d1768401eb00fabsalomon    SkAutoTUnref<GrTexture> yuvTextures[3];
258518d83dbc1c899e316e8c896af5defb58b83120fsugoi    for (int i = 0; i < 3; ++i) {
259518d83dbc1c899e316e8c896af5defb58b83120fsugoi        yuvDesc.fWidth  = yuvSizes[i].fWidth;
260518d83dbc1c899e316e8c896af5defb58b83120fsugoi        yuvDesc.fHeight = yuvSizes[i].fHeight;
261e30597375c19dfb5197fd065a3d1768401eb00fabsalomon        yuvTextures[i].reset(
262e30597375c19dfb5197fd065a3d1768401eb00fabsalomon            ctx->refScratchTexture(yuvDesc, GrContext::kApprox_ScratchTexMatch));
263e30597375c19dfb5197fd065a3d1768401eb00fabsalomon        if (!yuvTextures[i] ||
264e30597375c19dfb5197fd065a3d1768401eb00fabsalomon            !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
265e30597375c19dfb5197fd065a3d1768401eb00fabsalomon                                         yuvDesc.fConfig, planes[i], rowBytes[i])) {
266518d83dbc1c899e316e8c896af5defb58b83120fsugoi            return NULL;
267518d83dbc1c899e316e8c896af5defb58b83120fsugoi        }
268518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
269518d83dbc1c899e316e8c896af5defb58b83120fsugoi
270f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    GrSurfaceDesc rtDesc = desc;
271518d83dbc1c899e316e8c896af5defb58b83120fsugoi    rtDesc.fFlags = rtDesc.fFlags |
272f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon                    kRenderTarget_GrSurfaceFlag |
273f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon                    kNoStencil_GrSurfaceFlag;
274518d83dbc1c899e316e8c896af5defb58b83120fsugoi
2750249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    GrTexture* result = sk_gr_allocate_texture(ctx, cache, params, bm, rtDesc, NULL, 0);
276518d83dbc1c899e316e8c896af5defb58b83120fsugoi
277518d83dbc1c899e316e8c896af5defb58b83120fsugoi    GrRenderTarget* renderTarget = result ? result->asRenderTarget() : NULL;
27849f085dddff10473b6ebf832a974288300224e60bsalomon    if (renderTarget) {
279e30597375c19dfb5197fd065a3d1768401eb00fabsalomon        SkAutoTUnref<GrFragmentProcessor> yuvToRgbProcessor(
280e30597375c19dfb5197fd065a3d1768401eb00fabsalomon            GrYUVtoRGBEffect::Create(yuvTextures[0], yuvTextures[1], yuvTextures[2], colorSpace));
281518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrPaint paint;
282b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        paint.addColorProcessor(yuvToRgbProcessor);
283518d83dbc1c899e316e8c896af5defb58b83120fsugoi        SkRect r = SkRect::MakeWH(SkIntToScalar(yuvSizes[0].fWidth),
284518d83dbc1c899e316e8c896af5defb58b83120fsugoi                                  SkIntToScalar(yuvSizes[0].fHeight));
285518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrContext::AutoRenderTarget autoRT(ctx, renderTarget);
286518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrContext::AutoClip ac(ctx, GrContext::AutoClip::kWideOpen_InitialClip);
2875531d51ce7426bdae7563547326fcf0bf926a083joshualitt        ctx->drawRect(paint, SkMatrix::I(), r);
288518d83dbc1c899e316e8c896af5defb58b83120fsugoi    } else {
289518d83dbc1c899e316e8c896af5defb58b83120fsugoi        SkSafeSetNull(result);
290518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
291518d83dbc1c899e316e8c896af5defb58b83120fsugoi
292518d83dbc1c899e316e8c896af5defb58b83120fsugoi    return result;
293518d83dbc1c899e316e8c896af5defb58b83120fsugoi}
294518d83dbc1c899e316e8c896af5defb58b83120fsugoi
2951f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comstatic GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
2960797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                                              bool cache,
2971f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                              const GrTextureParams* params,
2981f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                              const SkBitmap& origBitmap) {
299ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    SkBitmap tmpBitmap;
300ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
301ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    const SkBitmap* bitmap = &origBitmap;
3025782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
303f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    GrSurfaceDesc desc;
3040797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    generate_bitmap_texture_desc(*bitmap, &desc);
3055782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
3060689d7b12e7c427a077b003d3d8ae759d86f798freed    if (kIndex_8_SkColorType == bitmap->colorType()) {
307ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // build_compressed_data doesn't do npot->pot expansion
308ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // and paletted textures can't be sub-updated
309e79a2dab91a90e26b13bc1ec9b8c6264a1ab22e4bsalomon        if (cache && ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) {
310d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon            size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
311d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon                                                          bitmap->width(), bitmap->height());
312d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon            SkAutoMalloc storage(imageSize);
313e79a2dab91a90e26b13bc1ec9b8c6264a1ab22e4bsalomon            build_index8_data(storage.get(), origBitmap);
314ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
315ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // our compressed data will be trimmed, so pass width() for its
316ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // "rowBytes", since they are the same now.
3170249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi            return sk_gr_allocate_texture(ctx, cache, params, origBitmap,
3180249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                          desc, storage.get(), bitmap->width());
319ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        } else {
32028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org            origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
321ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // now bitmap points to our temp, which has been promoted to 32bits
322ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            bitmap = &tmpBitmap;
3233adcc3403377c0b9a7afde6db8e0432325413a10commit-bot@chromium.org            desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
324ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
325309e86912445879651d52ebbedb67b4ff3f1516ckrajcevski    }
3269c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
3279c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    // Is this an ETC1 encoded texture?
3288c111f783f40470e697310244426362132979ad9krajcevski#ifndef SK_IGNORE_ETC1_SUPPORT
3299a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski    else if (
33077cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        // We do not support scratch ETC1 textures, hence they should all be at least
33177cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        // trying to go to the cache.
33277cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        cache
3339a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // Make sure that the underlying device supports ETC1 textures before we go ahead
3349a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // and check the data.
33577cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)
3369a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // If the bitmap had compressed data and was then uncompressed, it'll still return
3379a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // compressed data on 'refEncodedData' and upload it. Probably not good, since if
3389a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // the bitmap has available pixels, then they might not be what the decompressed
3399a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // data is.
3409a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        && !(bitmap->readyToDraw())) {
3410249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        GrTexture *texture = load_etc1_texture(ctx, cache, params, *bitmap, desc);
34249f085dddff10473b6ebf832a974288300224e60bsalomon        if (texture) {
3439c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski            return texture;
3449c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        }
3455782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com    }
3468c111f783f40470e697310244426362132979ad9krajcevski#endif   // SK_IGNORE_ETC1_SUPPORT
347ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
348518d83dbc1c899e316e8c896af5defb58b83120fsugoi    else {
3490249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        GrTexture *texture = load_yuv_texture(ctx, cache, params, *bitmap, desc);
35049f085dddff10473b6ebf832a974288300224e60bsalomon        if (texture) {
351518d83dbc1c899e316e8c896af5defb58b83120fsugoi            return texture;
352518d83dbc1c899e316e8c896af5defb58b83120fsugoi        }
353518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
3547f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    SkAutoLockPixels alp(*bitmap);
3557f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    if (!bitmap->readyToDraw()) {
3567f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com        return NULL;
3577f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    }
35850a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
3590249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    return sk_gr_allocate_texture(ctx, cache, params, origBitmap, desc,
3600249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                  bitmap->getPixels(), bitmap->rowBytes());
361ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
362ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
3639ed7f573491217079cccf1d81792cf4520a3c0d0bsalomonstatic GrTexture* get_texture_backing_bmp(const SkBitmap& bitmap, const GrContext* context,
3649ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon                                          const GrTextureParams* params) {
3659ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    if (GrTexture* texture = bitmap.getTexture()) {
3669ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        // Our texture-resizing-for-tiling used to upscale NPOT textures for tiling only works with
3679ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        // content-key cached resources. Rather than invest in that legacy code path, we'll just
3689ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        // take the horribly slow route of causing a cache miss which will cause the pixels to be
3699ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        // read and reuploaded to a texture with a content key.
3709ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        if (params && !context->getGpu()->caps()->npotTextureTileSupport() &&
3719ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon            (params->isTiled() || GrTextureParams::kMipMap_FilterMode == params->filterMode())) {
3729ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon            return NULL;
3739ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        }
3749ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        return texture;
3759ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    }
3769ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    return NULL;
3779ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon}
3789ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon
3790797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.combool GrIsBitmapInCache(const GrContext* ctx,
3800797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                       const SkBitmap& bitmap,
3810797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                       const GrTextureParams* params) {
3829ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    if (get_texture_backing_bmp(bitmap, ctx, params)) {
3839ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        return true;
3849ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    }
3859ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon
3860797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    GrCacheID cacheID;
3870797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    generate_bitmap_cache_id(bitmap, &cacheID);
3880797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
389f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon    GrSurfaceDesc desc;
3900797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    generate_bitmap_texture_desc(bitmap, &desc);
3910797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    return ctx->isTextureInCache(desc, cacheID, params);
3920797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com}
393ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
394bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomonGrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
395bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                                    const SkBitmap& bitmap,
396bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                                    const GrTextureParams* params) {
3979ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    GrTexture* result = get_texture_backing_bmp(bitmap, ctx, params);
3989ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    if (result) {
3999ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon        return SkRef(result);
4009ed7f573491217079cccf1d81792cf4520a3c0d0bsalomon    }
40124f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
4020797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    bool cache = !bitmap.isVolatile();
4039c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com
4040797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (cache) {
4050797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        // If the bitmap isn't changing try to find a cached copy first.
4064b86e3428b115202e82d49a0914ea8ab6dc25940bsalomon@google.com
4070797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        GrCacheID cacheID;
4080797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        generate_bitmap_cache_id(bitmap, &cacheID);
4090b6ad2297fbf43466950690102c1c9c150f2a972bsalomon@google.com
410f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon        GrSurfaceDesc desc;
4110797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        generate_bitmap_texture_desc(bitmap, &desc);
4120797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
41395ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        result = ctx->findAndRefTexture(desc, cacheID, params);
4140797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    }
4150797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (NULL == result) {
4160797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
41724f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com    }
4181f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == result) {
41938406c82b913350e55fa04af8c1941cd9b4aff52tfarina        SkDebugf("---- failed to create texture for cache [%d %d]\n",
42038406c82b913350e55fa04af8c1941cd9b4aff52tfarina                 bitmap.width(), bitmap.height());
42124f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com    }
4221f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return result;
42324f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com}
42424f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
42524f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com///////////////////////////////////////////////////////////////////////////////
42624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
42715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
42815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org// alpha info, that will be considered.
42915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgGrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
43015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    switch (ct) {
43115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kUnknown_SkColorType:
43215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kUnknown_GrPixelConfig;
43315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kAlpha_8_SkColorType:
43415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kAlpha_8_GrPixelConfig;
43515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kRGB_565_SkColorType:
43615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kRGB_565_GrPixelConfig;
43715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kARGB_4444_SkColorType:
43815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kRGBA_4444_GrPixelConfig;
43915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kRGBA_8888_SkColorType:
44015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kRGBA_8888_GrPixelConfig;
44115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kBGRA_8888_SkColorType:
44215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kBGRA_8888_GrPixelConfig;
44315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kIndex_8_SkColorType:
44415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kIndex_8_GrPixelConfig;
44515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    }
44615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkASSERT(0);    // shouldn't get here
44715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return kUnknown_GrPixelConfig;
44815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org}
44915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org
450bf790232f6d94b54239dbc210d8beee7411ca458reed@google.combool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
451bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    SkColorType ct;
452bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    switch (config) {
453bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kAlpha_8_GrPixelConfig:
454bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kAlpha_8_SkColorType;
455bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
456bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kIndex_8_GrPixelConfig:
457bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kIndex_8_SkColorType;
458bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
459bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kRGB_565_GrPixelConfig:
460bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kRGB_565_SkColorType;
461bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
462bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kRGBA_4444_GrPixelConfig:
463bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kARGB_4444_SkColorType;
464bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
465bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kRGBA_8888_GrPixelConfig:
466bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kRGBA_8888_SkColorType;
467bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
468bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kBGRA_8888_GrPixelConfig:
469bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kBGRA_8888_SkColorType;
470bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
471bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        default:
472bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            return false;
473bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
474bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (ctOut) {
475bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        *ctOut = ct;
476bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
477bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    return true;
478bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com}
4798dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4808dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
4818dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
48283d081ae1d731b5039e99823620f5e287542ee39bsalomonvoid SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor paintColor,
4838dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org                             bool constantColor, GrPaint* grPaint) {
4848dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4858dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    grPaint->setDither(skPaint.isDither());
4868dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    grPaint->setAntiAlias(skPaint.isAntiAlias());
4878dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4888dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkXfermode* mode = skPaint.getXfermode();
489378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    GrFragmentProcessor* fragmentProcessor = NULL;
490378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    GrXPFactory* xpFactory = NULL;
4919513143efa734bef0c1a0c7f945022572dbc8518egdaniel    if (SkXfermode::AsFragmentProcessorOrXPFactory(mode, &fragmentProcessor, &xpFactory)) {
492378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel        if (fragmentProcessor) {
493378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel            SkASSERT(NULL == xpFactory);
494378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel            grPaint->addColorProcessor(fragmentProcessor)->unref();
495c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel            xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode);
4968dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        }
4978dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    } else {
4988dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        // Fall back to src-over
499c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel        xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
5008dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
501378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    SkASSERT(xpFactory);
502378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    grPaint->setXPFactory(xpFactory)->unref();
503775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein
5049de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    //set the color of the paint to the one of the parameter
50583d081ae1d731b5039e99823620f5e287542ee39bsalomon    grPaint->setColor(paintColor);
5068dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
5078dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkColorFilter* colorFilter = skPaint.getColorFilter();
50849f085dddff10473b6ebf832a974288300224e60bsalomon    if (colorFilter) {
5098dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        // if the source color is a constant then apply the filter here once rather than per pixel
5108dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        // in a shader.
5118dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        if (constantColor) {
5128dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            SkColor filtered = colorFilter->filterColor(skPaint.getColor());
5138dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            grPaint->setColor(SkColor2GrColor(filtered));
5148dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        } else {
515b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkAutoTUnref<GrFragmentProcessor> fp(colorFilter->asFragmentProcessor(context));
516b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            if (fp.get()) {
517b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                grPaint->addColorProcessor(fp);
5188dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            }
5198dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        }
5208dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
521f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
522f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#ifndef SK_IGNORE_GPU_DITHER
523f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // If the dither flag is set, then we need to see if the underlying context
524f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // supports it. If not, then install a dither effect.
525f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    if (skPaint.isDither() && grPaint->numColorStages() > 0) {
526f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        // What are we rendering into?
527f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        const GrRenderTarget *target = context->getRenderTarget();
52849f085dddff10473b6ebf832a974288300224e60bsalomon        SkASSERT(target);
529f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
530f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        // Suspect the dithering flag has no effect on these configs, otherwise
531f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        // fall back on setting the appropriate state.
532f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        if (target->config() == kRGBA_8888_GrPixelConfig ||
533f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            target->config() == kBGRA_8888_GrPixelConfig) {
534f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            // The dither flag is set and the target is likely
535f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            // not going to be dithered by the GPU.
536b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkAutoTUnref<GrFragmentProcessor> fp(GrDitherEffect::Create());
537b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            if (fp.get()) {
538b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                grPaint->addColorProcessor(fp);
539f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                grPaint->setDither(false);
540f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            }
541f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        }
542f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    }
543f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#endif
5448dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org}
5458dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
5465531d51ce7426bdae7563547326fcf0bf926a083joshualittvoid SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
5478dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org                           bool constantColor, GrPaint* grPaint) {
5488dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkShader* shader = skPaint.getShader();
5498dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    if (NULL == shader) {
5509de5b514d38c5b36066bcdc14fba2f7e5196d372dandov        SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()),
5519de5b514d38c5b36066bcdc14fba2f7e5196d372dandov                                constantColor, grPaint);
5528dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        return;
5538dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
5548dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
55583d081ae1d731b5039e99823620f5e287542ee39bsalomon    GrColor paintColor = SkColor2GrColor(skPaint.getColor());
556f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
557f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // Start a new block here in order to preserve our context state after calling
558b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    // asFragmentProcessor(). Since these calls get passed back to the client, we don't really
559f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // want them messing around with the context.
560f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    {
561b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        // SkShader::asFragmentProcessor() may do offscreen rendering. Save off the current RT,
5625531d51ce7426bdae7563547326fcf0bf926a083joshualitt        // and clip
563f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        GrContext::AutoRenderTarget art(context, NULL);
564f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
565f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
56683d081ae1d731b5039e99823620f5e287542ee39bsalomon        // Allow the shader to modify paintColor and also create an effect to be installed as
56783d081ae1d731b5039e99823620f5e287542ee39bsalomon        // the first color effect on the GrPaint.
568b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        GrFragmentProcessor* fp = NULL;
5695531d51ce7426bdae7563547326fcf0bf926a083joshualitt        if (shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, &fp) && fp) {
570b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            grPaint->addColorProcessor(fp)->unref();
571f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            constantColor = false;
572f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        }
5738dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
574f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
575b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    // The grcolor is automatically set when calling asFragmentProcessor.
5769de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
57783d081ae1d731b5039e99823620f5e287542ee39bsalomon    SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint);
5788dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org}
579