Make GrGpu read/write pixels take GrSurface

Review URL: https://codereview.chromium.org/1262473004
diff --git a/src/gpu/GrBatchTarget.h b/src/gpu/GrBatchTarget.h
index 19cfb09..8a78904 100644
--- a/src/gpu/GrBatchTarget.h
+++ b/src/gpu/GrBatchTarget.h
@@ -51,8 +51,7 @@
                                 int left, int top, int width, int height,
                                 GrPixelConfig config, const void* buffer,
                                 size_t rowBytes) {
-            return fGpu->writeTexturePixels(texture, left, top, width, height, config, buffer,
-                                            rowBytes);
+            return fGpu->writePixels(texture, left, top, width, height, config, buffer, rowBytes);
         }
 
     private:
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index b7f8ac1..fd788cb 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -416,9 +416,9 @@
                 buffer = tmpPixels.get();
                 applyPremulToSrc = false;
             }
-            if (!fGpu->writeTexturePixels(tempTexture, 0, 0, width, height,
-                                          tempDrawInfo.fTempSurfaceDesc.fConfig, buffer,
-                                          rowBytes)) {
+            if (!fGpu->writePixels(tempTexture, 0, 0, width, height,
+                                   tempDrawInfo.fTempSurfaceDesc.fConfig, buffer,
+                                   rowBytes)) {
                 return false;
             }
             SkMatrix matrix;
@@ -437,7 +437,6 @@
         }
     }
     if (!tempTexture) {
-        SkASSERT(surface->asTexture());
         if (applyPremulToSrc) {
             size_t tmpRowBytes = 4 * width;
             tmpPixels.reset(width * height);
@@ -449,8 +448,7 @@
             buffer = tmpPixels.get();
             applyPremulToSrc = false;
         }
-        return fGpu->writeTexturePixels(surface->asTexture(), left, top, width, height, srcConfig,
-                                        buffer, rowBytes);
+        return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
     }
     return true;
 }
@@ -494,7 +492,7 @@
         return false;
     }
 
-    SkAutoTUnref<GrRenderTarget> rtToRead(SkSafeRef(src->asRenderTarget()));
+    SkAutoTUnref<GrSurface> surfaceToRead(SkRef(src));
     bool didTempDraw = false;
     if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
         GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch;
@@ -537,7 +535,7 @@
                 GrDrawContext* drawContext = this->drawContext();
                 drawContext->drawRect(temp->asRenderTarget(), GrClip::WideOpen(), paint,
                                       SkMatrix::I(), rect, NULL);
-                rtToRead.reset(SkRef(temp->asRenderTarget()));
+                surfaceToRead.reset(SkRef(temp.get()));
                 left = 0;
                 top = 0;
                 didTempDraw = true;
@@ -550,13 +548,14 @@
     }
     GrPixelConfig configToRead = dstConfig;
     if (didTempDraw) {
-        this->flushSurfaceWrites(rtToRead);
+        this->flushSurfaceWrites(surfaceToRead);
         // We swapped R and B while doing the temp draw. Swap back on the read.
         if (tempDrawInfo.fSwapRAndB) {
             configToRead = GrPixelConfigSwapRAndB(dstConfig);
         }
     }
-    if (!fGpu->readPixels(rtToRead, left, top, width, height, configToRead, buffer, rowBytes)) {
+    if (!fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead, buffer,
+                           rowBytes)) {
         return false;
     }
 
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index c61979b..c7137ef 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -287,22 +287,20 @@
     return true;
 }
 
