Rework how initial clearing of texture works.

1) It only applies when a texture is created, not when recycled from cache

2) It is all textures or none, not a flag GrSurfaceDesc

3) It is implemented by GrGpu clearing the texture after creation if
such a thing is supported in underlying API. Otherwise, GrResourceProvider
must provide pre-zeroed mip levels.

4) Works for MIP mapped textures (all levels without initial data are cleared)

This could cause performance regressions in WebGL until we re-add the
ability to clear using glCear() in GL. Doing that requires making the "can
clear using GrGpu" caps query be per-format. Deferring doing that until
GrPixelConfig work is farther along.

Bug: skia:6718


Change-Id: I234715b9faaf61e8b44d54464497a17cd553585d

start

Change-Id: Ib84a8c3ece010cc3164b18895107e78484cbf76b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/226977
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index f007304..addbc15 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -100,7 +100,7 @@
 }
 
 static bool validate_levels(int w, int h, const GrMipLevel texels[], int mipLevelCount, int bpp,
-                            const GrCaps* caps) {
+                            const GrCaps* caps, bool mustHaveDataForAllLevels = false) {
     SkASSERT(mipLevelCount > 0);
     bool hasBasePixels = texels[0].fPixels;
     int levelsWithPixelsCnt = 0;
@@ -138,7 +138,10 @@
     if (!hasBasePixels) {
         return levelsWithPixelsCnt == 0;
     }
-    return levelsWithPixelsCnt == 1 || levelsWithPixelsCnt == mipLevelCount;
+    if (levelsWithPixelsCnt == 1 && !mustHaveDataForAllLevels) {
+        return true;
+    }
+    return levelsWithPixelsCnt == mipLevelCount;
 }
 
 sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
@@ -162,14 +165,15 @@
     // Attempt to catch un- or wrongly initialized sample counts.
     SkASSERT(desc.fSampleCnt > 0 && desc.fSampleCnt <= 64);
 
+    bool mustHaveDataForAllLevels = this->caps()->createTextureMustSpecifyAllLevels();
     if (mipLevelCount) {
-        if (desc.fFlags & kPerformInitialClear_GrSurfaceFlag) {
-            return nullptr;
-        }
         int bpp = GrBytesPerPixel(desc.fConfig);
-        if (!validate_levels(desc.fWidth, desc.fHeight, texels, mipLevelCount, bpp, this->caps())) {
+        if (!validate_levels(desc.fWidth, desc.fHeight, texels, mipLevelCount, bpp, this->caps(),
+                             mustHaveDataForAllLevels)) {
             return nullptr;
         }
+    } else if (mustHaveDataForAllLevels) {
+        return nullptr;
     }
 
     this->handleDirtyContext();
@@ -201,6 +205,8 @@
         height < 1 || height > this->caps()->maxTextureSize()) {
         return nullptr;
     }
+    // Note if we relax the requirement that data must be provided then we must check
+    // caps()->shouldInitializeTextures() here.
     if (!data) {
         return nullptr;
     }