| Index: src/gpu/SkGr.cpp | 
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp | 
| index 1813433b300c2e3b003ec8172eeb66ecd095acd4..d8444968da6ea2e788b16900fc80af3e314a1243 100644 | 
| --- a/src/gpu/SkGr.cpp | 
| +++ b/src/gpu/SkGr.cpp | 
| @@ -38,6 +38,118 @@ | 
| #  include "etc1.h" | 
| #endif | 
|  | 
| +GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { | 
| +    GrSurfaceDesc desc; | 
| +    desc.fFlags = kNone_GrSurfaceFlags; | 
| +    desc.fWidth = info.width(); | 
| +    desc.fHeight = info.height(); | 
| +    desc.fConfig = SkImageInfo2GrPixelConfig(info); | 
| +    desc.fSampleCnt = 0; | 
| +    return desc; | 
| +} | 
| + | 
| +static void get_stretch(const GrCaps& caps, int width, int height, | 
| +                        const GrTextureParams& params, SkGrStretch* stretch) { | 
| +    stretch->fType = SkGrStretch::kNone_Type; | 
| +    bool doStretch = false; | 
| +    if (params.isTiled() && !caps.npotTextureTileSupport() && | 
| +        (!SkIsPow2(width) || !SkIsPow2(height))) { | 
| +        doStretch = true; | 
| +        stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize())); | 
| +        stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize())); | 
| +    } else if (width < caps.minTextureSize() || height < caps.minTextureSize()) { | 
| +        // The small texture issues appear to be with tiling. Hence it seems ok to scale them | 
| +        // up using the GPU. If issues persist we may need to CPU-stretch. | 
| +        doStretch = true; | 
| +        stretch->fWidth = SkTMax(width, caps.minTextureSize()); | 
| +        stretch->fHeight = SkTMax(height, caps.minTextureSize()); | 
| +    } | 
| +    if (doStretch) { | 
| +        switch (params.filterMode()) { | 
| +            case GrTextureParams::kNone_FilterMode: | 
| +                stretch->fType = SkGrStretch::kNearest_Type; | 
| +                break; | 
| +            case GrTextureParams::kBilerp_FilterMode: | 
| +            case GrTextureParams::kMipMap_FilterMode: | 
| +                stretch->fType = SkGrStretch::kBilerp_Type; | 
| +                break; | 
| +        } | 
| +    } else { | 
| +        stretch->fWidth = -1; | 
| +        stretch->fHeight = -1; | 
| +        stretch->fType = SkGrStretch::kNone_Type; | 
| +    } | 
| +} | 
| + | 
| +static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset) { | 
| +    SkASSERT(SkIsU16(subset.width())); | 
| +    SkASSERT(SkIsU16(subset.height())); | 
| + | 
| +    static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 
| +    GrUniqueKey::Builder builder(key, kDomain, 4); | 
| +    builder[0] = imageID; | 
| +    builder[1] = subset.x(); | 
| +    builder[2] = subset.y(); | 
| +    builder[3] = subset.width() | (subset.height() << 16); | 
| +} | 
| + | 
| +void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset, | 
| +                          const GrCaps& caps, const GrTextureParams& params) { | 
| +    SkGrStretch stretch; | 
| +    get_stretch(caps, subset.width(), subset.height(), params, &stretch); | 
| +    if (SkGrStretch::kNone_Type != stretch.fType) { | 
| +        GrUniqueKey tmpKey; | 
| +        make_unstretched_key(&tmpKey, imageID, subset); | 
| +        if (!GrMakeStretchedKey(tmpKey, stretch, key)) { | 
| +            *key = tmpKey; | 
| +        } | 
| +    } else { | 
| +        make_unstretched_key(key, imageID, subset); | 
| +    } | 
| +} | 
| + | 
| +GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, | 
| +                                                 int expectedW, int expectedH, | 
| +                                                 const void** outStartOfDataToUpload) { | 
| +    *outStartOfDataToUpload = nullptr; | 
| +#ifndef SK_IGNORE_ETC1_SUPPORT | 
| +    if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { | 
| +        return kUnknown_GrPixelConfig; | 
| +    } | 
| + | 
| +    const uint8_t* bytes = data->bytes(); | 
| +    if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) { | 
| +        // Does the data match the dimensions of the bitmap? If not, | 
| +        // then we don't know how to scale the image to match it... | 
| +        if (etc1_pkm_get_width(bytes) != (unsigned)expectedW || | 
| +            etc1_pkm_get_height(bytes) != (unsigned)expectedH) | 
| +        { | 
| +            return kUnknown_GrPixelConfig; | 
| +        } | 
| + | 
| +        *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE; | 
| +        return kETC1_GrPixelConfig; | 
| +    } else if (SkKTXFile::is_ktx(bytes)) { | 
| +        SkKTXFile ktx(data); | 
| + | 
| +        // Is it actually an ETC1 texture? | 
| +        if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) { | 
| +            return kUnknown_GrPixelConfig; | 
| +        } | 
| + | 
| +        // Does the data match the dimensions of the bitmap? If not, | 
| +        // then we don't know how to scale the image to match it... | 
| +        if (ktx.width() != expectedW || ktx.height() != expectedH) { | 
| +            return kUnknown_GrPixelConfig; | 
| +        } | 
| + | 
| +        *outStartOfDataToUpload = ktx.pixelData(); | 
| +        return kETC1_GrPixelConfig; | 
| +    } | 
| +#endif | 
| +    return kUnknown_GrPixelConfig; | 
| +} | 
| + | 
| /*  Fill out buffer with the compressed format Ganesh expects from a colortable | 
| based bitmap. [palette (colortable) + indices]. | 
|  | 
| @@ -97,38 +209,6 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) { | 
|  | 
| //////////////////////////////////////////////////////////////////////////////// | 
|  | 
| -static void get_stretch(const GrCaps& caps, int width, int height, | 
| -                        const GrTextureParams& params, SkGrStretch* stretch) { | 
| -    stretch->fType = SkGrStretch::kNone_Type; | 
| -    bool doStretch = false; | 
| -    if (params.isTiled() && !caps.npotTextureTileSupport() && | 
| -        (!SkIsPow2(width) || !SkIsPow2(height))) { | 
| -        doStretch = true; | 
| -        stretch->fWidth  = GrNextPow2(SkTMax(width, caps.minTextureSize())); | 
| -        stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize())); | 
| -    } else if (width < caps.minTextureSize() || height < caps.minTextureSize()) { | 
| -        // The small texture issues appear to be with tiling. Hence it seems ok to scale them | 
| -        // up using the GPU. If issues persist we may need to CPU-stretch. | 
| -        doStretch = true; | 
| -        stretch->fWidth = SkTMax(width, caps.minTextureSize()); | 
| -        stretch->fHeight = SkTMax(height, caps.minTextureSize()); | 
| -    } | 
| -    if (doStretch) { | 
| -        switch(params.filterMode()) { | 
| -            case GrTextureParams::kNone_FilterMode: | 
| -                stretch->fType = SkGrStretch::kNearest_Type; | 
| -                break; | 
| -            case GrTextureParams::kBilerp_FilterMode: | 
| -            case GrTextureParams::kMipMap_FilterMode: | 
| -                stretch->fType = SkGrStretch::kBilerp_Type; | 
| -                break; | 
| -        } | 
| -    } else { | 
| -        stretch->fWidth  = -1; | 
| -        stretch->fHeight = -1; | 
| -        stretch->fType = SkGrStretch::kNone_Type; | 
| -    } | 
| -} | 
|  | 
| bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, | 
| GrUniqueKey* stretchedKey) { | 
| @@ -146,43 +226,6 @@ bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch, | 
| return false; | 
| } | 
|  | 
| -static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset) { | 
| -    SkASSERT(SkIsU16(subset.width())); | 
| -    SkASSERT(SkIsU16(subset.height())); | 
| - | 
| -    static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 
| -    GrUniqueKey::Builder builder(key, kDomain, 4); | 
| -    builder[0] = imageID; | 
| -    builder[1] = subset.x(); | 
| -    builder[2] = subset.y(); | 
| -    builder[3] = subset.width() | (subset.height() << 16); | 
| -} | 
| - | 
| -void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset, | 
| -                          const GrCaps& caps, const GrTextureParams& params) { | 
| -    SkGrStretch stretch; | 
| -    get_stretch(caps, subset.width(), subset.height(), params, &stretch); | 
| -    if (SkGrStretch::kNone_Type != stretch.fType) { | 
| -        GrUniqueKey tmpKey; | 
| -        make_unstretched_key(&tmpKey, imageID, subset); | 
| -        if (!GrMakeStretchedKey(tmpKey, stretch, key)) { | 
| -            *key = tmpKey; | 
| -        } | 
| -    } else { | 
| -        make_unstretched_key(key, imageID, subset); | 
| -    } | 
| -} | 
| - | 
| -GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { | 
| -    GrSurfaceDesc desc; | 
| -    desc.fFlags = kNone_GrSurfaceFlags; | 
| -    desc.fWidth = info.width(); | 
| -    desc.fHeight = info.height(); | 
| -    desc.fConfig = SkImageInfo2GrPixelConfig(info); | 
| -    desc.fSampleCnt = 0; | 
| -    return desc; | 
| -} | 
| - | 
| namespace { | 
|  | 
| // When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key. | 
| @@ -287,65 +330,6 @@ GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch, | 
| return stretched.detach(); | 
| } | 
|  | 
| -GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data, | 
| -                                                 int expectedW, int expectedH, | 
| -                                                 const void** outStartOfDataToUpload) { | 
| -    *outStartOfDataToUpload = nullptr; | 
| -#ifndef SK_IGNORE_ETC1_SUPPORT | 
| -    if (!ctx->caps()->isConfigTexturable(kETC1_GrPixelConfig)) { | 
| -        return kUnknown_GrPixelConfig; | 
| -    } | 
| - | 
| -    const uint8_t* bytes = data->bytes(); | 
| -    if (data->size() > ETC_PKM_HEADER_SIZE && etc1_pkm_is_valid(bytes)) { | 
| -        // Does the data match the dimensions of the bitmap? If not, | 
| -        // then we don't know how to scale the image to match it... | 
| -        if (etc1_pkm_get_width(bytes) != (unsigned)expectedW || | 
| -            etc1_pkm_get_height(bytes) != (unsigned)expectedH) | 
| -        { | 
| -            return kUnknown_GrPixelConfig; | 
| -        } | 
| - | 
| -        *outStartOfDataToUpload = bytes + ETC_PKM_HEADER_SIZE; | 
| -        return kETC1_GrPixelConfig; | 
| -    } else if (SkKTXFile::is_ktx(bytes)) { | 
| -        SkKTXFile ktx(data); | 
| - | 
| -        // Is it actually an ETC1 texture? | 
| -        if (!ktx.isCompressedFormat(SkTextureCompressor::kETC1_Format)) { | 
| -            return kUnknown_GrPixelConfig; | 
| -        } | 
| - | 
| -        // Does the data match the dimensions of the bitmap? If not, | 
| -        // then we don't know how to scale the image to match it... | 
| -        if (ktx.width() != expectedW || ktx.height() != expectedH) { | 
| -            return kUnknown_GrPixelConfig; | 
| -        } | 
| - | 
| -        *outStartOfDataToUpload = ktx.pixelData(); | 
| -        return kETC1_GrPixelConfig; | 
| -    } | 
| -#endif | 
| -    return kUnknown_GrPixelConfig; | 
| -} | 
| - | 
| -static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey, | 
| -                                    const SkBitmap &bm, GrSurfaceDesc desc) { | 
| -    SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); | 
| -    if (!data) { | 
| -        return nullptr; | 
| -    } | 
| - | 
| -    const void* startOfTexData; | 
| -    desc.fConfig = GrIsCompressedTextureDataSupported(ctx, data, bm.width(), bm.height(), | 
| -                                                      &startOfTexData); | 
| -    if (kUnknown_GrPixelConfig == desc.fConfig) { | 
| -        return nullptr; | 
| -    } | 
| - | 
| -    return GrCreateTextureForPixels(ctx, optionalKey, desc, bm.pixelRef(), startOfTexData, 0); | 
| -} | 
| - | 
| /* | 
| *  Once we have made SkImages handle all lazy/deferred/generated content, the YUV apis will | 
| *  be gone from SkPixelRef, and we can remove this subclass entirely. | 
| @@ -391,6 +375,23 @@ static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKe | 
| return texture; | 
| } | 
|  | 
| +static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey, | 
| +                                    const SkBitmap &bm, GrSurfaceDesc desc) { | 
| +    SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData()); | 
| +    if (!data) { | 
| +        return nullptr; | 
| +    } | 
| + | 
| +    const void* startOfTexData; | 
| +    desc.fConfig = GrIsCompressedTextureDataSupported(ctx, data, bm.width(), bm.height(), | 
| +                                                      &startOfTexData); | 
| +    if (kUnknown_GrPixelConfig == desc.fConfig) { | 
| +        return nullptr; | 
| +    } | 
| + | 
| +    return GrCreateTextureForPixels(ctx, optionalKey, desc, bm.pixelRef(), startOfTexData, 0); | 
| +} | 
| + | 
| static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx, | 
| const SkBitmap& origBitmap, | 
| const GrUniqueKey& optionalKey) { | 
|  |