-bool GrGpu::readPixels(GrRenderTarget* target,
+bool GrGpu::readPixels(GrSurface* surface,
                        int left, int top, int width, int height,
                        GrPixelConfig config, void* buffer,
                        size_t rowBytes) {
     this->handleDirtyContext();
-    return this->onReadPixels(target, left, top, width, height,
-                              config, buffer, rowBytes);
+    return this->onReadPixels(surface, left, top, width, height, config, buffer, rowBytes);
 }
 
-bool GrGpu::writeTexturePixels(GrTexture* texture,
-                               int left, int top, int width, int height,
-                               GrPixelConfig config, const void* buffer,
-                               size_t rowBytes) {
+bool GrGpu::writePixels(GrSurface* surface,
+                        int left, int top, int width, int height,
+                        GrPixelConfig config, const void* buffer,
+                        size_t rowBytes) {
     this->handleDirtyContext();
-    if (this->onWriteTexturePixels(texture, left, top, width, height,
-                                   config, buffer, rowBytes)) {
+    if (this->onWritePixels(surface, left, top, width, height, config, buffer, rowBytes)) {
         fStats.incTextureUploads();
         return true;
     }
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 8bb676d..e6f37cc 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -210,8 +210,7 @@
     /**
      * Reads a rectangle of pixels from a render target.
      *
-     * @param renderTarget  the render target to read from. NULL means the
-     *                      current render target.
+     * @param surface       The surface to read from
      * @param left          left edge of the rectangle to read (inclusive)
      * @param top           top edge of the rectangle to read (inclusive)
      * @param width         width of rectangle to read in pixels.
@@ -227,13 +226,14 @@
      *              because of a unsupported pixel config or because no render
      *              target is currently set.
      */
-    bool readPixels(GrRenderTarget* renderTarget,
+    bool readPixels(GrSurface* surface,
                     int left, int top, int width, int height,
                     GrPixelConfig config, void* buffer, size_t rowBytes);
 
     /**
-     * Updates the pixels in a rectangle of a texture.
+     * Updates the pixels in a rectangle of a surface.
      *
+     * @param surface       The surface to write to.
      * @param left          left edge of the rectangle to write (inclusive)
      * @param top           top edge of the rectangle to write (inclusive)
      * @param width         width of rectangle to write in pixels.
@@ -243,10 +243,10 @@
      * @param rowBytes      number of bytes between consecutive rows. Zero
      *                      means rows are tightly packed.
      */
-    bool writeTexturePixels(GrTexture* texture,
-                            int left, int top, int width, int height,
-                            GrPixelConfig config, const void* buffer,
-                            size_t rowBytes);
+    bool writePixels(GrSurface* surface,
+                     int left, int top, int width, int height,
+                     GrPixelConfig config, const void* buffer,
+                     size_t rowBytes);
 
     /**
      * Clear the passed in render target. Ignores the draw state and clip. Clears the whole thing if
@@ -468,17 +468,18 @@
                                       GrPixelConfig srcConfig, DrawPreference*,
                                       WritePixelTempDrawInfo*) = 0;
 
-    virtual bool onReadPixels(GrRenderTarget* target,
+    // overridden by backend-specific derived class to perform the surface read
+    virtual bool onReadPixels(GrSurface*,
                               int left, int top, int width, int height,
                               GrPixelConfig,
                               void* buffer,
                               size_t rowBytes) = 0;
 
-    // overridden by backend-specific derived class to perform the texture update
-    virtual bool onWriteTexturePixels(GrTexture* texture,
-                                      int left, int top, int width, int height,
-                                      GrPixelConfig config, const void* buffer,
-                                      size_t rowBytes) = 0;
+    // overridden by backend-specific derived class to perform the surface write
+    virtual bool onWritePixels(GrSurface*,
+                               int left, int top, int width, int height,
+                               GrPixelConfig config, const void* buffer,
+                               size_t rowBytes) = 0;
 
     // overridden by backend-specific derived class to perform the resolve
     virtual void onResolveRenderTarget(GrRenderTarget* target) = 0;
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index fd2908e..ce98aa7 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -204,7 +204,7 @@
 
     void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override {}
 
-    bool onReadPixels(GrRenderTarget* target,
+    bool onReadPixels(GrSurface* surface,
                       int left, int top, int width, int height,
                       GrPixelConfig,
                       void* buffer,
@@ -212,10 +212,10 @@
         return false;
     }
 
-    bool onWriteTexturePixels(GrTexture* texture,
-                              int left, int top, int width, int height,
-                              GrPixelConfig config, const void* buffer,
-                              size_t rowBytes) override {
+    bool onWritePixels(GrSurface* surface,
+                       int left, int top, int width, int height,
+                       GrPixelConfig config, const void* buffer,
+                       size_t rowBytes) override {
         return false;
     }
 
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 41cf62c..781e772 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -513,6 +513,12 @@
         return false;
     }
 
+    // This subclass only allows writes to textures. If the dst is not a texture we have to draw
+    // into it. We could use glDrawPixels on GLs that have it, but we don't today.
+    if (!dstSurface->asTexture()) {
+        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+    }
+
     tempDrawInfo->fSwapRAndB = false;
 
     // These settings we will always want if a temp draw is performed. Initially set the config
@@ -553,14 +559,17 @@
     return true;
 }
 
-bool GrGLGpu::onWriteTexturePixels(GrTexture* texture,
-                                   int left, int top, int width, int height,
-                                   GrPixelConfig config, const void* buffer,
-                                   size_t rowBytes) {
+bool GrGLGpu::onWritePixels(GrSurface* surface,
+                            int left, int top, int width, int height,
+                            GrPixelConfig config, const void* buffer,
+                            size_t rowBytes) {
     if (NULL == buffer) {
         return false;
     }
-    GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
+    GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
+    if (!glTex) {
+        return false;
+    }
 
     this->setScratchTextureUnit();
     GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID()));
@@ -577,7 +586,7 @@
     }
 
     if (success) {
-        texture->texturePriv().dirtyMipMaps(true);
+        glTex->texturePriv().dirtyMipMaps(true);
         return true;
     }
 
@@ -1726,6 +1735,12 @@
         return false;
     }
 
+    // This subclass can only read pixels from a render target. We could use glTexSubImage2D on
+    // GL versions that support it but we don't today.
+    if (!srcSurface->asRenderTarget()) {
+        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+    }
+
     tempDrawInfo->fSwapRAndB = false;
 
     // These settings we will always want if a temp draw is performed. The config is set below
@@ -1773,27 +1788,32 @@
     return true;
 }
 
-bool GrGLGpu::onReadPixels(GrRenderTarget* target,
+bool GrGLGpu::onReadPixels(GrSurface* surface,
                            int left, int top,
                            int width, int height,
                            GrPixelConfig config,
                            void* buffer,
                            size_t rowBytes) {
-    SkASSERT(target);
+    SkASSERT(surface);
 
     // We cannot read pixels into a compressed buffer
     if (GrPixelConfigIsCompressed(config)) {
         return false;
     }
 
+    GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
+    if (!tgt) {
+        return false;
+    }
+
     GrGLenum format = 0;
     GrGLenum type = 0;
-    bool flipY = kBottomLeft_GrSurfaceOrigin == target->origin();
+    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
     if (!this->configToGLFormats(config, false, NULL, &format, &type)) {
         return false;
     }
     size_t bpp = GrBytesPerPixel(config);
-    if (!GrSurfacePriv::AdjustReadPixelParams(target->width(), target->height(), bpp,
+    if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
                                               &left, &top, &width, &height,
                                               &buffer,
                                               &rowBytes)) {
@@ -1801,12 +1821,11 @@
     }
 
     // resolve the render target if necessary
-    GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
     switch (tgt->getResolveType()) {
         case GrGLRenderTarget::kCantResolve_ResolveType:
             return false;
         case GrGLRenderTarget::kAutoResolves_ResolveType:
-            this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
+            this->flushRenderTarget(tgt, &SkIRect::EmptyIRect());
             break;
         case GrGLRenderTarget::kCanResolve_ResolveType:
             this->onResolveRenderTarget(tgt);
@@ -1823,7 +1842,7 @@
 
     // the read rect is viewport-relative
     GrGLIRect readRect;
-    readRect.setRelativeTo(glvp, left, top, width, height, target->origin());
+    readRect.setRelativeTo(glvp, left, top, width, height, tgt->origin());
 
     size_t tightRowBytes = bpp * width;
     if (0 == rowBytes) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 0442e11..5724107 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -137,17 +137,17 @@
 
     void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
 
-    bool onReadPixels(GrRenderTarget* target,
+    bool onReadPixels(GrSurface*,
                       int left, int top,
                       int width, int height,
                       GrPixelConfig,
                       void* buffer,
                       size_t rowBytes) override;
 
-    bool onWriteTexturePixels(GrTexture* texture,
-                              int left, int top, int width, int height,
-                              GrPixelConfig config, const void* buffer,
-                              size_t rowBytes) override;
+    bool onWritePixels(GrSurface*,
+                       int left, int top, int width, int height,
+                       GrPixelConfig config, const void* buffer,
+                       size_t rowBytes) override;
 
     void onResolveRenderTarget(GrRenderTarget* target) override;