Update GrBitmapTextureMaker for handling mipped requests

Specifically this updates the case when we are requesting to use mip
maps but there is already an unmipped version in the cache. Previously
we just grabbed the unmipped.

Now we will create a new mipped resource. Upload the cpu data to all
the levels besides the base, copy the base level on GPU from the
original resource to the mipped one. Then the mipped resource will
take over the originals unique key.

Bug: skia:
Change-Id: I38e9725c93280dc2460a0be8a7a229e7f20e1614
Reviewed-on: https://skia-review.googlesource.com/43840
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index 6654901..00dd48d 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -8,10 +8,13 @@
 #include "GrBitmapTextureMaker.h"
 
 #include "GrContext.h"
+#include "GrContextPriv.h"
 #include "GrGpuResourcePriv.h"
 #include "GrResourceProvider.h"
+#include "GrSurfaceContext.h"
 #include "SkBitmap.h"
 #include "SkGr.h"
+#include "SkMipMap.h"
 #include "SkPixelRef.h"
 
 static bool bmp_is_alpha_only(const SkBitmap& bm) { return kAlpha_8_SkColorType == bm.colorType(); }
@@ -34,17 +37,25 @@
         return nullptr;
     }
 
-    sk_sp<GrTextureProxy> proxy;
+    sk_sp<GrTextureProxy> originalProxy;
 
     if (fOriginalKey.isValid()) {
-        proxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey(
-                                                          fOriginalKey, kTopLeft_GrSurfaceOrigin);
-        if (proxy) {
-            return proxy;
+        originalProxy = this->context()->resourceProvider()->findOrCreateProxyByUniqueKey(
+                                                            fOriginalKey, kTopLeft_GrSurfaceOrigin);
+        if (originalProxy && (!willBeMipped || originalProxy->isMipMapped())) {
+            return originalProxy;
         }
     }
+
+    sk_sp<GrTextureProxy> proxy;
     if (willBeMipped) {
-        proxy = GrGenerateMipMapsAndUploadToTextureProxy(this->context(), fBitmap, dstColorSpace);
+        if (!originalProxy) {
+            proxy = GrGenerateMipMapsAndUploadToTextureProxy(this->context(), fBitmap,
+                                                             dstColorSpace);
+        } else {
+            proxy = GrCopyBaseMipMapToTextureProxy(this->context(), originalProxy.get(),
+                                                   dstColorSpace);
+        }
     }
     if (!proxy) {
         proxy = GrUploadBitmapToTextureProxy(this->context()->resourceProvider(), fBitmap,
@@ -52,6 +63,15 @@
     }
     if (proxy && fOriginalKey.isValid()) {
         SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
+        if (originalProxy) {
+            // In this case we are stealing the key from the original proxy which should only happen
+            // when we have just generated mipmaps for an originally unmipped proxy/texture. This
+            // means that all future uses of the key will access the mipmapped version. The texture
+            // backing the unmipped version will remain in the resource cache until the last texture
+            // proxy referencing it is deleted at which time it too will be deleted or recycled.
+            this->context()->resourceProvider()->removeUniqueKeyFromProxy(fOriginalKey,
+                                                                          originalProxy.get());
+        }
         this->context()->resourceProvider()->assignUniqueKeyToProxy(fOriginalKey, proxy.get());
         GrInstallBitmapUniqueKeyInvalidator(fOriginalKey, fBitmap.pixelRef());
     }