Refactor GrCaps::renderTargetWritePixelsSupported to support for some GL workarounds

Make indirect path in writeSurfacePixels2 use a copy rather than a draw.

Fix issue in GrVkGpu where render target dirty region is not updated after copy-as-draw

Remove unnecessary resolve of MSAA RT in GrVkCopyManager.

Splits WritePixelsNonTexture_Gpu test into MSAA and non-MSAA variants. MSAA variant blacklisted
on Adreno because of:

Bug: skia:7663

~~~~~~AND~~~~~~~

Revert "Suppress CopySurface test on Nexus 7"

This reverts commit b42b6169d52408a1712c2740655300465cd6ff1e.

Bug: skia:7658
Change-Id: I8337d718efb41e266537744bbf5ff8b1545322a7
Reviewed-on: https://skia-review.googlesource.com/110700
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 5b3d664..c61a6c1 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1054,10 +1054,7 @@
         return false;
     }
 
-    auto dstRTProxy = dstProxy->asRenderTargetProxy();
-    if (dstRTProxy &&
-        !fContext->caps()->renderTargetWritePixelsSupported(SkToBool(dstProxy->asTextureProxy()),
-                                                            dstRTProxy->numColorSamples())) {
+    if (!fContext->caps()->surfaceSupportsWritePixels(dstSurface)) {
         GrSurfaceDesc desc;
         desc.fConfig = dstProxy->config();
         desc.fWidth = width;
@@ -1078,14 +1075,7 @@
                                        srcColorSpace, buffer, rowBytes, pixelOpsFlags)) {
             return false;
         }
-        GrPaint paint;
-        paint.setAllowSRGBInputs(true);
-        paint.addColorTextureProcessor(std::move(tempProxy), SkMatrix::I());
-        paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-        dst->asRenderTargetContext()->drawRect(GrNoClip(), std::move(paint), GrAA::kNo,
-                                               SkMatrix::MakeTrans(left, top),
-                                               SkRect::MakeIWH(width, height));
-        return true;
+        return dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top});
     }
 
     // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type.
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 3bdf5d0..c31cdc7 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -2391,9 +2391,6 @@
         SkASSERT(!fUseDrawInsteadOfAllRenderTargetWrites);
         SkASSERT(!fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines);
     }
-    if (options.fUseDrawInsteadOfPartialRenderTargetWrite) {
-        fUseDrawInsteadOfAllRenderTargetWrites = true;
-    }
     if (GrContextOptions::Enable::kNo == options.fUseDrawInsteadOfGLClear) {
         fUseDrawToClearColor = false;
     } else if (GrContextOptions::Enable::kYes == options.fUseDrawInsteadOfGLClear) {
@@ -2404,6 +2401,26 @@
     }
 }
 
+bool GrGLCaps::surfaceSupportsWritePixels(const GrSurface* surface) const {
+    if (fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO) {
+        if (auto tex = static_cast<const GrGLTexture*>(surface->asTexture())) {
+            if (tex->hasBaseLevelBeenBoundToFBO()) {
+                return false;
+            }
+        }
+    }
+    if (auto rt = surface->asRenderTarget()) {
+        if (fUseDrawInsteadOfAllRenderTargetWrites) {
+            return false;
+        }
+        if (rt->numColorSamples() > 1 && this->usesMSAARenderBuffers()) {
+            return false;
+        }
+        return SkToBool(surface->asTexture());
+    }
+    return true;
+}
+
 bool GrGLCaps::onIsMixedSamplesSupportedForRT(const GrBackendRenderTarget& backendRT) const {
     const GrGLFramebufferInfo* fbInfo = backendRT.getGLFramebufferInfo();
     SkASSERT(fbInfo);
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index f7b4f68..770ebca 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -316,12 +316,7 @@
     /// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
     bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
 
-    bool renderTargetWritePixelsSupported(bool isAlsoTexture, int sampleCnt) const override {
-        if (sampleCnt > 1 && this->usesMSAARenderBuffers()) {
-            return false;
-        }
-        return isAlsoTexture;
-    }
+    bool surfaceSupportsWritePixels(const GrSurface* surface) const override;
 
     /// Does ReadPixels support reading readConfig pixels from a FBO that is surfaceConfig?
     bool readPixelsSupported(GrPixelConfig surfaceConfig,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 76baafb..af7c470 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3462,6 +3462,7 @@
         return false;
     }
     // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
+    // This implicitly handles this->glCaps().useDrawInsteadOfAllRenderTargetWrites().
     bool preferCopy = SkToBool(dst->asRenderTarget());
     if (preferCopy && src->asTexture()) {
         if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index 3ef404f..d8a2aad 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -67,9 +67,7 @@
         return 0;
     }
 
-    bool renderTargetWritePixelsSupported(bool isAlsoTexture, int sampleCnt) const override {
-        return true;
-    }
+    bool surfaceSupportsWritePixels(const GrSurface* surface) const override { return true; }
 
     bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
                             bool* rectsMustMatch, bool* disallowSubrect) const override {
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index 61eaffe..1252fd8 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -31,9 +31,7 @@
     int getRenderTargetSampleCount(int requestedCount, GrPixelConfig) const override;
     int maxRenderTargetSampleCount(GrPixelConfig) const override;
 
-    bool renderTargetWritePixelsSupported(bool isAlsoTexture, int sampleCnt) const override {
-        return true;
-    }
+    bool surfaceSupportsWritePixels(const GrSurface* surface) const override { return true; }
 
     bool isConfigCopyable(GrPixelConfig config) const override {
         return true;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 602d07b..869d6e0 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -6,9 +6,9 @@
  */
 
 #include "GrVkCaps.h"
-
 #include "GrBackendSurface.h"
 #include "GrRenderTargetProxy.h"
+#include "GrRenderTarget.h"
 #include "GrShaderCaps.h"
 #include "GrVkUtil.h"
 #include "vk/GrVkBackendContext.h"
@@ -429,6 +429,13 @@
     return table[table.count() - 1];
 }
 
+bool GrVkCaps::surfaceSupportsWritePixels(const GrSurface* surface) const {
+    if (auto rt = surface->asRenderTarget()) {
+        return rt->numColorSamples() <= 1 && SkToBool(surface->asTexture());
+    }
+    return true;
+}
+
 bool validate_image_info(VkFormat format, SkColorType ct, GrPixelConfig* config) {
     *config = kUnknown_GrPixelConfig;
 
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 55ed9168..14f37c9 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -40,9 +40,7 @@
     int getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const override;
     int maxRenderTargetSampleCount(GrPixelConfig config) const override;
 
-    bool renderTargetWritePixelsSupported(bool isAlsoTexture, int sampleCnt) const override {
-        return sampleCnt <= 1 && isAlsoTexture;
-    }
+    bool surfaceSupportsWritePixels(const GrSurface* surface) const override;
 
     bool isConfigTexturableLinearly(GrPixelConfig config) const {
         return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fLinearFlags);
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 95c86ef..e4a980a 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1845,6 +1845,8 @@
     }
 
     if (fCopyManager.copySurfaceAsDraw(this, dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
+        auto dstRect = srcRect.makeOffset(dstPoint.fX, dstPoint.fY);
+        this->didWriteToSurface(dst, dstOrigin, &dstRect);
         return true;
     }