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"
98dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org#include "SkColorFilter.h"
10ea476e1725f38688b79aadf4c5e36c10c3141927commit-bot@chromium.org#include "SkConfig8888.h"
119c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#include "SkData.h"
1250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkMessageBus.h"
1350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "SkPixelRef.h"
1440a1e11ebebe81586f3fec96408fdfd4b51123d2krajcevski#include "SkTextureCompressor.h"
1550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org#include "GrResourceCache.h"
169c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#include "GrGpu.h"
17f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "effects/GrDitherEffect.h"
189c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#include "GrDrawTargetCaps.h"
19518d83dbc1c899e316e8c896af5defb58b83120fsugoi#include "effects/GrYUVtoRGBEffect.h"
209c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
218c111f783f40470e697310244426362132979ad9krajcevski#ifndef SK_IGNORE_ETC1_SUPPORT
2299ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski#  include "ktx.h"
239c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#  include "etc1.h"
249c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski#endif
25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*  Fill out buffer with the compressed format Ganesh expects from a colortable
27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com based bitmap. [palette (colortable) + indices].
285782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
295782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com we could detect that the colortable.count is <= 16, and then repack the
31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com indices as nibbles to save RAM, but it would take more time (i.e. a lot
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com slower than memcpy), so skipping that for now.
335782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com as the colortable.count says it is.
36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
37ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
380689d7b12e7c427a077b003d3d8ae759d86f798freed    SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
395782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
407f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    SkAutoLockPixels alp(bitmap);
41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!bitmap.readyToDraw()) {
420c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com        SkDEBUGFAIL("bitmap not ready to draw!");
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return;
44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    SkColorTable* ctable = bitmap.getColorTable();
47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    char* dst = (char*)buffer;
485782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
497111d463cee893a479280c7af41757e709e33ef5reed@google.com    const int count = ctable->count();
507111d463cee893a479280c7af41757e709e33ef5reed@google.com
517111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkDstPixelInfo dstPI;
527111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fColorType = kRGBA_8888_SkColorType;
537111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fAlphaType = kPremul_SkAlphaType;
547111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fPixels = buffer;
557111d463cee893a479280c7af41757e709e33ef5reed@google.com    dstPI.fRowBytes = count * sizeof(SkPMColor);
567111d463cee893a479280c7af41757e709e33ef5reed@google.com
577111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkSrcPixelInfo srcPI;
5828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    srcPI.fColorType = kN32_SkColorType;
597111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.fAlphaType = kPremul_SkAlphaType;
607111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.fPixels = ctable->lockColors();
617111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.fRowBytes = count * sizeof(SkPMColor);
627111d463cee893a479280c7af41757e709e33ef5reed@google.com
637111d463cee893a479280c7af41757e709e33ef5reed@google.com    srcPI.convertPixelsTo(&dstPI, count, 1);
647111d463cee893a479280c7af41757e709e33ef5reed@google.com
650a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    ctable->unlockColors();
665782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@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
1080797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.comstatic void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrTextureDesc* desc) {
1090797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    desc->fFlags = kNone_GrTextureFlags;
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,
14277cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman                                         GrTextureDesc 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.
1620249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        result = ctx->lockAndRefScratchTexture(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,
1739c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski                                    const SkBitmap &bm, GrTextureDesc 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;
20999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        }
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,
222518d83dbc1c899e316e8c896af5defb58b83120fsugoi                                   const SkBitmap& bm, const GrTextureDesc& desc) {
223518d83dbc1c899e316e8c896af5defb58b83120fsugoi    SkPixelRef* pixelRef = bm.pixelRef();
224518d83dbc1c899e316e8c896af5defb58b83120fsugoi    SkISize yuvSizes[3];
225abaef86f2b37d8a939506a2076da07f6db456951rileya    if ((NULL == pixelRef) || !pixelRef->getYUV8Planes(yuvSizes, NULL, NULL, NULL)) {
226518d83dbc1c899e316e8c896af5defb58b83120fsugoi        return NULL;
227518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
228518d83dbc1c899e316e8c896af5defb58b83120fsugoi
229518d83dbc1c899e316e8c896af5defb58b83120fsugoi    // Allocate the memory for YUV
230518d83dbc1c899e316e8c896af5defb58b83120fsugoi    size_t totalSize(0);
231518d83dbc1c899e316e8c896af5defb58b83120fsugoi    size_t sizes[3], rowBytes[3];
232518d83dbc1c899e316e8c896af5defb58b83120fsugoi    for (int i = 0; i < 3; ++i) {
233518d83dbc1c899e316e8c896af5defb58b83120fsugoi        rowBytes[i] = yuvSizes[i].fWidth;
234518d83dbc1c899e316e8c896af5defb58b83120fsugoi        totalSize  += sizes[i] = rowBytes[i] * yuvSizes[i].fHeight;
235518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
236518d83dbc1c899e316e8c896af5defb58b83120fsugoi    SkAutoMalloc storage(totalSize);
237518d83dbc1c899e316e8c896af5defb58b83120fsugoi    void* planes[3];
238518d83dbc1c899e316e8c896af5defb58b83120fsugoi    planes[0] = storage.get();
239518d83dbc1c899e316e8c896af5defb58b83120fsugoi    planes[1] = (uint8_t*)planes[0] + sizes[0];
240518d83dbc1c899e316e8c896af5defb58b83120fsugoi    planes[2] = (uint8_t*)planes[1] + sizes[1];
241518d83dbc1c899e316e8c896af5defb58b83120fsugoi
242abaef86f2b37d8a939506a2076da07f6db456951rileya    SkYUVColorSpace colorSpace;
243abaef86f2b37d8a939506a2076da07f6db456951rileya
244518d83dbc1c899e316e8c896af5defb58b83120fsugoi    // Get the YUV planes
245abaef86f2b37d8a939506a2076da07f6db456951rileya    if (!pixelRef->getYUV8Planes(yuvSizes, planes, rowBytes, &colorSpace)) {
246518d83dbc1c899e316e8c896af5defb58b83120fsugoi        return NULL;
247518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
248518d83dbc1c899e316e8c896af5defb58b83120fsugoi
249518d83dbc1c899e316e8c896af5defb58b83120fsugoi    GrTextureDesc yuvDesc;
250518d83dbc1c899e316e8c896af5defb58b83120fsugoi    yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
251518d83dbc1c899e316e8c896af5defb58b83120fsugoi    GrAutoScratchTexture yuvTextures[3];
252518d83dbc1c899e316e8c896af5defb58b83120fsugoi    for (int i = 0; i < 3; ++i) {
253518d83dbc1c899e316e8c896af5defb58b83120fsugoi        yuvDesc.fWidth  = yuvSizes[i].fWidth;
254518d83dbc1c899e316e8c896af5defb58b83120fsugoi        yuvDesc.fHeight = yuvSizes[i].fHeight;
255518d83dbc1c899e316e8c896af5defb58b83120fsugoi        yuvTextures[i].set(ctx, yuvDesc);
256518d83dbc1c899e316e8c896af5defb58b83120fsugoi        if ((NULL == yuvTextures[i].texture()) ||
257518d83dbc1c899e316e8c896af5defb58b83120fsugoi            !ctx->writeTexturePixels(yuvTextures[i].texture(),
258518d83dbc1c899e316e8c896af5defb58b83120fsugoi                0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
259518d83dbc1c899e316e8c896af5defb58b83120fsugoi                yuvDesc.fConfig, planes[i], rowBytes[i])) {
260518d83dbc1c899e316e8c896af5defb58b83120fsugoi            return NULL;
261518d83dbc1c899e316e8c896af5defb58b83120fsugoi        }
262518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
263518d83dbc1c899e316e8c896af5defb58b83120fsugoi
264518d83dbc1c899e316e8c896af5defb58b83120fsugoi    GrTextureDesc rtDesc = desc;
265518d83dbc1c899e316e8c896af5defb58b83120fsugoi    rtDesc.fFlags = rtDesc.fFlags |
266518d83dbc1c899e316e8c896af5defb58b83120fsugoi                    kRenderTarget_GrTextureFlagBit |
267518d83dbc1c899e316e8c896af5defb58b83120fsugoi                    kNoStencil_GrTextureFlagBit;
268518d83dbc1c899e316e8c896af5defb58b83120fsugoi
2690249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    GrTexture* result = sk_gr_allocate_texture(ctx, cache, params, bm, rtDesc, NULL, 0);
270518d83dbc1c899e316e8c896af5defb58b83120fsugoi
271518d83dbc1c899e316e8c896af5defb58b83120fsugoi    GrRenderTarget* renderTarget = result ? result->asRenderTarget() : NULL;
27249f085dddff10473b6ebf832a974288300224e60bsalomon    if (renderTarget) {
273b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        SkAutoTUnref<GrFragmentProcessor> yuvToRgbProcessor(GrYUVtoRGBEffect::Create(
274abaef86f2b37d8a939506a2076da07f6db456951rileya            yuvTextures[0].texture(), yuvTextures[1].texture(), yuvTextures[2].texture(),
275abaef86f2b37d8a939506a2076da07f6db456951rileya            colorSpace));
276518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrPaint paint;
277b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        paint.addColorProcessor(yuvToRgbProcessor);
278518d83dbc1c899e316e8c896af5defb58b83120fsugoi        SkRect r = SkRect::MakeWH(SkIntToScalar(yuvSizes[0].fWidth),
279518d83dbc1c899e316e8c896af5defb58b83120fsugoi                                  SkIntToScalar(yuvSizes[0].fHeight));
280518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrContext::AutoRenderTarget autoRT(ctx, renderTarget);
281518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrContext::AutoMatrix am;
282518d83dbc1c899e316e8c896af5defb58b83120fsugoi        am.setIdentity(ctx);
283518d83dbc1c899e316e8c896af5defb58b83120fsugoi        GrContext::AutoClip ac(ctx, GrContext::AutoClip::kWideOpen_InitialClip);
284518d83dbc1c899e316e8c896af5defb58b83120fsugoi        ctx->drawRect(paint, r);
285518d83dbc1c899e316e8c896af5defb58b83120fsugoi    } else {
286518d83dbc1c899e316e8c896af5defb58b83120fsugoi        SkSafeSetNull(result);
287518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
288518d83dbc1c899e316e8c896af5defb58b83120fsugoi
289518d83dbc1c899e316e8c896af5defb58b83120fsugoi    return result;
290518d83dbc1c899e316e8c896af5defb58b83120fsugoi}
291518d83dbc1c899e316e8c896af5defb58b83120fsugoi
2921f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comstatic GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
2930797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                                              bool cache,
2941f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                              const GrTextureParams* params,
2951f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com                                              const SkBitmap& origBitmap) {
296ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    SkBitmap tmpBitmap;
297ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
298ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    const SkBitmap* bitmap = &origBitmap;
2995782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
30075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
3010797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    generate_bitmap_texture_desc(*bitmap, &desc);
3025782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
3030689d7b12e7c427a077b003d3d8ae759d86f798freed    if (kIndex_8_SkColorType == bitmap->colorType()) {
304ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // build_compressed_data doesn't do npot->pot expansion
305ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        // and paletted textures can't be sub-updated
3067f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com        if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) {
307d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon            size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
308d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon                                                          bitmap->width(), bitmap->height());
309d4cb922ea1a85d381e88975b63664f6c0bf28cdbbsalomon            SkAutoMalloc storage(imageSize);
3105782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com
311ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            build_compressed_data(storage.get(), origBitmap);
312ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
313ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // our compressed data will be trimmed, so pass width() for its
314ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // "rowBytes", since they are the same now.
3150249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi            return sk_gr_allocate_texture(ctx, cache, params, origBitmap,
3160249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                          desc, storage.get(), bitmap->width());
317ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        } else {
31828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org            origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
319ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            // now bitmap points to our temp, which has been promoted to 32bits
320ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com            bitmap = &tmpBitmap;
3213adcc3403377c0b9a7afde6db8e0432325413a10commit-bot@chromium.org            desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
322ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        }
323309e86912445879651d52ebbedb67b4ff3f1516ckrajcevski    }
3249c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
3259c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski    // Is this an ETC1 encoded texture?
3268c111f783f40470e697310244426362132979ad9krajcevski#ifndef SK_IGNORE_ETC1_SUPPORT
3279a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski    else if (
32877cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        // We do not support scratch ETC1 textures, hence they should all be at least
32977cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        // trying to go to the cache.
33077cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        cache
3319a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // Make sure that the underlying device supports ETC1 textures before we go ahead
3329a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // and check the data.
33377cd8b0ba20bca3a9d994586eb58337bcf2082fbbungeman        && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)
3349a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // If the bitmap had compressed data and was then uncompressed, it'll still return
3359a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // compressed data on 'refEncodedData' and upload it. Probably not good, since if
3369a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // the bitmap has available pixels, then they might not be what the decompressed
3379a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        // data is.
3389a3cdbb3d0957ad3f04d02277a4ce839752f4efdkrajcevski        && !(bitmap->readyToDraw())) {
3390249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        GrTexture *texture = load_etc1_texture(ctx, cache, params, *bitmap, desc);
34049f085dddff10473b6ebf832a974288300224e60bsalomon        if (texture) {
3419c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski            return texture;
3429c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        }
3435782d712ffc31557d0cb12d5a220cebb783f6895bsalomon@google.com    }
3448c111f783f40470e697310244426362132979ad9krajcevski#endif   // SK_IGNORE_ETC1_SUPPORT
345ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
346518d83dbc1c899e316e8c896af5defb58b83120fsugoi    else {
3470249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi        GrTexture *texture = load_yuv_texture(ctx, cache, params, *bitmap, desc);
34849f085dddff10473b6ebf832a974288300224e60bsalomon        if (texture) {
349518d83dbc1c899e316e8c896af5defb58b83120fsugoi            return texture;
350518d83dbc1c899e316e8c896af5defb58b83120fsugoi        }
351518d83dbc1c899e316e8c896af5defb58b83120fsugoi    }
3527f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    SkAutoLockPixels alp(*bitmap);
3537f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    if (!bitmap->readyToDraw()) {
3547f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com        return NULL;
3557f4ad5a30ff745e666579d2b518dfd0c1aa49596bsalomon@google.com    }
35650a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
3570249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi    return sk_gr_allocate_texture(ctx, cache, params, origBitmap, desc,
3580249ec267a7c4f31b1f19668c176c2e3e33b7e19sugoi                                  bitmap->getPixels(), bitmap->rowBytes());
359ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
360ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
3610797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.combool GrIsBitmapInCache(const GrContext* ctx,
3620797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                       const SkBitmap& bitmap,
3630797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                       const GrTextureParams* params) {
3640797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    GrCacheID cacheID;
3650797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    generate_bitmap_cache_id(bitmap, &cacheID);
3660797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
3670797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    GrTextureDesc desc;
3680797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    generate_bitmap_texture_desc(bitmap, &desc);
3690797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    return ctx->isTextureInCache(desc, cacheID, params);
3700797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com}
371ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
37295ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrLockAndRefCachedBitmapTexture(GrContext* ctx,
37395ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                           const SkBitmap& bitmap,
37495ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                           const GrTextureParams* params) {
3751f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrTexture* result = NULL;
37624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
3770797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    bool cache = !bitmap.isVolatile();
3789c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com
3790797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (cache) {
3800797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        // If the bitmap isn't changing try to find a cached copy first.
3814b86e3428b115202e82d49a0914ea8ab6dc25940bsalomon@google.com
3820797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        GrCacheID cacheID;
3830797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        generate_bitmap_cache_id(bitmap, &cacheID);
3840b6ad2297fbf43466950690102c1c9c150f2a972bsalomon@google.com
3850797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        GrTextureDesc desc;
3860797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        generate_bitmap_texture_desc(bitmap, &desc);
3870797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com
38895ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        result = ctx->findAndRefTexture(desc, cacheID, params);
3890797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    }
3900797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (NULL == result) {
3910797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        result = sk_gr_create_bitmap_texture(ctx, cache, params, bitmap);
39224f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com    }
3931f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == result) {
39424f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com        GrPrintf("---- failed to create texture for cache [%d %d]\n",
39524f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com                    bitmap.width(), bitmap.height());
39624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com    }
3971f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return result;
39824f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com}
39924f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
40095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comvoid GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) {
40149f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(texture->getContext());
4021f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com
4039fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com    texture->getContext()->unlockScratchTexture(texture);
40495ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    texture->unref();
40524f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com}
40624f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
40724f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com///////////////////////////////////////////////////////////////////////////////
40824f3ad1bbb44916cae33f5d3cf2a20af4bbc381frileya@google.com
40915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
41015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org// alpha info, that will be considered.
41115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgGrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
41215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    switch (ct) {
41315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kUnknown_SkColorType:
41415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kUnknown_GrPixelConfig;
41515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kAlpha_8_SkColorType:
41615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kAlpha_8_GrPixelConfig;
41715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kRGB_565_SkColorType:
41815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kRGB_565_GrPixelConfig;
41915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kARGB_4444_SkColorType:
42015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kRGBA_4444_GrPixelConfig;
42115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kRGBA_8888_SkColorType:
42215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kRGBA_8888_GrPixelConfig;
42315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kBGRA_8888_SkColorType:
42415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kBGRA_8888_GrPixelConfig;
42515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        case kIndex_8_SkColorType:
42615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org            return kIndex_8_GrPixelConfig;
42715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    }
42815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkASSERT(0);    // shouldn't get here
42915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return kUnknown_GrPixelConfig;
43015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org}
43115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org
432bf790232f6d94b54239dbc210d8beee7411ca458reed@google.combool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
433bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    SkColorType ct;
434bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    switch (config) {
435bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kAlpha_8_GrPixelConfig:
436bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kAlpha_8_SkColorType;
437bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
438bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kIndex_8_GrPixelConfig:
439bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kIndex_8_SkColorType;
440bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
441bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kRGB_565_GrPixelConfig:
442bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kRGB_565_SkColorType;
443bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
444bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kRGBA_4444_GrPixelConfig:
445bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kARGB_4444_SkColorType;
446bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
447bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kRGBA_8888_GrPixelConfig:
448bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kRGBA_8888_SkColorType;
449bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
450bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        case kBGRA_8888_GrPixelConfig:
451bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            ct = kBGRA_8888_SkColorType;
452bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            break;
453bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        default:
454bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com            return false;
455bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
456bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (ctOut) {
457bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        *ctOut = ct;
458bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
459bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    return true;
460bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com}
4618dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4628dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
4638dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
46483d081ae1d731b5039e99823620f5e287542ee39bsalomonvoid SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor paintColor,
4658dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org                             bool constantColor, GrPaint* grPaint) {
4668dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4678dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    grPaint->setDither(skPaint.isDither());
4688dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    grPaint->setAntiAlias(skPaint.isAntiAlias());
4698dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4708dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkXfermode::Coeff sm;
4718dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkXfermode::Coeff dm;
4728dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4738dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkXfermode* mode = skPaint.getXfermode();
474b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrFragmentProcessor* xferProcessor = NULL;
475b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (SkXfermode::asFragmentProcessorOrCoeff(mode, &xferProcessor, &sm, &dm)) {
476b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        if (xferProcessor) {
477b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            grPaint->addColorProcessor(xferProcessor)->unref();
4788dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            sm = SkXfermode::kOne_Coeff;
4798dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            dm = SkXfermode::kZero_Coeff;
4808dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        }
4818dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    } else {
4828dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
4838dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        // Fall back to src-over
4848dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        sm = SkXfermode::kOne_Coeff;
4858dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        dm = SkXfermode::kISA_Coeff;
4868dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
4878dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
4889de5b514d38c5b36066bcdc14fba2f7e5196d372dandov
4899de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    //set the color of the paint to the one of the parameter
49083d081ae1d731b5039e99823620f5e287542ee39bsalomon    grPaint->setColor(paintColor);
4918dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
4928dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkColorFilter* colorFilter = skPaint.getColorFilter();
49349f085dddff10473b6ebf832a974288300224e60bsalomon    if (colorFilter) {
4948dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        // if the source color is a constant then apply the filter here once rather than per pixel
4958dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        // in a shader.
4968dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        if (constantColor) {
4978dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            SkColor filtered = colorFilter->filterColor(skPaint.getColor());
4988dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            grPaint->setColor(SkColor2GrColor(filtered));
4998dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        } else {
500b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkAutoTUnref<GrFragmentProcessor> fp(colorFilter->asFragmentProcessor(context));
501b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            if (fp.get()) {
502b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                grPaint->addColorProcessor(fp);
5038dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org            }
5048dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        }
5058dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
506f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
507f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#ifndef SK_IGNORE_GPU_DITHER
508f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // If the dither flag is set, then we need to see if the underlying context
509f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // supports it. If not, then install a dither effect.
510f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    if (skPaint.isDither() && grPaint->numColorStages() > 0) {
511f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        // What are we rendering into?
512f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        const GrRenderTarget *target = context->getRenderTarget();
51349f085dddff10473b6ebf832a974288300224e60bsalomon        SkASSERT(target);
514f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
515f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        // Suspect the dithering flag has no effect on these configs, otherwise
516f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        // fall back on setting the appropriate state.
517f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        if (target->config() == kRGBA_8888_GrPixelConfig ||
518f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            target->config() == kBGRA_8888_GrPixelConfig) {
519f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            // The dither flag is set and the target is likely
520f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            // not going to be dithered by the GPU.
521b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkAutoTUnref<GrFragmentProcessor> fp(GrDitherEffect::Create());
522b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            if (fp.get()) {
523b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                grPaint->addColorProcessor(fp);
524f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                grPaint->setDither(false);
525f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            }
526f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        }
527f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    }
528f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#endif
5298dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org}
5308dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
5319e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org/**
5329e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrContext::AutoMatrix
5339e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org * likes to set the new matrix in its constructor because it is usually necessary to simulataneously
5349e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint, however.
5359e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org */
5369e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.orgclass AutoMatrix {
5379e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.orgpublic:
5389e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org    AutoMatrix(GrContext* context) {
5399e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org        fMatrix = context->getMatrix();
5409e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org        fContext = context;
5419e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org    }
5429e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org    ~AutoMatrix() {
54349f085dddff10473b6ebf832a974288300224e60bsalomon        SkASSERT(fContext);
5449e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org        fContext->setMatrix(fMatrix);
5459e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org    }
5469e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.orgprivate:
5479e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org    GrContext* fContext;
5489e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org    SkMatrix fMatrix;
5499e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org};
5509e967ad6e54c1e2e5ffb9d6e9eb8414e6b36b0e3commit-bot@chromium.org
5513595f88aff0a1b490aa6661f0ba2d3534ee86353commit-bot@chromium.orgvoid SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint,
5528dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org                           bool constantColor, GrPaint* grPaint) {
5538dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    SkShader* shader = skPaint.getShader();
5548dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    if (NULL == shader) {
5559de5b514d38c5b36066bcdc14fba2f7e5196d372dandov        SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()),
5569de5b514d38c5b36066bcdc14fba2f7e5196d372dandov                                constantColor, grPaint);
5578dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org        return;
5588dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
5598dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org
56083d081ae1d731b5039e99823620f5e287542ee39bsalomon    GrColor paintColor = SkColor2GrColor(skPaint.getColor());
561f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
562f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // Start a new block here in order to preserve our context state after calling
563b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    // asFragmentProcessor(). Since these calls get passed back to the client, we don't really
564f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // want them messing around with the context.
565f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    {
566b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        // SkShader::asFragmentProcessor() may do offscreen rendering. Save off the current RT,
567b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        // clip, and matrix. We don't reset the matrix on the context because
568b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        // SkShader::asFragmentProcessor may use GrContext::getMatrix() to know the transformation
569b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        // from local coords to device space.
570f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        GrContext::AutoRenderTarget art(context, NULL);
571f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
572f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        AutoMatrix am(context);
573f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
57483d081ae1d731b5039e99823620f5e287542ee39bsalomon        // Allow the shader to modify paintColor and also create an effect to be installed as
57583d081ae1d731b5039e99823620f5e287542ee39bsalomon        // the first color effect on the GrPaint.
576b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        GrFragmentProcessor* fp = NULL;
577b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        if (shader->asFragmentProcessor(context, skPaint, NULL, &paintColor, &fp) && fp) {
578b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            grPaint->addColorProcessor(fp)->unref();
579f461a8fdf642ba713dcdfb217534652df1eac278krajcevski            constantColor = false;
580f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        }
5818dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org    }
582f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
583b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    // The grcolor is automatically set when calling asFragmentProcessor.
5849de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
58583d081ae1d731b5039e99823620f5e287542ee39bsalomon    SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint);
5868dcff6416969708952d663a47993f73957a00badcommit-bot@chromium.org}
587