Initial work to get ETC1 data up to the GPU

Committed: http://code.google.com/p/skia/source/detail?r=15001

R=bsalomon@google.com, robertphillips@google.com

Author: krajcevski@google.com

Review URL: https://codereview.chromium.org/302783002
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 6bd04de..9579866 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -8,9 +8,16 @@
 #include "SkGr.h"
 #include "SkColorFilter.h"
 #include "SkConfig8888.h"
+#include "SkData.h"
 #include "SkMessageBus.h"
 #include "SkPixelRef.h"
 #include "GrResourceCache.h"
+#include "GrGpu.h"
+#include "GrDrawTargetCaps.h"
+
+#if SK_SUPPORT_ETC1
+#  include "etc1.h"
+#endif
 
 /*  Fill out buffer with the compressed format Ganesh expects from a colortable
  based bitmap. [palette (colortable) + indices].
@@ -124,6 +131,50 @@
     pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
 }
 
+#if SK_SUPPORT_ETC1
+static GrTexture *load_etc1_texture(GrContext* ctx,
+                                    const GrTextureParams* params,
+                                    const SkBitmap &bm, GrTextureDesc desc) {
+    SkData *data = bm.pixelRef()->refEncodedData();
+
+    // Is this even encoded data?
+    if (NULL == data) {
+        return NULL;
+    }
+
+    // Is this a valid PKM encoded data?
+    const uint8_t *bytes = data->bytes();
+    if (!etc1_pkm_is_valid(bytes)) {
+        return NULL;
+    }
+
+    uint32_t encodedWidth = etc1_pkm_get_width(bytes);
+    uint32_t encodedHeight = etc1_pkm_get_height(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 (encodedWidth != static_cast<uint32_t>(bm.width()) ||
+        encodedHeight != static_cast<uint32_t>(bm.height())) {
+        return NULL;
+    }
+
+    // Everything seems good... skip ahead to the data.
+    bytes += ETC_PKM_HEADER_SIZE;
+    desc.fConfig = kETC1_GrPixelConfig;
+
+    // This texture is likely to be used again so leave it in the cache
+    GrCacheID cacheID;
+    generate_bitmap_cache_id(bm, &cacheID);
+
+    GrResourceKey key;
+    GrTexture* result = ctx->createTexture(params, desc, cacheID, bytes, 0, &key);
+    if (NULL != result) {
+        add_genID_listener(key, bm.pixelRef());
+    }
+    return result;
+}
+#endif   // SK_SUPPORT_ETC1
+
 static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
                                               bool cache,
                                               const GrTextureParams* params,
@@ -172,7 +223,16 @@
             bitmap = &tmpBitmap;
             desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
         }
+
+    // Is this an ETC1 encoded texture?
+#if SK_SUPPORT_ETC1
+    } else if (cache && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)) {
+        GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc);
+        if (NULL != texture) {
+            return texture;
+        }
     }
+#endif   // SK_SUPPORT_ETC1
 
     SkAutoLockPixels alp(*bitmap);
     if (!bitmap->readyToDraw()) {