Don't execute onFlush op lists until after GPU data is uploaded

Bug: skia:
Change-Id: Ide85e802fd6e6a19412457dbaded3545b962c240
Reviewed-on: https://skia-review.googlesource.com/55562
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index f1e116f..6076609 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -137,6 +137,8 @@
 
     GrOnFlushResourceProvider onFlushProvider(this);
 
+    // Prepare any onFlush op lists (e.g. atlases).
+    SkSTArray<8, sk_sp<GrOpList>> onFlushOpLists;
     if (!fOnFlushCBObjects.empty()) {
         // MDB TODO: pre-MDB '1' is the correct pre-allocated size. Post-MDB it will need
         // to be larger.
@@ -144,27 +146,19 @@
         for (int i = 0; i < fOpLists.count(); ++i) {
             opListIds[i] = fOpLists[i]->uniqueID();
         }
-
-        SkSTArray<1, sk_sp<GrRenderTargetContext>> renderTargetContexts;
+        SkSTArray<4, sk_sp<GrRenderTargetContext>> renderTargetContexts;
         for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
             onFlushCBObject->preFlush(&onFlushProvider,
                                       opListIds.get(), opListIds.count(),
                                       &renderTargetContexts);
-            if (!renderTargetContexts.count()) {
-                continue;       // This is fine. No atlases of this type are required for this flush
-            }
-
-            for (int j = 0; j < renderTargetContexts.count(); ++j) {
-                GrOpList* opList = renderTargetContexts[j]->getOpList();
-                if (!opList) {
+            for (const sk_sp<GrRenderTargetContext>& rtc : renderTargetContexts) {
+                sk_sp<GrOpList> onFlushOpList = sk_ref_sp(rtc->getOpList());
+                if (!onFlushOpList) {
                     continue;   // Odd - but not a big deal
                 }
-                SkASSERT(opList->unique());
-                opList->makeClosed(*fContext->caps());
-                opList->prepare(&fFlushState);
-                if (!opList->execute(&fFlushState)) {
-                    continue;         // This is bad
-                }
+                onFlushOpList->makeClosed(*fContext->caps());
+                onFlushOpList->prepare(&fFlushState);
+                onFlushOpLists.push_back(std::move(onFlushOpList));
             }
             renderTargetContexts.reset();
         }
@@ -201,6 +195,17 @@
     // Upload all data to the GPU
     fFlushState.preIssueDraws();
 
+    // Execute the onFlush op lists first, if any.
+    for (sk_sp<GrOpList>& onFlushOpList : onFlushOpLists) {
+        if (!onFlushOpList->execute(&fFlushState)) {
+            SkDebugf("WARNING: onFlushOpList failed to execute.\n");
+        }
+        SkASSERT(onFlushOpList->unique());
+        onFlushOpList = nullptr;
+    }
+    onFlushOpLists.reset();
+
+    // Execute the normal op lists.
     for (int i = 0; i < fOpLists.count(); ++i) {
         if (!fOpLists[i]) {
             continue;
@@ -227,6 +232,7 @@
             // https://bugs.chromium.org/p/skia/issues/detail?id=7111
             fOpLists[i]->endFlush();
         }
+        fOpLists[i] = nullptr;
     }
     fOpLists.reset();
 
diff --git a/tests/OnFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
index e47a76b..3701651 100644
--- a/tests/OnFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -166,16 +166,6 @@
 
 }  // anonymous namespace
 
-#ifdef SK_DEBUG
-#include "SkImageEncoder.h"
-#include "sk_tool_utils.h"
-
-static void save_bm(const SkBitmap& bm, const char name[]) {
-    bool result = sk_tool_utils::EncodeImageToFile(name, bm, SkEncodedImageFormat::kPNG, 100);
-    SkASSERT(result);
-}
-#endif
-
 static constexpr SkRect kEmptyRect = SkRect::MakeEmpty();
 
 namespace {
@@ -294,23 +284,6 @@
         fAtlasDest = atlasDest;
     }
 
-    void saveRTC(sk_sp<GrRenderTargetContext> rtc) {
-        SkASSERT(!fRTC);
-        fRTC = rtc;
-    }
-
-#ifdef SK_DEBUG
-    void saveAtlasToDisk() {
-        SkBitmap readBack;
-        readBack.allocN32Pixels(fRTC->width(), fRTC->height());
-
-        bool result = fRTC->readPixels(readBack.info(),
-                                       readBack.getPixels(), readBack.rowBytes(), 0, 0);
-        SkASSERT(result);
-        save_bm(readBack, "atlas-real.png");
-    }
-#endif
-
     /*
      * This callback back creates the atlas and updates the AtlasedRectOps to read from it
      */
@@ -389,9 +362,6 @@
             this->clearOpsFor(lists[i]);
         }
 
-        // Hide a ref to the RTC in AtlasData so we can check on it later
-        this->saveRTC(rtc);
-
         results->push_back(std::move(rtc));
     }
 
@@ -420,9 +390,6 @@
     // Each opList containing AtlasedRectOps gets its own internal singly-linked list
     SkTDArray<LinkedListHeader>  fOps;
 
-    // The RTC used to create the atlas
-    sk_sp<GrRenderTargetContext> fRTC;
-
     // For the time being we need to pre-allocate the atlas bc the TextureSamplers require
     // a GrTexture
     sk_sp<GrTextureProxy>        fAtlasDest;
@@ -467,7 +434,14 @@
 // Enable this if you want to debug the final draws w/o having the atlasCallback create the
 // atlas
 #if 0
+#include "SkImageEncoder.h"
 #include "SkGrPriv.h"
+#include "sk_tool_utils.h"
+
+static void save_bm(const SkBitmap& bm, const char name[]) {
+    bool result = sk_tool_utils::EncodeImageToFile(name, bm, SkEncodedImageFormat::kPNG, 100);
+    SkASSERT(result);
+}
 
 sk_sp<GrTextureProxy> pre_create_atlas(GrContext* context) {
     SkBitmap bm;
@@ -601,11 +575,6 @@
 
     object.markAsDone();
 
-#if 0
-    save_bm(readBack, "atlas-final-image.png");
-    data.saveAtlasToDisk();
-#endif
-
     int x = kDrawnTileSize/2;
     test_color(reporter, readBack, x, SK_ColorRED);
     x += kDrawnTileSize;