Revert "Remove SkImage::MakeTextureFromPixmap"

This reverts commit 8ccbbb455c6ef194920c47e846b95b50f5017138.

Reason for revert: Chrome perf regression

BUG=chrome:684483

Original change's description:
> Remove SkImage::MakeTextureFromPixmap
> 
> Another step towards reducing the number of texture upload paths.
> 
> BUG=skia:
> 
> Change-Id: Ica185e7334f52dc9ebf87e21fe6f60589ef87bb3
> Reviewed-on: https://skia-review.googlesource.com/7346
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> 

TBR=bsalomon@google.com,robertphillips@google.com,brianosman@google.com,cblume@google.com
# Not skipping CQ checks because original CL landed > 1 day ago.
BUG=skia:

Change-Id: I8bf6970b764018f3ebcac8123e4d6a8ad05317ff
Reviewed-on: https://skia-review.googlesource.com/7484
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 92b8f80..076da33 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -175,6 +175,8 @@
                                           const SkMatrix*, const SkPaint*, BitDepth,
                                           sk_sp<SkColorSpace>);
 
+    static sk_sp<SkImage> MakeTextureFromPixmap(GrContext*, const SkPixmap&, SkBudgeted budgeted);
+
     ///////////////////////////////////////////////////////////////////////////////////////////////
 
     int width() const { return fWidth; }
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 8efe91a..5eb6937 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -329,6 +329,10 @@
 
 #if !SK_SUPPORT_GPU
 
+sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext*, const SkPixmap&, SkBudgeted budgeted) {
+    return nullptr;
+}
+
 sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&, const GrMipLevel* texels,
                                      int mipLevelCount, SkBudgeted, SkDestinationSurfaceColorMode) {
     return nullptr;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index a1ecf5b..ec1968f 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -371,6 +371,20 @@
     return MakeRasterData(info, data, rowBytes);
 }
 
+sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext* ctx, const SkPixmap& pixmap,
+                                              SkBudgeted budgeted) {
+    if (!ctx) {
+        return nullptr;
+    }
+    sk_sp<GrTexture> texture(GrUploadPixmapToTexture(ctx, pixmap, budgeted));
+    if (!texture) {
+        return nullptr;
+    }
+    return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID,
+                                   pixmap.alphaType(), std::move(texture),
+                                   sk_ref_sp(pixmap.info().colorSpace()), budgeted);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace {
@@ -666,14 +680,21 @@
     }
     SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight,
                                          dti->fColorType, dti->fAlphaType, colorSpace);
-    SkAutoSTArray<16, GrMipLevel> texels(mipLevelCount);
-    for (int i = 0; i < mipLevelCount; i++) {
-        texels[i].fPixels = dti->fMipMapLevelData[i].fPixelData;
-        texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
-    }
+    if (mipLevelCount == 1) {
+        SkPixmap pixmap;
+        pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData, dti->fMipMapLevelData[0].fRowBytes);
+        return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
+    } else {
+        std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
+        for (int i = 0; i < mipLevelCount; i++) {
+            texels[i].fPixels = dti->fMipMapLevelData[i].fPixelData;
+            texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
+        }
 
-    return SkImage::MakeTextureFromMipMap(context, info, texels.get(), mipLevelCount,
-                                          SkBudgeted::kYes, dti->fColorMode);
+        return SkImage::MakeTextureFromMipMap(context, info, texels.get(),
+                                              mipLevelCount, SkBudgeted::kYes,
+                                              dti->fColorMode);
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index b16b8ea..4f9d944 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -92,6 +92,13 @@
     return SkImage::MakeRasterData(info, std::move(data), info.minRowBytes());
 }
 #if SK_SUPPORT_GPU // not gpu-specific but currently only used in GPU tests
+static sk_sp<SkImage> create_image_565() {
+    const SkImageInfo info = SkImageInfo::Make(20, 20, kRGB_565_SkColorType, kOpaque_SkAlphaType);
+    auto surface(SkSurface::MakeRaster(info));
+    draw_image_test_pattern(surface->getCanvas());
+    return surface->makeImageSnapshot();
+}
+
 static sk_sp<SkImage> create_image_large(int maxTextureSize) {
     const SkImageInfo info = SkImageInfo::MakeN32(maxTextureSize + 1, 32, kOpaque_SkAlphaType);
     auto surface(SkSurface::MakeRaster(info));
@@ -101,6 +108,23 @@
     surface->getCanvas()->drawRect(SkRect::MakeXYWH(4000, 2, 28000, 30), paint);
     return surface->makeImageSnapshot();
 }
+static sk_sp<SkImage> create_image_ct() {
+    SkPMColor colors[] = {
+        SkPreMultiplyARGB(0xFF, 0xFF, 0xFF, 0x00),
+        SkPreMultiplyARGB(0x80, 0x00, 0xA0, 0xFF),
+        SkPreMultiplyARGB(0xFF, 0xBB, 0x00, 0xBB)
+    };
+    sk_sp<SkColorTable> colorTable(new SkColorTable(colors, SK_ARRAY_COUNT(colors)));
+    uint8_t data[] = {
+        0, 0, 0, 0, 0,
+        0, 1, 1, 1, 0,
+        0, 1, 2, 1, 0,
+        0, 1, 1, 1, 0,
+        0, 0, 0, 0, 0
+    };
+    SkImageInfo info = SkImageInfo::Make(5, 5, kIndex_8_SkColorType, kPremul_SkAlphaType);
+    return SkImage::MakeRasterCopy(SkPixmap(info, data, 5, colorTable.get()));
+}
 static sk_sp<SkImage> create_picture_image() {
     SkPictureRecorder recorder;
     SkCanvas* canvas = recorder.beginRecording(10, 10);
@@ -776,6 +800,31 @@
     }
 }
 
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(NewTextureFromPixmap, reporter, ctxInfo) {
+    for (auto create : {&create_image,
+                        &create_image_565,
+                        &create_image_ct}) {
+        sk_sp<SkImage> image((*create)());
+        if (!image) {
+            ERRORF(reporter, "Could not create image");
+            return;
+        }
+
+        SkPixmap pixmap;
+        if (!image->peekPixels(&pixmap)) {
+            ERRORF(reporter, "peek failed");
+        } else {
+            sk_sp<SkImage> texImage(SkImage::MakeTextureFromPixmap(ctxInfo.grContext(), pixmap,
+                                                                   SkBudgeted::kNo));
+            if (!texImage) {
+                ERRORF(reporter, "NewTextureFromPixmap failed.");
+            } else {
+                check_images_same(reporter, image.get(), texImage.get());
+            }
+        }
+    }
+}
+
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
     GrContext* context = ctxInfo.grContext();
     sk_gpu_test::TestContext* testContext = ctxInfo.testContext();