Remove origin field from GrSurface (take 2)

This mainly consists of rm origin from GrSurface and the wrapBackEnd*
methods and then re-adding an explicit origin parameter to all the
GrGpu methods that need it.

TBR=bsalomon@google.com

Change-Id: I4248b2a4749ef844da4233ce53b0dc504bc9eb74
Reviewed-on: https://skia-review.googlesource.com/30280
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 4caa842..65ac7ec 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -35,11 +35,6 @@
      */
     SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); }
 
-    GrSurfaceOrigin origin() const {
-        SkASSERT(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);
-        return fOrigin;
-    }
-
     /**
      * Retrieves the pixel config specified when the surface was created.
      * For render targets this can be kUnknown_GrPixelConfig
@@ -81,8 +76,7 @@
             : INHERITED(gpu)
             , fConfig(desc.fConfig)
             , fWidth(desc.fWidth)
-            , fHeight(desc.fHeight)
-            , fOrigin(desc.fOrigin) {}
+            , fHeight(desc.fHeight) {}
     ~GrSurface() override {}
 
 
@@ -93,7 +87,6 @@
     GrPixelConfig        fConfig;
     int                  fWidth;
     int                  fHeight;
-    GrSurfaceOrigin      fOrigin;
 
     typedef GrGpuResource INHERITED;
 };
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index ca74772..ba8e9d7 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -192,7 +192,6 @@
         return nullptr;
     }
     sk_sp<GrTexture> tex = context->resourceProvider()->wrapBackendTexture(backendTex,
-                                                                       kTopLeft_GrSurfaceOrigin,
                                                                        kAdopt_GrWrapOwnership);
     if (!tex) {
         glDeleteTextures(1, &texID);
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index ac4fee3..22cdec3 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -54,7 +54,8 @@
 }
 
 std::unique_ptr<SkImageGenerator>
-GrBackendTextureImageGenerator::Make(sk_sp<GrTexture> texture, sk_sp<GrSemaphore> semaphore,
+GrBackendTextureImageGenerator::Make(sk_sp<GrTexture> texture, GrSurfaceOrigin origin,
+                                     sk_sp<GrSemaphore> semaphore,
                                      SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
     if (colorSpace && (!colorSpace->gammaCloseToSRGB() && !colorSpace->gammaIsLinear())) {
         return nullptr;
@@ -82,11 +83,12 @@
     SkImageInfo info = SkImageInfo::Make(texture->width(), texture->height(), colorType, alphaType,
                                          std::move(colorSpace));
     return std::unique_ptr<SkImageGenerator>(new GrBackendTextureImageGenerator(
-            info, texture.get(), context->uniqueID(), std::move(semaphore), backendTexture));
+          info, texture.get(), origin, context->uniqueID(), std::move(semaphore), backendTexture));
 }
 
 GrBackendTextureImageGenerator::GrBackendTextureImageGenerator(const SkImageInfo& info,
                                                                GrTexture* texture,
+                                                               GrSurfaceOrigin origin,
                                                                uint32_t owningContextID,
                                                                sk_sp<GrSemaphore> semaphore,
                                                                const GrBackendTexture& backendTex)
@@ -95,7 +97,7 @@
     , fSemaphore(std::move(semaphore))
     , fLastBorrowingContextID(SK_InvalidGenID)
     , fBackendTexture(backendTex)
-    , fSurfaceOrigin(texture->origin()) { }
+    , fSurfaceOrigin(origin) { }
 
 GrBackendTextureImageGenerator::~GrBackendTextureImageGenerator() {
     fRefHelper->unref();
@@ -146,12 +148,13 @@
             }
         }
 
+        SkASSERT(kDefault_GrSurfaceOrigin != fSurfaceOrigin);
         // We just gained access to the texture. If we're on the original context, we could use the
         // original texture, but we'd have no way of detecting that it's no longer in-use. So we
         // always make a wrapped copy, where the release proc informs us that the context is done
         // with it. This is unfortunate - we'll have two texture objects referencing the same GPU
         // object. However, no client can ever see the original texture, so this should be safe.
-        tex = context->resourceProvider()->wrapBackendTexture(fBackendTexture, fSurfaceOrigin,
+        tex = context->resourceProvider()->wrapBackendTexture(fBackendTexture,
                                                               kBorrow_GrWrapOwnership);
         if (!tex) {
             fRefHelper->fBorrowingContextID = SK_InvalidGenID;
diff --git a/src/gpu/GrBackendTextureImageGenerator.h b/src/gpu/GrBackendTextureImageGenerator.h
index 1124b96..f99055a 100644
--- a/src/gpu/GrBackendTextureImageGenerator.h
+++ b/src/gpu/GrBackendTextureImageGenerator.h
@@ -16,7 +16,8 @@
 
 class GrBackendTextureImageGenerator : public SkImageGenerator {
 public:
-    static std::unique_ptr<SkImageGenerator> Make(sk_sp<GrTexture>, sk_sp<GrSemaphore>,
+    static std::unique_ptr<SkImageGenerator> Make(sk_sp<GrTexture>, GrSurfaceOrigin,
+                                                  sk_sp<GrSemaphore>,
                                                   SkAlphaType, sk_sp<SkColorSpace>);
 
     ~GrBackendTextureImageGenerator() override;
@@ -33,7 +34,7 @@
 #endif
 
 private:
-    GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*,
+    GrBackendTextureImageGenerator(const SkImageInfo& info, GrTexture*, GrSurfaceOrigin,
                                    uint32_t owningContextID, sk_sp<GrSemaphore>,
                                    const GrBackendTexture&);
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 915700c..8714b20 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -449,7 +449,7 @@
     GrGpu::DrawPreference drawPreference = premulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference
                                                        : GrGpu::kNoDraw_DrawPreference;
     GrGpu::WritePixelTempDrawInfo tempDrawInfo;
-    if (!fContext->fGpu->getWritePixelsInfo(dstSurface, width, height,
+    if (!fContext->fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height,
                                             srcConfig, &drawPreference, &tempDrawInfo)) {
         return false;
     }
@@ -501,8 +501,8 @@
             return false;
         }
         GrTexture* texture = tempProxy->priv().peekTexture();
-        if (!fContext->fGpu->writePixels(texture, 0, 0, width, height, tempDrawInfo.fWriteConfig,
-                                         buffer, rowBytes)) {
+        if (!fContext->fGpu->writePixels(texture, tempProxy->origin(), 0, 0, width, height,
+                                         tempDrawInfo.fWriteConfig, buffer, rowBytes)) {
             return false;
         }
         SkMatrix matrix;
@@ -524,8 +524,8 @@
             this->flushSurfaceWrites(renderTargetContext->asRenderTargetProxy());
         }
     } else {
-        return fContext->fGpu->writePixels(dstSurface, left, top, width, height, srcConfig,
-                                           buffer, rowBytes);
+        return fContext->fGpu->writePixels(dstSurface, dstProxy->origin(), left, top, width,
+                                           height, srcConfig, buffer, rowBytes);
     }
     return true;
 }
@@ -579,7 +579,7 @@
     GrGpu::DrawPreference drawPreference = unpremulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference
                                                          : GrGpu::kNoDraw_DrawPreference;
     GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
-    if (!fContext->fGpu->getReadPixelsInfo(srcSurface, width, height, rowBytes,
+    if (!fContext->fGpu->getReadPixelsInfo(srcSurface, srcProxy->origin(), width, height, rowBytes,
                                            dstConfig, &drawPreference, &tempDrawInfo)) {
         return false;
     }
@@ -655,7 +655,7 @@
         this->flushSurfaceWrites(proxyToRead.get());
         configToRead = tempDrawInfo.fReadConfig;
     }
-    if (!fContext->fGpu->readPixels(surfaceToRead,
+    if (!fContext->fGpu->readPixels(surfaceToRead, proxyToRead->origin(),
                                     left, top, width, height, configToRead, buffer, rowBytes)) {
         return false;
     }
@@ -756,7 +756,8 @@
                                                                  sk_sp<SkColorSpace> colorSpace) {
     ASSERT_SINGLE_OWNER_PRIV
 
-    sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(tex, origin));
+    SkASSERT(kDefault_GrSurfaceOrigin != origin);
+    sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(tex));
     if (!surface) {
         return nullptr;
     }
@@ -777,8 +778,10 @@
                                                                    const SkSurfaceProps* props) {
     ASSERT_SINGLE_OWNER_PRIV
 
+    SkASSERT(kDefault_GrSurfaceOrigin != origin);
+
     sk_sp<GrSurface> surface(
-            fContext->resourceProvider()->wrapRenderableBackendTexture(tex, origin, sampleCnt));
+            fContext->resourceProvider()->wrapRenderableBackendTexture(tex, sampleCnt));
     if (!surface) {
         return nullptr;
     }
@@ -799,8 +802,8 @@
                                                 const SkSurfaceProps* surfaceProps) {
     ASSERT_SINGLE_OWNER_PRIV
 
-    sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(backendRT,
-                                                                                   origin));
+    SkASSERT(kDefault_GrSurfaceOrigin != origin);
+    sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(backendRT));
     if (!rt) {
         return nullptr;
     }
@@ -823,9 +826,9 @@
                                                      const SkSurfaceProps* surfaceProps) {
     ASSERT_SINGLE_OWNER_PRIV
 
+    SkASSERT(kDefault_GrSurfaceOrigin != origin);
     sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(
                                                                                         tex,
-                                                                                        origin,
                                                                                         sampleCnt));
     if (!surface) {
         return nullptr;
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index d7ab495..6e21cc2 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -230,7 +230,7 @@
     GrSurface* surface = proxy->priv().peekSurface();
 
     if (fContext->getGpu() && surface->asRenderTarget()) {
-        fContext->getGpu()->resolveRenderTarget(surface->asRenderTarget());
+        fContext->getGpu()->resolveRenderTarget(surface->asRenderTarget(), proxy->origin());
     }
     return result;
 }
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 50a05c8..f99dce4 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -71,17 +71,6 @@
     return false;
 }
 
-static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
-    // By default, GrRenderTargets are GL's normal orientation so that they
-    // can be drawn to by the outside world without the client having
-    // to render upside down.
-    if (kDefault_GrSurfaceOrigin == origin) {
-        return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
-    } else {
-        return origin;
-    }
-}
-
 /**
  * Prior to creating a texture, make sure the type of texture being created is
  * supported by calling check_texture_creation_params.
@@ -149,8 +138,7 @@
     desc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
     // Attempt to catch un- or wrongly initialized sample counts.
     SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64);
-
-    desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
+    SkASSERT(kDefault_GrSurfaceOrigin != desc.fOrigin);
 
     if (mipLevelCount && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
         return nullptr;
@@ -177,7 +165,6 @@
 }
 
 sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
-                                           GrSurfaceOrigin origin,
                                            GrWrapOwnership ownership) {
     this->handleDirtyContext();
     if (!this->caps()->isConfigTexturable(backendTex.config())) {
@@ -187,7 +174,7 @@
         backendTex.height() > this->caps()->maxTextureSize()) {
         return nullptr;
     }
-    sk_sp<GrTexture> tex = this->onWrapBackendTexture(backendTex, origin, ownership);
+    sk_sp<GrTexture> tex = this->onWrapBackendTexture(backendTex, ownership);
     if (!tex) {
         return nullptr;
     }
@@ -195,8 +182,7 @@
 }
 
 sk_sp<GrTexture> GrGpu::wrapRenderableBackendTexture(const GrBackendTexture& backendTex,
-                                                     GrSurfaceOrigin origin, int sampleCnt,
-                                                     GrWrapOwnership ownership) {
+                                                     int sampleCnt, GrWrapOwnership ownership) {
     this->handleDirtyContext();
     if (!this->caps()->isConfigTexturable(backendTex.config()) ||
         !this->caps()->isConfigRenderable(backendTex.config(), sampleCnt > 0)) {
@@ -208,7 +194,7 @@
         return nullptr;
     }
     sk_sp<GrTexture> tex =
-            this->onWrapRenderableBackendTexture(backendTex, origin, sampleCnt, ownership);
+            this->onWrapRenderableBackendTexture(backendTex, sampleCnt, ownership);
     if (!tex) {
         return nullptr;
     }
@@ -222,17 +208,15 @@
     return tex;
 }
 
-sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT,
-                                                     GrSurfaceOrigin origin) {
+sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
     if (!this->caps()->isConfigRenderable(backendRT.config(), backendRT.sampleCnt() > 0)) {
         return nullptr;
     }
     this->handleDirtyContext();
-    return this->onWrapBackendRenderTarget(backendRT, origin);
+    return this->onWrapBackendRenderTarget(backendRT);
 }
 
 sk_sp<GrRenderTarget> GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
-                                                              GrSurfaceOrigin origin,
                                                               int sampleCnt) {
     this->handleDirtyContext();
     if (!this->caps()->isConfigRenderable(tex.config(), sampleCnt > 0)) {
@@ -242,7 +226,7 @@
     if (tex.width() > maxSize || tex.height() > maxSize) {
         return nullptr;
     }
-    return this->onWrapBackendTextureAsRenderTarget(tex, origin, sampleCnt);
+    return this->onWrapBackendTextureAsRenderTarget(tex, sampleCnt);
 }
 
 GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
@@ -265,10 +249,9 @@
     return this->onCreateInstancedRendering();
 }
 
-bool GrGpu::copySurface(GrSurface* dst,
-                        GrSurface* src,
-                        const SkIRect& srcRect,
-                        const SkIPoint& dstPoint) {
+bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                        GrSurface* src, GrSurfaceOrigin srcOrigin,
+                        const SkIRect& srcRect, const SkIPoint& dstPoint) {
     GR_CREATE_TRACE_MARKER_CONTEXT("GrGpu", "copySurface", fContext);
     SkASSERT(dst && src);
     this->handleDirtyContext();
@@ -276,10 +259,11 @@
     if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
         return false;
     }
-    return this->onCopySurface(dst, src, srcRect, dstPoint);
+    return this->onCopySurface(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
 }
 
-bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
+bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                              int width, int height, size_t rowBytes,
                               GrPixelConfig readConfig, DrawPreference* drawPreference,
                               ReadPixelTempDrawInfo* tempDrawInfo) {
     SkASSERT(drawPreference);
@@ -293,8 +277,8 @@
         return false;
     }
 
-   if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
-                                   tempDrawInfo)) {
+   if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, readConfig,
+                                  drawPreference, tempDrawInfo)) {
         return false;
     }
 
@@ -310,7 +294,8 @@
 
     return true;
 }
-bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                               int width, int height,
                                GrPixelConfig srcConfig, DrawPreference* drawPreference,
                                WritePixelTempDrawInfo* tempDrawInfo) {
     SkASSERT(drawPreference);
@@ -318,7 +303,7 @@
     SkASSERT(dstSurface);
     SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
 
-    if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference,
+    if (!this->onGetWritePixelsInfo(dstSurface, dstOrigin, width, height, srcConfig, drawPreference,
                                     tempDrawInfo)) {
         return false;
     }
@@ -336,7 +321,7 @@
     return true;
 }
 
-bool GrGpu::readPixels(GrSurface* surface,
+bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin,
                        int left, int top, int width, int height,
                        GrPixelConfig config, void* buffer,
                        size_t rowBytes) {
@@ -357,13 +342,13 @@
 
     this->handleDirtyContext();
 
-    return this->onReadPixels(surface,
+    return this->onReadPixels(surface, origin,
                               left, top, width, height,
                               config, buffer,
                               rowBytes);
 }
 
-bool GrGpu::writePixels(GrSurface* surface,
+bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
                         int left, int top, int width, int height,
                         GrPixelConfig config, const GrMipLevel texels[], int mipLevelCount) {
     SkASSERT(surface);
@@ -391,7 +376,8 @@
     }
 
     this->handleDirtyContext();
-    if (this->onWritePixels(surface, left, top, width, height, config, texels, mipLevelCount)) {
+    if (this->onWritePixels(surface, origin, left, top, width, height, config,
+                            texels, mipLevelCount)) {
         SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
         this->didWriteToSurface(surface, &rect, mipLevelCount);
         fStats.incTextureUploads();
@@ -400,13 +386,13 @@
     return false;
 }
 
-bool GrGpu::writePixels(GrSurface* surface,
+bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
                         int left, int top, int width, int height,
                         GrPixelConfig config, const void* buffer,
                         size_t rowBytes) {
     GrMipLevel mipLevel = { buffer, rowBytes };
 
-    return this->writePixels(surface, left, top, width, height, config, &mipLevel, 1);
+    return this->writePixels(surface, origin, left, top, width, height, config, &mipLevel, 1);
 }
 
 bool GrGpu::transferPixels(GrTexture* texture,
@@ -439,10 +425,10 @@
     return false;
 }
 
-void GrGpu::resolveRenderTarget(GrRenderTarget* target) {
+void GrGpu::resolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin) {
     SkASSERT(target);
     this->handleDirtyContext();
-    this->onResolveRenderTarget(target);
+    this->onResolveRenderTarget(target, origin);
 }
 
 void GrGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels) const {
@@ -473,7 +459,8 @@
 
     int effectiveSampleCnt;
     SkSTArray<16, SkPoint, true> pattern;
-    this->onQueryMultisampleSpecs(rt, stencil, &effectiveSampleCnt, &pattern);
+    this->onQueryMultisampleSpecs(rt, pipeline.proxy()->origin(), stencil,
+                                  &effectiveSampleCnt, &pattern);
     SkASSERT(effectiveSampleCnt >= rt->numStencilSamples());
 
     uint8_t id;
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 8f11249..a0a552c 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -119,24 +119,23 @@
     /**
      * Implements GrResourceProvider::wrapBackendTexture
      */
-    sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture&, GrSurfaceOrigin, GrWrapOwnership);
+    sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture&, GrWrapOwnership);
 
     /**
      * Implements GrResourceProvider::wrapRenderableBackendTexture
      */
-    sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture&, GrSurfaceOrigin,
+    sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture&,
                                                   int sampleCnt, GrWrapOwnership);
 
     /**
      * Implements GrResourceProvider::wrapBackendRenderTarget
      */
-    sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin);
+    sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&);
 
     /**
      * Implements GrResourceProvider::wrapBackendTextureAsRenderTarget
      */
     sk_sp<GrRenderTarget> wrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                           GrSurfaceOrigin,
                                                            int sampleCnt);
 
     /**
@@ -161,7 +160,7 @@
     /**
      * Resolves MSAA.
      */
-    void resolveRenderTarget(GrRenderTarget* target);
+    void resolveRenderTarget(GrRenderTarget*, GrSurfaceOrigin);
 
     /** Info struct returned by getReadPixelsInfo about performing intermediate draws before
         reading pixels for performance or correctness. */
@@ -211,7 +210,8 @@
      * that would allow a successful readPixels call. The passed width, height, and rowBytes,
      * must be non-zero and already reflect clipping to the src bounds.
      */
-    bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+    bool getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                           int readWidth, int readHeight, size_t rowBytes,
                            GrPixelConfig readConfig, DrawPreference*, ReadPixelTempDrawInfo*);
 
     /** Info struct returned by getWritePixelsInfo about performing an intermediate draw in order
@@ -237,7 +237,7 @@
      * that would allow a successful transfer of the src pixels to the dst. The passed width,
      * height, and rowBytes, must be non-zero and already reflect clipping to the dst bounds.
      */
-    bool getWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+    bool getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width, int height,
                             GrPixelConfig srcConfig, DrawPreference*, WritePixelTempDrawInfo*);
 
     /**
@@ -259,7 +259,7 @@
      *              because of a unsupported pixel config or because no render
      *              target is currently set.
      */
-    bool readPixels(GrSurface* surface,
+    bool readPixels(GrSurface* surface, GrSurfaceOrigin,
                     int left, int top, int width, int height,
                     GrPixelConfig config, void* buffer, size_t rowBytes);
 
@@ -275,7 +275,7 @@
      * @param texels        array of mipmap levels containing texture data
      * @param mipLevelCount number of levels in 'texels'
      */
-    bool writePixels(GrSurface* surface,
+    bool writePixels(GrSurface* surface, GrSurfaceOrigin origin,
                      int left, int top, int width, int height,
                      GrPixelConfig config,
                      const GrMipLevel texels[], int mipLevelCount);
@@ -288,7 +288,7 @@
      * @param rowBytes number of bytes between consecutive rows. Zero
      *                 means rows are tightly packed.
      */
-    bool writePixels(GrSurface* surface,
+    bool writePixels(GrSurface* surface, GrSurfaceOrigin origin,
                      int left, int top, int width, int height,
                      GrPixelConfig config, const void* buffer,
                      size_t rowBytes);
@@ -334,8 +334,8 @@
     // take place at the GrOpList level and this function implement faster copy paths. The rect
     // and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the
     // src/dst bounds and non-empty.
-    bool copySurface(GrSurface* dst,
-                     GrSurface* src,
+    bool copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                     GrSurface* src, GrSurfaceOrigin srcOrigin,
                      const SkIRect& srcRect,
                      const SkIPoint& dstPoint);
 
@@ -554,18 +554,13 @@
                                              const GrMipLevel texels[],
                                              int mipLevelCount) = 0;
 
-    virtual sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
-                                                  GrSurfaceOrigin,
-                                                  GrWrapOwnership) = 0;
+    virtual sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) = 0;
     virtual sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
-                                                            GrSurfaceOrigin,
                                                             int sampleCnt,
                                                             GrWrapOwnership) = 0;
-    virtual sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
-                                                            GrSurfaceOrigin) = 0;
+    virtual sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) = 0;
     virtual sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                                     GrSurfaceOrigin,
-                                                                     int sampleCnt)=0;
+                                                                     int sampleCnt) = 0;
     virtual GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
                                      const void* data) = 0;
 
@@ -580,15 +575,17 @@
         return false;
     }
 
-    virtual bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight,
+    virtual bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                                     int readWidth, int readHeight,
                                      size_t rowBytes, GrPixelConfig readConfig, DrawPreference*,
                                      ReadPixelTempDrawInfo*) = 0;
-    virtual bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+    virtual bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                                      int width, int height,
                                       GrPixelConfig srcConfig, DrawPreference*,
                                       WritePixelTempDrawInfo*) = 0;
 
     // overridden by backend-specific derived class to perform the surface read
-    virtual bool onReadPixels(GrSurface*,
+    virtual bool onReadPixels(GrSurface*, GrSurfaceOrigin,
                               int left, int top,
                               int width, int height,
                               GrPixelConfig,
@@ -596,7 +593,7 @@
                               size_t rowBytes) = 0;
 
     // overridden by backend-specific derived class to perform the surface write
-    virtual bool onWritePixels(GrSurface*,
+    virtual bool onWritePixels(GrSurface*, GrSurfaceOrigin,
                                int left, int top, int width, int height,
                                GrPixelConfig config,
                                const GrMipLevel texels[], int mipLevelCount) = 0;
@@ -608,16 +605,16 @@
                                   size_t offset, size_t rowBytes) = 0;
 
     // overridden by backend-specific derived class to perform the resolve
-    virtual void onResolveRenderTarget(GrRenderTarget* target) = 0;
+    virtual void onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin) = 0;
 
     // overridden by backend specific derived class to perform the copy surface
-    virtual bool onCopySurface(GrSurface* dst,
-                               GrSurface* src,
-                               const SkIRect& srcRect,
-                               const SkIPoint& dstPoint) = 0;
+    virtual bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                               GrSurface* src, GrSurfaceOrigin srcOrigin,
+                               const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
 
     // overridden by backend specific derived class to perform the multisample queries
-    virtual void onQueryMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&,
+    virtual void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin rtOrigin,
+                                         const GrStencilSettings&,
                                          int* effectiveSampleCnt, SamplePattern*) = 0;
 
     virtual void onFinishFlush(bool insertedSemaphores) = 0;
diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h
index a80f6e4..2ac5e14 100644
--- a/src/gpu/GrGpuCommandBuffer.h
+++ b/src/gpu/GrGpuCommandBuffer.h
@@ -30,7 +30,8 @@
 
     // Copy src into current surface owned by either a GrGpuTextureCommandBuffer or
     // GrGpuRenderTargetCommandBuffer.
-    virtual void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
+    virtual void copy(GrSurface* src, GrSurfaceOrigin srcOrigin,
+                      const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
 
     virtual void insertEventMarker(const char*) = 0;
 
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index 390942a..63c586d 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -62,10 +62,10 @@
         GrSurface* surface = proxy->priv().peekSurface();
         GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
         GrGpu::WritePixelTempDrawInfo tempInfo;
-        fGpu->getWritePixelsInfo(surface, width, height, proxy->config(),
+        fGpu->getWritePixelsInfo(surface, proxy->origin(), width, height, proxy->config(),
                                  &drawPreference, &tempInfo);
         if (GrGpu::kNoDraw_DrawPreference == drawPreference) {
-            return this->fGpu->writePixels(surface, left, top, width, height,
+            return this->fGpu->writePixels(surface, proxy->origin(), left, top, width, height,
                                            config, buffer, rowBytes);
         }
         GrSurfaceDesc desc;
@@ -78,11 +78,11 @@
         if (!temp) {
             return false;
         }
-        if (!fGpu->writePixels(temp.get(), 0, 0, width, height, desc.fConfig,
+        if (!fGpu->writePixels(temp.get(), proxy->origin(), 0, 0, width, height, desc.fConfig,
                                buffer, rowBytes)) {
             return false;
         }
-        return fGpu->copySurface(surface, temp.get(),
+        return fGpu->copySurface(surface, proxy->origin(), temp.get(), proxy->origin(),
                                  SkIRect::MakeWH(width, height), {left, top});
     };
     upload(wp);
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index d07dd08..52cb709 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -20,6 +20,7 @@
 GrPipeline::GrPipeline(const InitArgs& args, GrProcessorSet&& processors,
                        GrAppliedClip&& appliedClip) {
     SkASSERT(args.fProxy);
+    SkASSERT(kDefault_GrSurfaceOrigin != args.fProxy->origin());
     SkASSERT(processors.isFinalized());
 
     fProxy.reset(args.fProxy);
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 6dcc149..9f3c8cd 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -98,6 +98,8 @@
 
 sk_sp<GrTexture> GrResourceProvider::getExactScratch(const GrSurfaceDesc& desc,
                                                      SkBudgeted budgeted, uint32_t flags) {
+    SkASSERT(desc.fOrigin != kDefault_GrSurfaceOrigin);
+
     flags |= kExact_Flag | kNoCreate_Flag;
     sk_sp<GrTexture> tex(this->refScratchTexture(desc, flags));
     if (tex && SkBudgeted::kNo == budgeted) {
@@ -159,6 +161,7 @@
 sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                                    uint32_t flags) {
     ASSERT_SINGLE_OWNER
+    SkASSERT(desc.fOrigin != kDefault_GrSurfaceOrigin);
 
     if (this->isAbandoned()) {
         return nullptr;
@@ -180,6 +183,7 @@
                                                          uint32_t flags) {
     ASSERT_SINGLE_OWNER
     SkASSERT(0 == flags || kNoPendingIO_Flag == flags);
+    SkASSERT(kDefault_GrSurfaceOrigin != desc.fOrigin);
 
     if (this->isAbandoned()) {
         return nullptr;
@@ -197,6 +201,7 @@
     ASSERT_SINGLE_OWNER
     SkASSERT(!this->isAbandoned());
     SkASSERT(validate_desc(inDesc, *fCaps));
+    SkASSERT(inDesc.fOrigin != kDefault_GrSurfaceOrigin);
 
     SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
 
@@ -238,31 +243,29 @@
 }
 
 sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
-                                                        GrSurfaceOrigin origin,
                                                         GrWrapOwnership ownership) {
     ASSERT_SINGLE_OWNER
     if (this->isAbandoned()) {
         return nullptr;
     }
-    return fGpu->wrapBackendTexture(tex, origin, ownership);
+    return fGpu->wrapBackendTexture(tex, ownership);
 }
 
 sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
-                                                                  GrSurfaceOrigin origin,
                                                                   int sampleCnt,
                                                                   GrWrapOwnership ownership) {
     ASSERT_SINGLE_OWNER
     if (this->isAbandoned()) {
         return nullptr;
     }
-    return fGpu->wrapRenderableBackendTexture(tex, origin, sampleCnt, ownership);
+    return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership);
 }
 
 sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
-        const GrBackendRenderTarget& backendRT, GrSurfaceOrigin origin)
+        const GrBackendRenderTarget& backendRT)
 {
     ASSERT_SINGLE_OWNER
-    return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT, origin);
+    return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
 }
 
 void GrResourceProvider::assignUniqueKeyToResource(const GrUniqueKey& key,
@@ -476,12 +479,12 @@
 }
 
 sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendTextureAsRenderTarget(
-        const GrBackendTexture& tex, GrSurfaceOrigin origin, int sampleCnt)
+        const GrBackendTexture& tex, int sampleCnt)
 {
     if (this->isAbandoned()) {
         return nullptr;
     }
-    return this->gpu()->wrapBackendTextureAsRenderTarget(tex, origin, sampleCnt);
+    return this->gpu()->wrapBackendTextureAsRenderTarget(tex, sampleCnt);
 }
 
 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool isOwned) {
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 9616d75..1ab1ec4 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -87,7 +87,6 @@
      * @return GrTexture object or NULL on failure.
      */
     sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture& tex,
-                                        GrSurfaceOrigin origin,
                                         GrWrapOwnership = kBorrow_GrWrapOwnership);
 
     /**
@@ -96,7 +95,6 @@
      * to the texture.
      */
     sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture& tex,
-                                                  GrSurfaceOrigin origin,
                                                   int sampleCnt,
                                                   GrWrapOwnership = kBorrow_GrWrapOwnership);
 
@@ -109,7 +107,7 @@
      *
      * @return GrRenderTarget object or NULL on failure.
      */
-    sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin);
+    sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&);
 
     static const uint32_t kMinScratchTextureSize;
 
@@ -214,7 +212,6 @@
       * @return GrRenderTarget object or NULL on failure.
       */
      sk_sp<GrRenderTarget> wrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                            GrSurfaceOrigin origin,
                                                             int sampleCnt);
 
     /**
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 6a55270..739fa6c 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -34,7 +34,6 @@
         , fGpuMemorySize(kInvalidGpuMemorySize)
         , fLastOpList(nullptr) {
     SkASSERT(kDefault_GrSurfaceOrigin != fOrigin);
-    SkASSERT(fTarget->origin() == fOrigin);
 }
 
 GrSurfaceProxy::~GrSurfaceProxy() {
@@ -65,6 +64,8 @@
                                                 int sampleCnt, bool needsStencil,
                                                 GrSurfaceFlags flags, bool isMipMapped,
                                                 SkDestinationSurfaceColorMode mipColorMode) const {
+    SkASSERT(kDefault_GrSurfaceOrigin != fOrigin);
+
     GrSurfaceDesc desc;
     desc.fFlags = flags;
     if (fNeedsClear) {
@@ -146,8 +147,7 @@
         height = SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(height));
     }
 
-    GrTexturePriv::ComputeScratchKey(this->config(), width, height,
-                                     this->origin(), SkToBool(rtp), sampleCount,
+    GrTexturePriv::ComputeScratchKey(this->config(), width, height, SkToBool(rtp), sampleCount,
                                      hasMipMaps, key);
 }
 
@@ -207,6 +207,7 @@
                                                    SkBudgeted budgeted,
                                                    uint32_t flags) {
     SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
+    SkASSERT(kDefault_GrSurfaceOrigin != desc.fOrigin);
 
     const GrCaps* caps = resourceProvider->caps();
 
@@ -301,7 +302,8 @@
 sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
                                                          GrBackendTexture& backendTex,
                                                          GrSurfaceOrigin origin) {
-    sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(backendTex, origin));
+    SkASSERT(kDefault_GrSurfaceOrigin != origin);
+    sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(backendTex));
     return GrSurfaceProxy::MakeWrapped(std::move(tex), origin);
 }
 
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 4f4e5aa..8e79a69 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -40,24 +40,6 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
-
-namespace {
-
-// FIXME:  This should be refactored with the code in gl/GrGLGpu.cpp.
-GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) {
-    // By default, GrRenderTargets are GL's normal orientation so that they
-    // can be drawn to by the outside world without the client having
-    // to render upside down.
-    bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrSurfaceFlag);
-    if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
-        return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
-    } else {
-        return desc.fOrigin;
-    }
-}
-}
-
-//////////////////////////////////////////////////////////////////////////////
 GrTexture::GrTexture(GrGpu* gpu, const GrSurfaceDesc& desc, GrSLType samplerType,
                      GrSamplerParams::FilterMode highestFilterMode, bool wasMipMapDataProvided)
     : INHERITED(gpu, desc)
@@ -81,12 +63,12 @@
         sampleCount = rt->numStencilSamples();
     }
     GrTexturePriv::ComputeScratchKey(this->config(), this->width(), this->height(),
-                                     this->origin(), SkToBool(rt), sampleCount,
+                                     SkToBool(rt), sampleCount,
                                      this->texturePriv().hasMipMaps(), key);
 }
 
 void GrTexturePriv::ComputeScratchKey(GrPixelConfig config, int width, int height,
-                                      GrSurfaceOrigin origin, bool isRenderTarget, int sampleCnt,
+                                      bool isRenderTarget, int sampleCnt,
                                       bool isMipMapped, GrScratchKey* key) {
     static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType();
     uint32_t flags = isRenderTarget;
@@ -98,17 +80,18 @@
     SkASSERT(static_cast<int>(config) < (1 << 5));
     SkASSERT(sampleCnt < (1 << 8));
     SkASSERT(flags < (1 << 10));
-    SkASSERT(static_cast<int>(origin) < (1 << 8));
 
     GrScratchKey::Builder builder(key, kType, 3);
     builder[0] = width;
     builder[1] = height;
-    builder[2] = config | (isMipMapped << 5) | (sampleCnt << 6) | (flags << 14) | (origin << 24);
+    builder[2] = config | (isMipMapped << 5) | (sampleCnt << 6) | (flags << 14);
 }
 
 void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* key) {
-    GrSurfaceOrigin origin = resolve_origin(desc);
-    return ComputeScratchKey(desc.fConfig, desc.fWidth, desc.fHeight, origin,
+    SkASSERT(kDefault_GrSurfaceOrigin != desc.fOrigin);
+
+    // Note: the fOrigin field is not used in the scratch key
+    return ComputeScratchKey(desc.fConfig, desc.fWidth, desc.fHeight,
                              SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag), desc.fSampleCnt,
                              desc.fIsMipMapped, key);
 }
diff --git a/src/gpu/GrTexturePriv.h b/src/gpu/GrTexturePriv.h
index 8a256a4..86f945b 100644
--- a/src/gpu/GrTexturePriv.h
+++ b/src/gpu/GrTexturePriv.h
@@ -57,7 +57,7 @@
 
     static void ComputeScratchKey(const GrSurfaceDesc&, GrScratchKey*);
     static void ComputeScratchKey(GrPixelConfig config, int width, int height,
-                                  GrSurfaceOrigin origin, bool isRenderTarget, int sampleCnt,
+                                  bool isRenderTarget, int sampleCnt,
                                   bool isMipMapped, GrScratchKey* key);
 
 
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 0471e08..2445fb8 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -530,7 +530,6 @@
 }
 
 sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
-                                               GrSurfaceOrigin origin,
                                                GrWrapOwnership ownership) {
     GrGLTexture::IDDesc idDesc;
     if (!check_backend_texture(backendTex, this->glCaps(), &idDesc)) {
@@ -544,24 +543,16 @@
 
     GrSurfaceDesc surfDesc;
     surfDesc.fFlags = kNone_GrSurfaceFlags;
+    surfDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // This isn't used in the following
     surfDesc.fWidth = backendTex.width();
     surfDesc.fHeight = backendTex.height();
     surfDesc.fConfig = backendTex.config();
     surfDesc.fSampleCnt = 0;
-    // FIXME:  this should be calling resolve_origin(), but Chrome code is currently
-    // assuming the old behaviour, which is that backend textures are always
-    // BottomLeft, even for non-RT's.  Once Chrome is fixed, change this to:
-    // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
-    if (kDefault_GrSurfaceOrigin == origin) {
-        surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-    } else {
-        surfDesc.fOrigin = origin;
-    }
+
     return GrGLTexture::MakeWrapped(this, surfDesc, idDesc);
 }
 
 sk_sp<GrTexture> GrGLGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
-                                                         GrSurfaceOrigin origin,
                                                          int sampleCnt,
                                                          GrWrapOwnership ownership) {
     GrGLTexture::IDDesc idDesc;
@@ -582,19 +573,11 @@
 
     GrSurfaceDesc surfDesc;
     surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+    surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; // This isn't actually used in the following
     surfDesc.fWidth = backendTex.width();
     surfDesc.fHeight = backendTex.height();
     surfDesc.fConfig = backendTex.config();
     surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config());
-    // FIXME:  this should be calling resolve_origin(), but Chrome code is currently
-    // assuming the old behaviour, which is that backend textures are always
-    // BottomLeft, even for non-RT's.  Once Chrome is fixed, change this to:
-    // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
-    if (kDefault_GrSurfaceOrigin == origin) {
-        surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-    } else {
-        surfDesc.fOrigin = origin;
-    }
 
     GrGLRenderTarget::IDDesc rtIDDesc;
     if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
@@ -606,8 +589,7 @@
     return std::move(texRT);
 }
 
-sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT,
-                                                         GrSurfaceOrigin origin) {
+sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
     const GrGLFramebufferInfo* info = backendRT.getGLFramebufferInfo();
     if (!info) {
         return nullptr;
@@ -621,19 +603,17 @@
     idDesc.fIsMixedSampled = false;
 
     GrSurfaceDesc desc;
-    desc.fConfig = backendRT.config();
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
+    desc.fOrigin = kBottomLeft_GrSurfaceOrigin; // This isn't actually used in the following
     desc.fWidth = backendRT.width();
     desc.fHeight = backendRT.height();
+    desc.fConfig = backendRT.config();
     desc.fSampleCnt = this->caps()->getSampleCount(backendRT.sampleCnt(), backendRT.config());
-    SkASSERT(kDefault_GrSurfaceOrigin != origin);
-    desc.fOrigin = origin;
 
     return GrGLRenderTarget::MakeWrapped(this, desc, idDesc, backendRT.stencilBits());
 }
 
 sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
-                                                                  GrSurfaceOrigin origin,
                                                                   int sampleCnt) {
     const GrGLTextureInfo* info = tex.getGLTextureInfo();
     if (!info || !info->fID) {
@@ -653,19 +633,11 @@
 
     GrSurfaceDesc surfDesc;
     surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+    surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; // This isn't actually used in the following
     surfDesc.fWidth = tex.width();
     surfDesc.fHeight = tex.height();
     surfDesc.fConfig = tex.config();
     surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config());
-    // FIXME:  this should be calling resolve_origin(), but Chrome code is currently
-    // assuming the old behaviour, which is that backend textures are always
-    // BottomLeft, even for non-RT's.  Once Chrome is fixed, change this to:
-    // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
-    if (kDefault_GrSurfaceOrigin == origin) {
-        surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-    } else {
-        surfDesc.fOrigin = origin;
-    }
 
     GrGLRenderTarget::IDDesc rtIDDesc;
     if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
@@ -676,7 +648,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                                   int width, int height,
                                    GrPixelConfig srcConfig,
                                    DrawPreference* drawPreference,
                                    WritePixelTempDrawInfo* tempDrawInfo) {
@@ -751,8 +724,7 @@
         }
     }
 
-    if (!this->glCaps().unpackFlipYSupport() &&
-        kBottomLeft_GrSurfaceOrigin == dstSurface->origin()) {
+    if (!this->glCaps().unpackFlipYSupport() && kBottomLeft_GrSurfaceOrigin == dstOrigin) {
         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
     }
 
@@ -778,7 +750,7 @@
     return true;
 }
 
-bool GrGLGpu::onWritePixels(GrSurface* surface,
+bool GrGLGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin,
                             int left, int top, int width, int height,
                             GrPixelConfig config,
                             const GrMipLevel texels[],
@@ -793,7 +765,7 @@
     GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
 
     return this->uploadTexData(glTex->config(), glTex->width(), glTex->height(),
-                               glTex->origin(), glTex->target(), kWrite_UploadType,
+                               origin, glTex->target(), kWrite_UploadType,
                                left, top, width, height, config, texels, mipLevelCount);
 }
 
@@ -1742,14 +1714,14 @@
 }
 
 void GrGLGpu::flushWindowRectangles(const GrWindowRectsState& windowState,
-                                    const GrGLRenderTarget* rt) {
+                                    const GrGLRenderTarget* rt, GrSurfaceOrigin origin) {
 #ifndef USE_NSIGHT
     typedef GrWindowRectsState::Mode Mode;
     SkASSERT(!windowState.enabled() || rt->renderFBOID()); // Window rects can't be used on-screen.
     SkASSERT(windowState.numWindows() <= this->caps()->maxWindowRectangles());
 
     if (!this->caps()->maxWindowRectangles() ||
-        fHWWindowRectsState.knownEqualTo(rt->origin(), rt->getViewport(), windowState)) {
+        fHWWindowRectsState.knownEqualTo(origin, rt->getViewport(), windowState)) {
         return;
     }
 
@@ -1761,13 +1733,13 @@
     GrGLIRect glwindows[GrWindowRectangles::kMaxWindows];
     const SkIRect* skwindows = windowState.windows().data();
     for (int i = 0; i < numWindows; ++i) {
-        glwindows[i].setRelativeTo(rt->getViewport(), skwindows[i], rt->origin());
+        glwindows[i].setRelativeTo(rt->getViewport(), skwindows[i], origin);
     }
 
     GrGLenum glmode = (Mode::kExclusive == windowState.mode()) ? GR_GL_EXCLUSIVE : GR_GL_INCLUSIVE;
     GL_CALL(WindowRectangles(glmode, numWindows, glwindows->asInts()));
 
-    fHWWindowRectsState.set(rt->origin(), rt->getViewport(), windowState);
+    fHWWindowRectsState.set(origin, rt->getViewport(), windowState);
 #endif
 }
 
@@ -1835,7 +1807,7 @@
     }
     this->flushStencil(stencil);
     this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), pipeline.proxy()->origin());
-    this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT);
+    this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT, pipeline.proxy()->origin());
     this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !stencil.isDisabled());
 
     // This must come after textures are flushed because a texture may need
@@ -1961,7 +1933,7 @@
 
     this->flushRenderTarget(glRT, clip.scissorEnabled() ? &clip.scissorRect() : nullptr);
     this->flushScissor(clip.scissorState(), glRT->getViewport(), origin);
-    this->flushWindowRectangles(clip.windowRectsState(), glRT);
+    this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
 
     GrGLfloat r, g, b, a;
     static const GrGLfloat scale255 = 1.f / 255.f;
@@ -2007,7 +1979,7 @@
     this->handleDirtyContext();
 
     if (this->glCaps().useDrawToClearStencilClip()) {
-        this->clearStencilClipAsDraw(clip, insideStencilMask, target);
+        this->clearStencilClipAsDraw(clip, insideStencilMask, target, origin);
         return;
     }
 
@@ -2037,7 +2009,7 @@
     this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
 
     this->flushScissor(clip.scissorState(), glRT->getViewport(), origin);
-    this->flushWindowRectangles(clip.windowRectsState(), glRT);
+    this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
 
     GL_CALL(StencilMask((uint32_t) clipStencilMask));
     GL_CALL(ClearStencil(value));
@@ -2152,7 +2124,8 @@
     return false;
 }
 
-bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
+bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                                  int width, int height, size_t rowBytes,
                                   GrPixelConfig readConfig, DrawPreference* drawPreference,
                                   ReadPixelTempDrawInfo* tempDrawInfo) {
     GrPixelConfig srcConfig = srcSurface->config();
@@ -2257,7 +2230,7 @@
     }
 
     if ((srcSurface->asRenderTarget() || this->glCaps().canConfigBeFBOColorAttachment(srcConfig)) &&
-        read_pixels_pays_for_y_flip(srcSurface->origin(), this->glCaps(), width, height, readConfig,
+        read_pixels_pays_for_y_flip(srcOrigin, this->glCaps(), width, height, readConfig,
                                     rowBytes)) {
         ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
     }
@@ -2265,7 +2238,7 @@
     return true;
 }
 
-bool GrGLGpu::onReadPixels(GrSurface* surface,
+bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
                            int left, int top,
                            int width, int height,
                            GrPixelConfig config,
@@ -2294,8 +2267,8 @@
         if (kAlpha_8_GrPixelConfig == config &&
             this->readPixelsSupported(surface, tempConfig)) {
             std::unique_ptr<uint32_t[]> temp(new uint32_t[width * height * 4]);
-            if (this->onReadPixels(surface, left, top, width, height, tempConfig, temp.get(),
-                                   width*4)) {
+            if (this->onReadPixels(surface, origin, left, top, width, height,
+                                   tempConfig, temp.get(), width*4)) {
                 uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
                 for (int j = 0; j < height; ++j) {
                     for (int i = 0; i < width; ++i) {
@@ -2314,7 +2287,7 @@
                                             &externalType)) {
         return false;
     }
-    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
+    bool flipY = kBottomLeft_GrSurfaceOrigin == origin;
 
     GrGLIRect glvp;
     if (renderTarget) {
@@ -2326,7 +2299,7 @@
                 this->flushRenderTarget(renderTarget, &SkIRect::EmptyIRect());
                 break;
             case GrGLRenderTarget::kCanResolve_ResolveType:
-                this->onResolveRenderTarget(renderTarget);
+                this->onResolveRenderTarget(renderTarget, origin);
                 // we don't track the state of the READ FBO ID.
                 fStats.incRenderTargetBinds();
                 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID()));
@@ -2343,7 +2316,7 @@
 
     // the read rect is viewport-relative
     GrGLIRect readRect;
-    readRect.setRelativeTo(glvp, left, top, width, height, surface->origin());
+    readRect.setRelativeTo(glvp, left, top, width, height, origin);
 
     size_t bytesPerPixel = GrBytesPerPixel(config);
     size_t tightRowBytes = bytesPerPixel * width;
@@ -2644,7 +2617,7 @@
     fStats.incNumDraws();
 }
 
-void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
+void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin) {
     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
     if (rt->needsResolve()) {
         // Some extensions automatically resolves the texture when it is read.
@@ -2664,7 +2637,7 @@
                 // Apple's extension uses the scissor as the blit bounds.
                 GrScissorState scissorState;
                 scissorState.set(dirtyRect);
-                this->flushScissor(scissorState, vp, rt->origin());
+                this->flushScissor(scissorState, vp, origin);
                 this->disableWindowRectangles();
                 GL_CALL(ResolveMultisampleFramebuffer());
             } else {
@@ -2677,7 +2650,7 @@
                     t = target->height();
                 } else {
                     GrGLIRect rect;
-                    rect.setRelativeTo(vp, dirtyRect, target->origin());
+                    rect.setRelativeTo(vp, dirtyRect, origin);
                     l = rect.fLeft;
                     b = rect.fBottom;
                     r = rect.fLeft + rect.fWidth;
@@ -2930,7 +2903,7 @@
 }
 
 void GrGLGpu::bindTexture(int unitIdx, const GrSamplerParams& params, bool allowSRGBInputs,
-                          GrGLTexture* texture) {
+                          GrGLTexture* texture, GrSurfaceOrigin textureOrigin) {
     SkASSERT(texture);
 
 #ifdef SK_DEBUG
@@ -2950,7 +2923,7 @@
     // out of the "last != next" check.
     GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
     if (texRT) {
-        this->onResolveRenderTarget(texRT);
+        this->onResolveRenderTarget(texRT, textureOrigin);
     }
 
     GrGpuResource::UniqueID textureID = texture->uniqueID();
@@ -3118,7 +3091,7 @@
 }
 
 void GrGLGpu::generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs,
-                              GrGLTexture* texture) {
+                              GrGLTexture* texture, GrSurfaceOrigin textureOrigin) {
     SkASSERT(texture);
 
     // First, figure out if we need mips for this texture at all:
@@ -3154,7 +3127,7 @@
     // from the rt it will still be the last bound texture, but it needs resolving.
     GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
     if (texRT) {
-        this->onResolveRenderTarget(texRT);
+        this->onResolveRenderTarget(texRT, textureOrigin);
     }
 
     GrGLenum target = texture->target();
@@ -3177,7 +3150,7 @@
     }
 
     // Either do manual mipmap generation or (if that fails), just rely on the driver:
-    if (!this->generateMipmap(texture, allowSRGBInputs)) {
+    if (!this->generateMipmap(texture, textureOrigin, allowSRGBInputs)) {
         GL_CALL(GenerateMipmap(target));
     }
 
@@ -3241,11 +3214,12 @@
 }
 
 // Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface.
-static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst,
-                                                         const GrSurface* src,
-                                                         const SkIRect& srcRect,
-                                                         const SkIPoint& dstPoint,
-                                                         const GrGLGpu* gpu) {
+static inline bool can_blit_framebuffer_for_copy_surface(
+                                                const GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                                const GrSurface* src, GrSurfaceOrigin srcOrigin,
+                                                const SkIRect& srcRect,
+                                                const SkIPoint& dstPoint,
+                                                const GrGLGpu* gpu) {
     auto blitFramebufferFlags = gpu->glCaps().blitFramebufferSupportFlags();
     if (!gpu->glCaps().canConfigBeFBOColorAttachment(dst->config()) ||
         !gpu->glCaps().canConfigBeFBOColorAttachment(src->config())) {
@@ -3270,7 +3244,7 @@
     if (GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag & blitFramebufferFlags) {
         // We would mirror to compensate for origin changes. Note that copySurface is
         // specified such that the src and dst rects are the same.
-        if (dst->origin() != src->origin()) {
+        if (dstOrigin != srcOrigin) {
             return false;
         }
     }
@@ -3304,7 +3278,7 @@
             if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) {
                 return false;
             }
-            if (dst->origin() != src->origin()) {
+            if (dstOrigin != srcOrigin) {
                 return false;
             }
         }
@@ -3312,8 +3286,8 @@
     return true;
 }
 
-static inline bool can_copy_texsubimage(const GrSurface* dst,
-                                        const GrSurface* src,
+static inline bool can_copy_texsubimage(const GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                        const GrSurface* src, GrSurfaceOrigin srcOrigin,
                                         const GrGLGpu* gpu) {
     // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage
     // and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
@@ -3348,7 +3322,7 @@
     // is required.
     if (gpu->glCaps().canConfigBeFBOColorAttachment(src->config()) &&
         (!srcTex || srcTex->target() == GR_GL_TEXTURE_2D) && dstTex->target() == GR_GL_TEXTURE_2D &&
-        dst->origin() == src->origin()) {
+        dstOrigin == srcOrigin) {
         return true;
     } else {
         return false;
@@ -3404,10 +3378,9 @@
     }
 }
 
-bool GrGLGpu::onCopySurface(GrSurface* dst,
-                            GrSurface* src,
-                            const SkIRect& srcRect,
-                            const SkIPoint& dstPoint) {
+bool GrGLGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                            GrSurface* src, GrSurfaceOrigin srcOrigin,
+                            const SkIRect& srcRect, const SkIPoint& dstPoint) {
     // None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the
     // swizzle.
     if (this->caps()->shaderCaps()->configOutputSwizzle(src->config()) !=
@@ -3417,22 +3390,24 @@
     // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
     bool preferCopy = SkToBool(dst->asRenderTarget());
     if (preferCopy && src->asTexture()) {
-        if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
+        if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
             return true;
         }
     }
 
-    if (can_copy_texsubimage(dst, src, this)) {
-        this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint);
+    if (can_copy_texsubimage(dst, dstOrigin, src, srcOrigin, this)) {
+        this->copySurfaceAsCopyTexSubImage(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
         return true;
     }
 
-    if (can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this)) {
-        return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint);
+    if (can_blit_framebuffer_for_copy_surface(dst, dstOrigin, src, srcOrigin,
+                                              srcRect, dstPoint, this)) {
+        return this->copySurfaceAsBlitFramebuffer(dst, dstOrigin, src, srcOrigin,
+                                                  srcRect, dstPoint);
     }
 
     if (!preferCopy && src->asTexture()) {
-        if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
+        if (this->copySurfaceAsDraw(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
             return true;
         }
     }
@@ -3790,7 +3765,7 @@
 }
 
 void GrGLGpu::clearStencilClipAsDraw(const GrFixedClip& clip, bool insideStencilMask,
-                                     GrRenderTarget* rt) {
+                                     GrRenderTarget* rt, GrSurfaceOrigin origin) {
     // TODO: This should swizzle the output to match dst's config, though it is a debugging
     // visualization.
 
@@ -3820,8 +3795,8 @@
     this->flushBlend(blendInfo, GrSwizzle::RGBA());
     this->flushColorWrite(false);
     this->flushHWAAState(glRT, false, false);
-    this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin());
-    this->flushWindowRectangles(clip.windowRectsState(), glRT);
+    this->flushScissor(clip.scissorState(), glRT->getViewport(), origin);
+    this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
     GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment();
     // This should only be called internally when we know we have a stencil buffer.
     SkASSERT(sb);
@@ -3832,8 +3807,8 @@
 }
 
 
-bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
-                                GrSurface* src,
+bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                GrSurface* src, GrSurfaceOrigin srcOrigin,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint) {
     GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
@@ -3850,7 +3825,7 @@
     int h = srcRect.height();
 
     GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
-    this->bindTexture(0, params, true, srcTex);
+    this->bindTexture(0, params, true, srcTex, srcOrigin);
 
     GrGLIRect dstVP;
     this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);
@@ -3876,7 +3851,7 @@
     GrGLfloat dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
     GrGLfloat dy0 = 2.f * dstPoint.fY / dh - 1.f;
     GrGLfloat dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
-    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
         dy0 = -dy0;
         dy1 = -dy1;
     }
@@ -3887,7 +3862,7 @@
     GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h);
     int sw = src->width();
     int sh = src->height();
-    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
         sy0 = sh - sy0;
         sy1 = sh - sy1;
     }
@@ -3921,11 +3896,11 @@
     return true;
 }
 
-void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst,
-                                           GrSurface* src,
+void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                           GrSurface* src, GrSurfaceOrigin srcOrigin,
                                            const SkIRect& srcRect,
                                            const SkIPoint& dstPoint) {
-    SkASSERT(can_copy_texsubimage(dst, src, this));
+    SkASSERT(can_copy_texsubimage(dst, dstOrigin, src, srcOrigin, this));
     GrGLIRect srcVP;
     this->bindSurfaceFBOForPixelOps(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
     GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture());
@@ -3933,12 +3908,12 @@
     // We modified the bound FBO
     fHWBoundRenderTargetUniqueID.makeInvalid();
     GrGLIRect srcGLRect;
-    srcGLRect.setRelativeTo(srcVP, srcRect, src->origin());
+    srcGLRect.setRelativeTo(srcVP, srcRect, srcOrigin);
 
     this->setScratchTextureUnit();
     GL_CALL(BindTexture(dstTex->target(), dstTex->textureID()));
     GrGLint dstY;
-    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
         dstY = dst->height() - (dstPoint.fY + srcGLRect.fHeight);
     } else {
         dstY = dstPoint.fY;
@@ -3953,11 +3928,12 @@
     this->didWriteToSurface(dst, &dstRect);
 }
 
-bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
-                                           GrSurface* src,
+bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                           GrSurface* src, GrSurfaceOrigin srcOrigin,
                                            const SkIRect& srcRect,
                                            const SkIPoint& dstPoint) {
-    SkASSERT(can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this));
+    SkASSERT(can_blit_framebuffer_for_copy_surface(dst, dstOrigin, src, srcOrigin,
+                                                   srcRect, dstPoint, this));
     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
                                         srcRect.width(), srcRect.height());
     if (dst == src) {
@@ -3974,8 +3950,8 @@
     fHWBoundRenderTargetUniqueID.makeInvalid();
     GrGLIRect srcGLRect;
     GrGLIRect dstGLRect;
-    srcGLRect.setRelativeTo(srcVP, srcRect, src->origin());
-    dstGLRect.setRelativeTo(dstVP, dstRect, dst->origin());
+    srcGLRect.setRelativeTo(srcVP, srcRect, srcOrigin);
+    dstGLRect.setRelativeTo(dstVP, dstRect, dstOrigin);
 
     // BlitFrameBuffer respects the scissor, so disable it.
     this->disableScissor();
@@ -3984,7 +3960,7 @@
     GrGLint srcY0;
     GrGLint srcY1;
     // Does the blit need to y-mirror or not?
-    if (src->origin() == dst->origin()) {
+    if (srcOrigin == dstOrigin) {
         srcY0 = srcGLRect.fBottom;
         srcY1 = srcGLRect.fBottom + srcGLRect.fHeight;
     } else {
@@ -4009,7 +3985,8 @@
 // Manual implementation of mipmap generation, to work around driver bugs w/sRGB.
 // Uses draw calls to do a series of downsample operations to successive mips.
 // If this returns false, then the calling code falls back to using glGenerateMipmap.
-bool GrGLGpu::generateMipmap(GrGLTexture* texture, bool gammaCorrect) {
+bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin,
+                             bool gammaCorrect) {
     SkASSERT(!GrPixelConfigIsSint(texture->config()));
     // Our iterative downsample requires the ability to limit which level we're sampling:
     if (!this->glCaps().doManualMipmapping()) {
@@ -4072,7 +4049,7 @@
     // We'll be changing our base level further below:
     this->setTextureUnit(0);
     GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBilerp_FilterMode);
-    this->bindTexture(0, params, gammaCorrect, texture);
+    this->bindTexture(0, params, gammaCorrect, texture, textureOrigin);
 
     // Vertex data:
     if (!fMipmapProgramArrayBuffer) {
@@ -4154,7 +4131,8 @@
     return true;
 }
 
-void GrGLGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings& stencil,
+void GrGLGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin rtOrigin,
+                                      const GrStencilSettings& stencil,
                                       int* effectiveSampleCnt, SamplePattern* samplePattern) {
     SkASSERT(GrFSAAType::kMixedSamples != rt->fsaaType() ||
              rt->renderTargetPriv().getStencilAttachment() || stencil.isDisabled());
@@ -4176,7 +4154,7 @@
         for (int i = 0; i < *effectiveSampleCnt; ++i) {
             GrGLfloat pos[2];
             GL_CALL(GetMultisamplefv(GR_GL_SAMPLE_POSITION, i, pos));
-            if (kTopLeft_GrSurfaceOrigin == rt->origin()) {
+            if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
                 (*samplePattern)[i].set(pos[0], pos[1]);
             } else {
                 (*samplePattern)[i].set(pos[0], 1 - pos[1]);
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 23709b4..6f2e5d3 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -60,19 +60,22 @@
 
     // Used by GrGLProgram to configure OpenGL state.
     void bindTexture(int unitIdx, const GrSamplerParams& params, bool allowSRGBInputs,
-                     GrGLTexture* texture);
+                     GrGLTexture* texture, GrSurfaceOrigin textureOrigin);
 
     void bindTexelBuffer(int unitIdx, GrPixelConfig, GrGLBuffer*);
 
     void bindImageStorage(int unitIdx, GrIOType, GrGLTexture *);
 
-    void generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs, GrGLTexture* texture);
+    void generateMipmaps(const GrSamplerParams& params, bool allowSRGBInputs,
+                         GrGLTexture* texture, GrSurfaceOrigin textureOrigin);
 
-    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+    bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                             int readWidth, int readHeight, size_t rowBytes,
                              GrPixelConfig readConfig, DrawPreference*,
                              ReadPixelTempDrawInfo*) override;
 
-    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+    bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                              int width, int height,
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override;
 
@@ -199,17 +202,12 @@
     GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
                              const void* data) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
-                                          GrSurfaceOrigin,
-                                          GrWrapOwnership) override;
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override;
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
-                                                    GrSurfaceOrigin,
                                                     int sampleCnt,
                                                     GrWrapOwnership) override;
-    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
-                                                    GrSurfaceOrigin origin) override;
+    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override;
     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                             GrSurfaceOrigin,
                                                              int sampleCnt) override;
 
     std::unique_ptr<gr_instanced::OpAllocator> onCreateInstancedRenderingAllocator() override;
@@ -246,14 +244,14 @@
     // variations above, depending on whether the surface is a render target or not.
     bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig);
 
-    bool onReadPixels(GrSurface*,
+    bool onReadPixels(GrSurface*, GrSurfaceOrigin,
                       int left, int top,
                       int width, int height,
                       GrPixelConfig,
                       void* buffer,
                       size_t rowBytes) override;
 
-    bool onWritePixels(GrSurface*,
+    bool onWritePixels(GrSurface*, GrSurfaceOrigin,
                        int left, int top, int width, int height,
                        GrPixelConfig config,
                        const GrMipLevel texels[], int mipLevelCount) override;
@@ -263,14 +261,13 @@
                           GrPixelConfig config, GrBuffer* transferBuffer,
                           size_t offset, size_t rowBytes) override;
 
-    void onResolveRenderTarget(GrRenderTarget* target) override;
+    void onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin) override;
 
-    bool onCopySurface(GrSurface* dst,
-                       GrSurface* src,
-                       const SkIRect& srcRect,
-                       const SkIPoint& dstPoint) override;
+    bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                       GrSurface* src, GrSurfaceOrigin srcOrigin,
+                       const SkIRect& srcRect, const SkIPoint& dstPoint) override;
 
-    void onQueryMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&,
+    void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
                                  int* effectiveSampleCnt, SamplePattern*) override;
 
     // binds texture unit in GL
@@ -296,20 +293,18 @@
 
     bool hasExtension(const char* ext) const { return fGLContext->hasExtension(ext); }
 
-    bool copySurfaceAsDraw(GrSurface* dst,
-                           GrSurface* src,
-                           const SkIRect& srcRect,
-                           const SkIPoint& dstPoint);
-    void copySurfaceAsCopyTexSubImage(GrSurface* dst,
-                                      GrSurface* src,
-                                      const SkIRect& srcRect,
-                                      const SkIPoint& dstPoint);
-    bool copySurfaceAsBlitFramebuffer(GrSurface* dst,
-                                      GrSurface* src,
-                                      const SkIRect& srcRect,
-                                      const SkIPoint& dstPoint);
-    bool generateMipmap(GrGLTexture* texture, bool gammaCorrect);
-    void clearStencilClipAsDraw(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
+    bool copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                           GrSurface* src, GrSurfaceOrigin srcOrigin,
+                           const SkIRect& srcRect, const SkIPoint& dstPoint);
+    void copySurfaceAsCopyTexSubImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                      GrSurface* src, GrSurfaceOrigin srcOrigin,
+                                      const SkIRect& srcRect, const SkIPoint& dstPoint);
+    bool copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                      GrSurface* src, GrSurfaceOrigin srcOrigin,
+                                      const SkIRect& srcRect, const SkIPoint& dstPoint);
+    bool generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin, bool gammaCorrect);
+    void clearStencilClipAsDraw(const GrFixedClip&, bool insideStencilMask,
+                                GrRenderTarget*, GrSurfaceOrigin);
 
     static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
 
@@ -360,7 +355,7 @@
     // disables the scissor
     void disableScissor();
 
-    void flushWindowRectangles(const GrWindowRectsState&, const GrGLRenderTarget*);
+    void flushWindowRectangles(const GrWindowRectsState&, const GrGLRenderTarget*, GrSurfaceOrigin);
     void disableWindowRectangles();
 
     // sets a texture unit to use for texture operations other than binding a texture to a program.
diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h
index f57935a..cfcde79 100644
--- a/src/gpu/gl/GrGLGpuCommandBuffer.h
+++ b/src/gpu/gl/GrGLGpuCommandBuffer.h
@@ -1,9 +1,9 @@
 /*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
 
 #ifndef GrGLGpuCommandBuffer_DEFINED
 #define GrGLGpuCommandBuffer_DEFINED
@@ -28,8 +28,9 @@
 
     void submit() override {}
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
-        fGpu->copySurface(fTexture, src, srcRect, dstPoint);
+    void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+              const SkIPoint& dstPoint) override {
+        fGpu->copySurface(fTexture, fOrigin, src, srcOrigin, srcRect, dstPoint);
     }
 
     void insertEventMarker(const char* msg) override {
@@ -37,7 +38,7 @@
     }
 
 private:
-    GrGLGpu*                    fGpu;
+    GrGLGpu* fGpu;
 
     typedef GrGpuTextureCommandBuffer INHERITED;
 };
@@ -81,8 +82,9 @@
         state->doUpload(upload);
     }
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {
-        fGpu->copySurface(fRenderTarget, src, srcRect, dstPoint);
+    void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+              const SkIPoint& dstPoint) override {
+        fGpu->copySurface(fRenderTarget, fOrigin, src, srcOrigin, srcRect, dstPoint);
     }
 
     void submit() override {}
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 82a8170..f7e337c 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -70,7 +70,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) {
-    this->setRenderTargetState(primProc, pipeline.renderTarget());
+    this->setRenderTargetState(primProc, pipeline.proxy());
 
     // we set the textures, and uniforms for installed processors in a generic way, but subclasses
     // of GLProgram determine how to set coord transforms
@@ -97,7 +97,8 @@
     fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
     if (dstTexture) {
         fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerParams::ClampNoFilter(), true,
-                          static_cast<GrGLTexture*>(dstTexture));
+                          static_cast<GrGLTexture*>(dstTexture),
+                          pipeline.dstTextureProxy()->origin());
     }
     SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
     SkASSERT(nextTexelBufferIdx == fNumTextureSamplers + fNumTexelBuffers);
@@ -135,7 +136,8 @@
 
 
 void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
-                                       const GrRenderTarget* rt) {
+                                       const GrRenderTargetProxy* proxy) {
+    GrRenderTarget* rt = proxy->priv().peekRenderTarget();
     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
         fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
@@ -146,10 +148,10 @@
     SkISize size;
     size.set(rt->width(), rt->height());
     if (!primProc.isPathRendering()) {
-        if (fRenderTargetState.fRenderTargetOrigin != rt->origin() ||
+        if (fRenderTargetState.fRenderTargetOrigin != proxy->origin() ||
             fRenderTargetState.fRenderTargetSize != size) {
             fRenderTargetState.fRenderTargetSize = size;
-            fRenderTargetState.fRenderTargetOrigin = rt->origin();
+            fRenderTargetState.fRenderTargetOrigin = proxy->origin();
 
             float rtAdjustmentVec[4];
             fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
@@ -159,7 +161,7 @@
         SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
         const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
         fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
-                                                     size, rt->origin());
+                                                     size, proxy->origin());
     }
 }
 
@@ -171,7 +173,8 @@
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
         fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.params(),
-                          allowSRGBInputs, static_cast<GrGLTexture*>(sampler.peekTexture()));
+                          allowSRGBInputs, static_cast<GrGLTexture*>(sampler.peekTexture()),
+                          sampler.proxy()->origin());
     }
     for (int i = 0; i < processor.numBuffers(); ++i) {
         const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(i);
@@ -189,6 +192,7 @@
     for (int i = 0; i < processor.numTextureSamplers(); ++i) {
         const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i);
         fGpu->generateMipmaps(sampler.params(), allowSRGBInputs,
-                              static_cast<GrGLTexture*>(sampler.peekTexture()));
+                              static_cast<GrGLTexture*>(sampler.peekTexture()),
+                              sampler.proxy()->origin());
     }
 }
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 3a18792..96ff10f 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -124,7 +124,7 @@
                          int* nextTexelBufferIdx, int* nextImageStorageIdx);
 
     // Helper for setData() that sets the view matrix and loads the render target height uniform
-    void setRenderTargetState(const GrPrimitiveProcessor&, const GrRenderTarget*);
+    void setRenderTargetState(const GrPrimitiveProcessor&, const GrRenderTargetProxy*);
 
     // Helper for setData() that binds textures and texel buffers to the appropriate texture units
     void bindTextures(const GrResourceIOProcessor&, bool allowSRGBInputs, int* nextSamplerIdx,
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 76f893e..5efe3b7 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -25,20 +25,21 @@
 
     ~GrMockGpu() override {}
 
-    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+    bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                             int readWidth, int readHeight, size_t rowBytes,
                              GrPixelConfig readConfig, DrawPreference*,
                              ReadPixelTempDrawInfo*) override { return true; }
 
-    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+    bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                              int width, int height,
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override { return true; }
 
-    bool onCopySurface(GrSurface* dst,
-                       GrSurface* src,
-                       const SkIRect& srcRect,
-                       const SkIPoint& dstPoint) override { return true; }
+    bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                       GrSurface* src, GrSurfaceOrigin srcOrigin,
+                       const SkIRect& srcRect, const SkIPoint& dstPoint) override { return true; }
 
-    void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
+    void onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
                                  int* effectiveSampleCnt, SamplePattern*) override {
         *effectiveSampleCnt = rt->numStencilSamples();
     }
@@ -75,26 +76,21 @@
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted,
                                      const GrMipLevel texels[], int mipLevelCount) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
-                                          GrSurfaceOrigin,
-                                          GrWrapOwnership) override {
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override {
         return nullptr;
     }
 
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
-                                                    GrSurfaceOrigin,
                                                     int sampleCnt,
                                                     GrWrapOwnership) override {
         return nullptr;
     }
 
-    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
-                                                    GrSurfaceOrigin) override {
+    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override {
         return nullptr;
     }
 
     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                             GrSurfaceOrigin,
                                                              int sampleCnt) override {
         return nullptr;
     }
@@ -104,7 +100,7 @@
 
     gr_instanced::InstancedRendering* onCreateInstancedRendering() override { return nullptr; }
 
-    bool onReadPixels(GrSurface* surface,
+    bool onReadPixels(GrSurface* surface, GrSurfaceOrigin,
                       int left, int top, int width, int height,
                       GrPixelConfig,
                       void* buffer,
@@ -112,7 +108,7 @@
         return true;
     }
 
-    bool onWritePixels(GrSurface* surface,
+    bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
                        int left, int top, int width, int height,
                        GrPixelConfig config,
                        const GrMipLevel texels[], int mipLevelCount) override {
@@ -126,7 +122,7 @@
         return true;
     }
 
-    void onResolveRenderTarget(GrRenderTarget* target) override { return; }
+    void onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin) override { return; }
 
     void onFinishFlush(bool insertedSemaphores) override {}
 
diff --git a/src/gpu/mock/GrMockGpuCommandBuffer.h b/src/gpu/mock/GrMockGpuCommandBuffer.h
index d3bf732..9c5d824 100644
--- a/src/gpu/mock/GrMockGpuCommandBuffer.h
+++ b/src/gpu/mock/GrMockGpuCommandBuffer.h
@@ -19,7 +19,8 @@
 
     ~GrMockGpuTextureCommandBuffer() override {}
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
+    void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+              const SkIPoint& dstPoint) override {}
     void insertEventMarker(const char*) override {}
 
 private:
@@ -41,7 +42,8 @@
     void insertEventMarker(const char*) override {}
     void begin() override {}
     void end() override {}
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override {}
+    void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+              const SkIPoint& dstPoint) override {}
 
     int numDraws() const { return fNumDraws; }
 
diff --git a/src/gpu/mock/GrMockTexture.h b/src/gpu/mock/GrMockTexture.h
index 3bccd41..a3bad02 100644
--- a/src/gpu/mock/GrMockTexture.h
+++ b/src/gpu/mock/GrMockTexture.h
@@ -90,7 +90,7 @@
 
     void computeScratchKey(GrScratchKey* key) const override {
         GrTexturePriv::ComputeScratchKey(this->config(), this->width(), this->height(),
-                                         this->origin(), true, this->numStencilSamples(),
+                                         true, this->numStencilSamples(),
                                          this->texturePriv().hasMipMaps(), key);
     }
 };
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index f8e3e5b..1794948 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -31,20 +31,22 @@
 
     id<MTLDevice> device() const { return fDevice; }
 
-    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+    bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin origin,
+                             int readWidth, int readHeight, size_t rowBytes,
                              GrPixelConfig readConfig, DrawPreference*,
                              ReadPixelTempDrawInfo*) override { return false; }
 
-    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+    bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                              int width, int height,
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override { return false; }
 
-    bool onCopySurface(GrSurface* dst,
-                       GrSurface* src,
+    bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                       GrSurface* src, GrSurfaceOrigin srcOrigin,
                        const SkIRect& srcRect,
                        const SkIPoint& dstPoint) override { return false; }
 
-    void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
+    void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
                                  int* effectiveSampleCnt, SamplePattern*) override {}
 
     GrGpuRTCommandBuffer* createCommandBuffer(
@@ -82,26 +84,21 @@
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                      const GrMipLevel texels[], int mipLevelCount) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
-                                          GrSurfaceOrigin,
-                                          GrWrapOwnership) override {
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override {
         return nullptr;
     }
 
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
-                                                    GrSurfaceOrigin,
                                                     int sampleCnt,
                                                     GrWrapOwnership) override {
         return nullptr;
     }
 
-    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
-                                                    GrSurfaceOrigin) override {
+    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override {
         return nullptr;
     }
 
     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                             GrSurfaceOrigin,
                                                              int sampleCnt) override {
         return nullptr;
     }
@@ -112,7 +109,7 @@
 
     gr_instanced::InstancedRendering* onCreateInstancedRendering() override { return nullptr; }
 
-    bool onReadPixels(GrSurface* surface,
+    bool onReadPixels(GrSurface* surface, GrSurfaceOrigin,
                       int left, int top, int width, int height,
                       GrPixelConfig,
                       void* buffer,
@@ -120,7 +117,7 @@
         return false;
     }
 
-    bool onWritePixels(GrSurface* surface,
+    bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
                        int left, int top, int width, int height,
                        GrPixelConfig config,
                        const GrMipLevel texels[], int mipLevelCount) override {
@@ -134,7 +131,7 @@
         return false;
     }
 
-    void onResolveRenderTarget(GrRenderTarget* target) override { return; }
+    void onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin) override { return; }
 
     void onFinishFlush(bool insertedSemaphores) override {}
 
diff --git a/src/gpu/ops/GrClearOp.cpp b/src/gpu/ops/GrClearOp.cpp
index cb9d4db..702edcc 100644
--- a/src/gpu/ops/GrClearOp.cpp
+++ b/src/gpu/ops/GrClearOp.cpp
@@ -3,14 +3,14 @@
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
- */

-

-#include "GrClearOp.h"

-

-#include "GrGpuCommandBuffer.h"

-#include "GrOpFlushState.h"

+ */
+
+#include "GrClearOp.h"
+
+#include "GrGpuCommandBuffer.h"
+#include "GrOpFlushState.h"
 #include "GrResourceProvider.h"
-

+
 GrClearOp::GrClearOp(const GrFixedClip& clip, GrColor color, GrSurfaceProxy* proxy)
         : INHERITED(ClassID())
         , fClip(clip)
diff --git a/src/gpu/ops/GrCopySurfaceOp.cpp b/src/gpu/ops/GrCopySurfaceOp.cpp
index ad6fec9..39991d3 100644
--- a/src/gpu/ops/GrCopySurfaceOp.cpp
+++ b/src/gpu/ops/GrCopySurfaceOp.cpp
@@ -85,5 +85,6 @@
         return;
     }
 
-    state->commandBuffer()->copy(fSrc.get()->priv().peekSurface(), fSrcRect, fDstPoint);
+    state->commandBuffer()->copy(fSrc.get()->priv().peekSurface(), fSrc.get()->origin(),
+                                 fSrcRect, fDstPoint);
 }
diff --git a/src/gpu/vk/GrVkCopyManager.cpp b/src/gpu/vk/GrVkCopyManager.cpp
index 040d742..9e1decf 100644
--- a/src/gpu/vk/GrVkCopyManager.cpp
+++ b/src/gpu/vk/GrVkCopyManager.cpp
@@ -143,10 +143,9 @@
 }
 
 bool GrVkCopyManager::copySurfaceAsDraw(GrVkGpu* gpu,
-                                        GrSurface* dst,
-                                        GrSurface* src,
-                                        const SkIRect& srcRect,
-                                        const SkIPoint& dstPoint) {
+                                        GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                        GrSurface* src, GrSurfaceOrigin srcOrigin,
+                                        const SkIRect& srcRect, const SkIPoint& dstPoint) {
     // None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDraw handle the
     // swizzle.
     if (gpu->caps()->shaderCaps()->configOutputSwizzle(src->config()) !=
@@ -204,7 +203,7 @@
     float dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
     float dy0 = 2.f * dstPoint.fY / dh - 1.f;
     float dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
-    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
         dy0 = -dy0;
         dy1 = -dy1;
     }
@@ -215,7 +214,7 @@
     float sy0 = (float)srcRect.fTop;
     float sy1 = (float)(srcRect.fTop + h);
     int sh = src->height();
-    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
         sy0 = sh - sy0;
         sy1 = sh - sy1;
     }
@@ -293,7 +292,7 @@
 
     GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(srcTex->asRenderTarget());
     if (texRT) {
-        gpu->onResolveRenderTarget(texRT);
+        gpu->onResolveRenderTarget(texRT, srcOrigin);
     }
 
     GrVkPrimaryCommandBuffer* cmdBuffer = gpu->currentCommandBuffer();
diff --git a/src/gpu/vk/GrVkCopyManager.h b/src/gpu/vk/GrVkCopyManager.h
index 36a08be..726faf3 100644
--- a/src/gpu/vk/GrVkCopyManager.h
+++ b/src/gpu/vk/GrVkCopyManager.h
@@ -8,6 +8,7 @@
 #ifndef GrVkCopyManager_DEFINED
 #define GrVkCopyManager_DEFINED
 
+#include "GrTypes.h"
 #include "GrVkDescriptorSetManager.h"
 
 #include "vk/GrVkDefines.h"
@@ -27,10 +28,9 @@
     ~GrVkCopyManager();
 
     bool copySurfaceAsDraw(GrVkGpu* gpu,
-                           GrSurface* dst,
-                           GrSurface* src,
-                           const SkIRect& srcRect,
-                           const SkIPoint& dstPoint);
+                           GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                           GrSurface* src, GrSurfaceOrigin srcOrigin,
+                           const SkIRect& srcRect, const SkIPoint& dstPoint);
 
     void destroyResources(GrVkGpu* gpu);
     void abandonResources();
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index f32a83a..93a4c62 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -338,7 +338,8 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                                   int width, int height,
                                    GrPixelConfig srcConfig, DrawPreference* drawPreference,
                                    WritePixelTempDrawInfo* tempDrawInfo) {
     GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
@@ -381,7 +382,7 @@
     return true;
 }
 
-bool GrVkGpu::onWritePixels(GrSurface* surface,
+bool GrVkGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin,
                             int left, int top, int width, int height,
                             GrPixelConfig config,
                             const GrMipLevel texels[], int mipLevelCount) {
@@ -416,7 +417,7 @@
                                   false);
             this->submitCommandBuffer(kForce_SyncQueue);
         }
-        success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
+        success = this->uploadTexDataLinear(vkTex, origin, left, top, width, height, config,
                                             texels[0].fPixels, texels[0].fRowBytes);
     } else {
         int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
@@ -425,7 +426,7 @@
                 return false;
             }
         }
-        success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config,
+        success = this->uploadTexDataOptimal(vkTex, origin, left, top, width, height, config,
                                              texels, mipLevelCount);
     }
 
@@ -493,8 +494,9 @@
     return true;
 }
 
-void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
-                           const SkIPoint& dstPoint) {
+void GrVkGpu::resolveImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                           GrVkRenderTarget* src, GrSurfaceOrigin srcOrigin,
+                           const SkIRect& srcRect, const SkIPoint& dstPoint) {
     SkASSERT(dst);
     SkASSERT(src && src->numColorSamples() > 1 && src->msaaImage());
 
@@ -506,8 +508,8 @@
     SkIRect srcVkRect = srcRect;
     int32_t dstY = dstPoint.fY;
 
-    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
-        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
+    if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
+        SkASSERT(kBottomLeft_GrSurfaceOrigin == dstOrigin);
         srcVkRect.fTop = src->height() - srcRect.fBottom;
         srcVkRect.fBottom = src->height() - srcRect.fTop;
         dstY = dst->height() - dstPoint.fY - srcVkRect.height();
@@ -544,7 +546,8 @@
     fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dstImage, 1, &resolveInfo);
 }
 
-void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
+void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin,
+                                          bool requiresSubmit) {
     if (target->needsResolve()) {
         SkASSERT(target->numColorSamples() > 1);
         GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
@@ -552,7 +555,8 @@
 
         const SkIRect& srcRect = rt->getResolveRect();
 
-        this->resolveImage(target, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
+        this->resolveImage(target, origin, rt, origin, srcRect,
+                           SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
 
         rt->flagAsResolved();
 
@@ -562,7 +566,7 @@
     }
 }
 
-bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
+bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
                                   int left, int top, int width, int height,
                                   GrPixelConfig dataConfig,
                                   const void* data,
@@ -598,7 +602,7 @@
                                                     &subres,
                                                     &layout));
 
-    int texTop = kBottomLeft_GrSurfaceOrigin == tex->origin() ? tex->height() - top - height : top;
+    int texTop = kBottomLeft_GrSurfaceOrigin == texOrigin ? tex->height() - top - height : top;
     const GrVkAlloc& alloc = tex->alloc();
     VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp;
     VkDeviceSize size = height*layout.rowPitch;
@@ -608,7 +612,7 @@
         return false;
     }
 
-    if (kBottomLeft_GrSurfaceOrigin == tex->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == texOrigin) {
         // copy into buffer by rows
         const char* srcRow = reinterpret_cast<const char*>(data);
         char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
@@ -628,7 +632,7 @@
     return true;
 }
 
-bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
+bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
                                    int left, int top, int width, int height,
                                    GrPixelConfig dataConfig,
                                    const GrMipLevel texels[], int mipLevelCount) {
@@ -663,7 +667,7 @@
     }
 
     // Determine whether we need to flip when we copy into the buffer
-    bool flipY = (kBottomLeft_GrSurfaceOrigin == tex->origin() && mipLevelCount);
+    bool flipY = (kBottomLeft_GrSurfaceOrigin == texOrigin && mipLevelCount);
 
     SkTArray<size_t> individualMipOffsets(mipLevelCount);
     individualMipOffsets.push_back(0);
@@ -820,8 +824,8 @@
 
     if (mipLevelCount) {
         SkASSERT(texels[0].fPixels);
-        if (!this->uploadTexDataOptimal(tex.get(), 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
-                                        texels, mipLevelCount)) {
+        if (!this->uploadTexDataOptimal(tex.get(), desc.fOrigin, 0, 0, desc.fWidth, desc.fHeight,
+                                        desc.fConfig, texels, mipLevelCount)) {
             tex->unref();
             return nullptr;
         }
@@ -864,15 +868,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
-    // By default, all textures in Vk use TopLeft
-    if (kDefault_GrSurfaceOrigin == origin) {
-        return kTopLeft_GrSurfaceOrigin;
-    } else {
-        return origin;
-    }
-}
-
 static bool check_backend_texture(const GrBackendTexture& backendTex) {
     const GrVkImageInfo* info = backendTex.getVkImageInfo();
     if (!info) {
@@ -888,7 +883,6 @@
 }
 
 sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
-                                               GrSurfaceOrigin origin,
                                                GrWrapOwnership ownership) {
     if (!check_backend_texture(backendTex)) {
         return nullptr;
@@ -896,19 +890,16 @@
 
     GrSurfaceDesc surfDesc;
     surfDesc.fFlags = kNone_GrSurfaceFlags;
+    surfDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // Not actually used in the following
     surfDesc.fWidth = backendTex.width();
     surfDesc.fHeight = backendTex.height();
     surfDesc.fConfig = backendTex.config();
     surfDesc.fSampleCnt = 0;
-    // In GL, Chrome assumes all textures are BottomLeft
-    // In VK, we don't have this restriction
-    surfDesc.fOrigin = resolve_origin(origin);
 
     return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, backendTex.getVkImageInfo());
 }
 
 sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
-                                                         GrSurfaceOrigin origin,
                                                          int sampleCnt,
                                                          GrWrapOwnership ownership) {
     if (!check_backend_texture(backendTex)) {
@@ -917,20 +908,17 @@
 
     GrSurfaceDesc surfDesc;
     surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+    surfDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; // Not actually used in the following
     surfDesc.fWidth = backendTex.width();
     surfDesc.fHeight = backendTex.height();
     surfDesc.fConfig = backendTex.config();
     surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config());
-    // In GL, Chrome assumes all textures are BottomLeft
-    // In VK, we don't have this restriction
-    surfDesc.fOrigin = resolve_origin(origin);
 
     return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, surfDesc, ownership,
                                                                    backendTex.getVkImageInfo());
 }
 
-sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT,
-                                                         GrSurfaceOrigin origin){
+sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT){
     // Currently the Vulkan backend does not support wrapping of msaa render targets directly. In
     // general this is not an issue since swapchain images in vulkan are never multisampled. Thus if
     // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
@@ -949,8 +937,7 @@
 
     GrSurfaceDesc desc;
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
-    SkASSERT(kDefault_GrSurfaceOrigin != origin);
-    desc.fOrigin = origin;
+    desc.fOrigin = kBottomLeft_GrSurfaceOrigin; // Not actually used in the following
     desc.fWidth = backendRT.width();
     desc.fHeight = backendRT.height();
     desc.fConfig = backendRT.config();
@@ -966,7 +953,6 @@
 }
 
 sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
-                                                                  GrSurfaceOrigin origin,
                                                                   int sampleCnt) {
 
     const GrVkImageInfo* info = tex.getVkImageInfo();
@@ -979,7 +965,7 @@
 
     GrSurfaceDesc desc;
     desc.fFlags = kRenderTarget_GrSurfaceFlag;
-    desc.fOrigin = resolve_origin(origin);
+    desc.fOrigin = kBottomLeft_GrSurfaceOrigin; // Not actually used in the following
     desc.fWidth = tex.width();
     desc.fHeight = tex.height();
     desc.fConfig = tex.config();
@@ -989,7 +975,7 @@
     return tgt;
 }
 
-void GrVkGpu::generateMipmap(GrVkTexture* tex) {
+void GrVkGpu::generateMipmap(GrVkTexture* tex, GrSurfaceOrigin texOrigin) {
     // don't do anything for linearly tiled textures (can't have mipmaps)
     if (tex->isLinearTiled()) {
         SkDebugf("Trying to create mipmap for linear tiled texture");
@@ -1011,7 +997,7 @@
     // We may need to resolve the texture first if it is also a render target
     GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget());
     if (texRT) {
-        this->internalResolveRenderTarget(texRT, false);
+        this->internalResolveRenderTarget(texRT, texOrigin, false);
     }
 
     int width = tex->width();
@@ -1521,8 +1507,8 @@
     fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
 }
 
-inline bool can_copy_image(const GrSurface* dst,
-                           const GrSurface* src,
+inline bool can_copy_image(const GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                           const GrSurface* src, GrSurfaceOrigin srcOrigin,
                            const GrVkGpu* gpu) {
     const GrRenderTarget* dstRT = dst->asRenderTarget();
     const GrRenderTarget* srcRT = src->asRenderTarget();
@@ -1542,7 +1528,7 @@
 
     // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
     // as image usage flags.
-    if (src->origin() == dst->origin() &&
+    if (srcOrigin == dstOrigin &&
         GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
         return true;
     }
@@ -1550,13 +1536,13 @@
     return false;
 }
 
-void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
-                                     GrSurface* src,
+void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                     GrSurface* src, GrSurfaceOrigin srcOrigin,
                                      GrVkImage* dstImage,
                                      GrVkImage* srcImage,
                                      const SkIRect& srcRect,
                                      const SkIPoint& dstPoint) {
-    SkASSERT(can_copy_image(dst, src, this));
+    SkASSERT(can_copy_image(dst, dstOrigin, src, srcOrigin, this));
 
     // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
     // the cache is flushed since it is only being written to.
@@ -1576,8 +1562,8 @@
     SkIRect srcVkRect = srcRect;
     int32_t dstY = dstPoint.fY;
 
-    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
-        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
+    if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
+        SkASSERT(kBottomLeft_GrSurfaceOrigin == dstOrigin);
         srcVkRect.fTop = src->height() - srcRect.fBottom;
         srcVkRect.fBottom =  src->height() - srcRect.fTop;
         dstY = dst->height() - dstPoint.fY - srcVkRect.height();
@@ -1627,8 +1613,8 @@
     return true;
 }
 
-void GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
-                                GrSurface* src,
+void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                GrSurface* src, GrSurfaceOrigin srcOrigin,
                                 GrVkImage* dstImage,
                                 GrVkImage* srcImage,
                                 const SkIRect& srcRect,
@@ -1655,7 +1641,7 @@
     dstRect.fLeft = dstPoint.fX;
     dstRect.fRight = dstPoint.fX + srcRect.width();
 
-    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
         srcVkRect.fTop = src->height() - srcRect.fBottom;
         srcVkRect.fBottom = src->height() - srcRect.fTop;
     } else {
@@ -1663,7 +1649,7 @@
         srcVkRect.fBottom = srcRect.fBottom;
     }
 
-    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
         dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
     } else {
         dstRect.fTop = dstPoint.fY;
@@ -1672,7 +1658,7 @@
 
     // If we have different origins, we need to flip the top and bottom of the dst rect so that we
     // get the correct origintation of the copied data.
-    if (src->origin() != dst->origin()) {
+    if (srcOrigin != dstOrigin) {
         SkTSwap(dstRect.fTop, dstRect.fBottom);
     }
 
@@ -1695,8 +1681,8 @@
     this->didWriteToSurface(dst, &dstRect);
 }
 
-inline bool can_copy_as_resolve(const GrSurface* dst,
-                                const GrSurface* src,
+inline bool can_copy_as_resolve(const GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                const GrSurface* src, GrSurfaceOrigin srcOrigin,
                                 const GrVkGpu* gpu) {
     // Our src must be a multisampled render target
     if (!src->asRenderTarget() || src->asRenderTarget()->numColorSamples() <= 1) {
@@ -1711,27 +1697,27 @@
     }
 
     // Surfaces must have the same origin.
-    if (src->origin() != dst->origin()) {
+    if (srcOrigin != dstOrigin) {
         return false;
     }
 
     return true;
 }
 
-void GrVkGpu::copySurfaceAsResolve(GrSurface* dst,
-                                   GrSurface* src,
+void GrVkGpu::copySurfaceAsResolve(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                   GrSurface* src, GrSurfaceOrigin srcOrigin,
                                    const SkIRect& srcRect,
                                    const SkIPoint& dstPoint) {
     GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
-    this->resolveImage(dst, srcRT, srcRect, dstPoint);
+    this->resolveImage(dst, dstOrigin, srcRT, srcOrigin, srcRect, dstPoint);
 }
 
-bool GrVkGpu::onCopySurface(GrSurface* dst,
-                            GrSurface* src,
+bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                            GrSurface* src, GrSurfaceOrigin srcOrigin,
                             const SkIRect& srcRect,
                             const SkIPoint& dstPoint) {
-    if (can_copy_as_resolve(dst, src, this)) {
-        this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
+    if (can_copy_as_resolve(dst, dstOrigin, src, srcOrigin, this)) {
+        this->copySurfaceAsResolve(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
         return true;
     }
 
@@ -1739,7 +1725,7 @@
         this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
     }
 
-    if (fCopyManager.copySurfaceAsDraw(this, dst, src, srcRect, dstPoint)) {
+    if (fCopyManager.copySurfaceAsDraw(this, dst, dstOrigin, src, srcOrigin, srcRect, dstPoint)) {
         return true;
     }
 
@@ -1767,27 +1753,30 @@
         return false;
     }
 
-    if (can_copy_image(dst, src, this)) {
-        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
+    if (can_copy_image(dst, dstOrigin, src, srcOrigin, this)) {
+        this->copySurfaceAsCopyImage(dst, dstOrigin, src, srcOrigin, dstImage, srcImage,
+                                     srcRect, dstPoint);
         return true;
     }
 
     if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
-        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
+        this->copySurfaceAsBlit(dst, dstOrigin, src, srcOrigin, dstImage, srcImage,
+                                srcRect, dstPoint);
         return true;
     }
 
     return false;
 }
 
-void GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
+void GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, GrSurfaceOrigin, const GrStencilSettings&,
                                       int* effectiveSampleCnt, SamplePattern*) {
     // TODO: stub.
     SkASSERT(!this->caps()->sampleLocationsSupport());
     *effectiveSampleCnt = rt->numStencilSamples();
 }
 
-bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
+bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                                  int width, int height, size_t rowBytes,
                                   GrPixelConfig readConfig, DrawPreference* drawPreference,
                                   ReadPixelTempDrawInfo* tempDrawInfo) {
     // These settings we will always want if a temp draw is performed.
@@ -1820,7 +1809,7 @@
     return true;
 }
 
-bool GrVkGpu::onReadPixels(GrSurface* surface,
+bool GrVkGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
                            int left, int top, int width, int height,
                            GrPixelConfig config,
                            void* buffer,
@@ -1840,7 +1829,7 @@
             case GrVkRenderTarget::kAutoResolves_ResolveType:
                 break;
             case GrVkRenderTarget::kCanResolve_ResolveType:
-                this->internalResolveRenderTarget(rt, false);
+                this->internalResolveRenderTarget(rt, origin, false);
                 break;
             default:
                 SK_ABORT("Unknown resolve type");
@@ -1863,7 +1852,7 @@
 
     size_t bpp = GrBytesPerPixel(config);
     size_t tightRowBytes = bpp * width;
-    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
+    bool flipY = kBottomLeft_GrSurfaceOrigin == origin;
 
     VkBufferImageCopy region;
     memset(&region, 0, sizeof(VkBufferImageCopy));
@@ -1987,11 +1976,11 @@
 void GrVkGpu::submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBuffer*>& buffers,
                                            const GrVkRenderPass* renderPass,
                                            const VkClearValue* colorClear,
-                                           GrVkRenderTarget* target,
+                                           GrVkRenderTarget* target, GrSurfaceOrigin origin,
                                            const SkIRect& bounds) {
     const SkIRect* pBounds = &bounds;
     SkIRect flippedBounds;
-    if (kBottomLeft_GrSurfaceOrigin == target->origin()) {
+    if (kBottomLeft_GrSurfaceOrigin == origin) {
         flippedBounds = bounds;
         flippedBounds.fTop = target->height() - bounds.fBottom;
         flippedBounds.fBottom = target->height() - bounds.fTop;
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index f36ec31..3850af6 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -66,20 +66,21 @@
         kSkip_SyncQueue
     };
 
-    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+    bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
+                             int readWidth, int readHeight, size_t rowBytes,
                              GrPixelConfig readConfig, DrawPreference*,
                              ReadPixelTempDrawInfo*) override;
 
-    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+    bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
+                              int width, int height,
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override;
 
-    bool onCopySurface(GrSurface* dst,
-                       GrSurface* src,
-                       const SkIRect& srcRect,
-                       const SkIPoint& dstPoint) override;
+    bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                       GrSurface* src, GrSurfaceOrigin srcOrigin,
+                       const SkIRect& srcRect, const SkIPoint& dstPoint) override;
 
-    void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
+    void onQueryMultisampleSpecs(GrRenderTarget*, GrSurfaceOrigin, const GrStencilSettings&,
                                  int* effectiveSampleCnt, SamplePattern*) override;
 
     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
@@ -120,14 +121,14 @@
         return fCompiler;
     }
 
-    void onResolveRenderTarget(GrRenderTarget* target) override {
-        this->internalResolveRenderTarget(target, true);
+    void onResolveRenderTarget(GrRenderTarget* target, GrSurfaceOrigin origin) override {
+        this->internalResolveRenderTarget(target, origin, true);
     }
 
     void submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBuffer*>&,
                                       const GrVkRenderPass*,
                                       const VkClearValue* colorClear,
-                                      GrVkRenderTarget*,
+                                      GrVkRenderTarget*, GrSurfaceOrigin,
                                       const SkIRect& bounds);
 
     GrFence SK_WARN_UNUSED_RESULT insertFence() override;
@@ -142,7 +143,7 @@
 
     sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
 
-    void generateMipmap(GrVkTexture* tex);
+    void generateMipmap(GrVkTexture* tex, GrSurfaceOrigin texOrigin);
 
     void copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceSize srcOffset,
                     VkDeviceSize dstOffset, VkDeviceSize size);
@@ -181,18 +182,13 @@
     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
                                      const GrMipLevel texels[], int mipLevelCount) override;
 
-    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
-                                          GrSurfaceOrigin,
-                                          GrWrapOwnership) override;
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override;
     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
-                                                    GrSurfaceOrigin,
                                                     int sampleCnt,
                                                     GrWrapOwnership) override;
-    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
-                                                    GrSurfaceOrigin) override;
+    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override;
 
     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
-                                                             GrSurfaceOrigin,
                                                              int sampleCnt) override;
 
     GrBuffer* onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern,
@@ -200,13 +196,13 @@
 
     gr_instanced::InstancedRendering* onCreateInstancedRendering() override { return nullptr; }
 
-    bool onReadPixels(GrSurface* surface,
+    bool onReadPixels(GrSurface* surface, GrSurfaceOrigin,
                       int left, int top, int width, int height,
                       GrPixelConfig,
                       void* buffer,
                       size_t rowBytes) override;
 
-    bool onWritePixels(GrSurface* surface,
+    bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
                        int left, int top, int width, int height,
                        GrPixelConfig config, const GrMipLevel texels[], int mipLevelCount) override;
 
@@ -225,42 +221,39 @@
     // wait semaphores to the submission of this command buffer.
     void submitCommandBuffer(SyncQueue sync);
 
-    void internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit);
+    void internalResolveRenderTarget(GrRenderTarget*, GrSurfaceOrigin origin, bool requiresSubmit);
 
-    void copySurfaceAsCopyImage(GrSurface* dst,
-                                GrSurface* src,
-                                GrVkImage* dstImage,
-                                GrVkImage* srcImage,
+    void copySurfaceAsCopyImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                                GrSurface* src, GrSurfaceOrigin srcOrigin,
+                                GrVkImage* dstImage, GrVkImage* srcImage,
                                 const SkIRect& srcRect,
                                 const SkIPoint& dstPoint);
 
-    void copySurfaceAsBlit(GrSurface* dst,
-                           GrSurface* src,
-                           GrVkImage* dstImage,
-                           GrVkImage* srcImage,
+    void copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                           GrSurface* src, GrSurfaceOrigin srcOrigin,
+                           GrVkImage* dstImage, GrVkImage* srcImage,
                            const SkIRect& srcRect,
                            const SkIPoint& dstPoint);
 
-    void copySurfaceAsResolve(GrSurface* dst,
-                              GrSurface* src,
+    void copySurfaceAsResolve(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                              GrSurface* src, GrSurfaceOrigin srcOrigin,
                               const SkIRect& srcRect,
                               const SkIPoint& dstPoint);
 
     // helpers for onCreateTexture and writeTexturePixels
-    bool uploadTexDataLinear(GrVkTexture* tex,
+    bool uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
                              int left, int top, int width, int height,
                              GrPixelConfig dataConfig,
                              const void* data,
                              size_t rowBytes);
-    bool uploadTexDataOptimal(GrVkTexture* tex,
+    bool uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
                               int left, int top, int width, int height,
                               GrPixelConfig dataConfig,
                               const GrMipLevel texels[], int mipLevelCount);
 
-    void resolveImage(GrSurface* dst,
-                      GrVkRenderTarget* src,
-                      const SkIRect& srcRect,
-                      const SkIPoint& dstPoint);
+    void resolveImage(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+                      GrVkRenderTarget* src, GrSurfaceOrigin srcOrigin,
+                      const SkIRect& srcRect, const SkIPoint& dstPoint);
 
     sk_sp<const GrVkBackendContext> fBackendContext;
     sk_sp<GrVkCaps>                 fVkCaps;
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 1b2beff..f202c9b 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -22,9 +22,9 @@
 #include "GrVkTexture.h"
 #include "SkRect.h"
 
-void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
-                                       const SkIPoint& dstPoint) {
-    fCopies.emplace_back(src, srcRect, dstPoint);
+void GrVkGpuTextureCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin,
+                                       const SkIRect& srcRect, const SkIPoint& dstPoint) {
+    fCopies.emplace_back(src, srcOrigin, srcRect, dstPoint);
 }
 
 void GrVkGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
@@ -34,7 +34,8 @@
 void GrVkGpuTextureCommandBuffer::submit() {
     for (int i = 0; i < fCopies.count(); ++i) {
         CopyInfo& copyInfo = fCopies[i];
-        fGpu->copySurface(fTexture, copyInfo.fSrc, copyInfo.fSrcRect, copyInfo.fDstPoint);
+        fGpu->copySurface(fTexture, fOrigin, copyInfo.fSrc, copyInfo.fSrcOrigin, copyInfo.fSrcRect,
+                          copyInfo.fDstPoint);
     }
 }
 
@@ -181,7 +182,8 @@
 
         for (int j = 0; j < cbInfo.fPreCopies.count(); ++j) {
             CopyInfo& copyInfo = cbInfo.fPreCopies[j];
-            fGpu->copySurface(fRenderTarget, copyInfo.fSrc, copyInfo.fSrcRect, copyInfo.fDstPoint);
+            fGpu->copySurface(fRenderTarget, fOrigin, copyInfo.fSrc, copyInfo.fSrcOrigin,
+                              copyInfo.fSrcRect, copyInfo.fDstPoint);
         }
 
         // TODO: We can't add this optimization yet since many things create a scratch texture which
@@ -203,7 +205,7 @@
             cbInfo.fBounds.roundOut(&iBounds);
 
             fGpu->submitSecondaryCommandBuffer(cbInfo.fCommandBuffers, cbInfo.fRenderPass,
-                                               &cbInfo.fColorClearValue, vkRT, iBounds);
+                                               &cbInfo.fColorClearValue, vkRT, fOrigin, iBounds);
         }
     }
 }
@@ -440,13 +442,13 @@
     fCommandBufferInfos[fCurrentCmdInfo].fPreDrawUploads.emplace_back(state, upload);
 }
 
-void GrVkGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
+void GrVkGpuRTCommandBuffer::copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
                                   const SkIPoint& dstPoint) {
     if (!fCommandBufferInfos[fCurrentCmdInfo].fIsEmpty ||
         fCommandBufferInfos[fCurrentCmdInfo].fStartsWithClear) {
         this->addAdditionalRenderPass();
     }
-    fCommandBufferInfos[fCurrentCmdInfo].fPreCopies.emplace_back(src, srcRect, dstPoint);
+    fCommandBufferInfos[fCurrentCmdInfo].fPreCopies.emplace_back(src, srcOrigin, srcRect, dstPoint);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -523,10 +525,12 @@
     GrRenderTarget* rt = pipeline.renderTarget();
 
     if (!pipeline.getScissorState().enabled()) {
-        GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt,
+        GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(),
+                                                 rt, pipeline.proxy()->origin(),
                                                  SkIRect::MakeWH(rt->width(), rt->height()));
     } else if (!hasDynamicState) {
-        GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), rt,
+        GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(),
+                                                 rt, pipeline.proxy()->origin(),
                                                  pipeline.getScissorState().rect());
     }
     GrVkPipeline::SetDynamicViewportState(fGpu, cbInfo.currentCmdBuf(), rt);
@@ -555,14 +559,14 @@
         // We may need to resolve the texture first if it is also a render target
         GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(vkTexture->asRenderTarget());
         if (texRT) {
-            gpu->onResolveRenderTarget(texRT);
+            gpu->onResolveRenderTarget(texRT, sampler.proxy()->origin());
         }
 
         const GrSamplerParams& params = sampler.params();
         // Check if we need to regenerate any mip maps
         if (GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
             if (vkTexture->texturePriv().mipMapsAreDirty()) {
-                gpu->generateMipmap(vkTexture);
+                gpu->generateMipmap(vkTexture, sampler.proxy()->origin());
                 vkTexture->texturePriv().dirtyMipMaps(false);
             }
         }
@@ -622,7 +626,7 @@
         if (dynamicStates) {
             if (pipeline.getScissorState().enabled()) {
                 GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(),
-                                                         fRenderTarget,
+                                                         fRenderTarget, pipeline.proxy()->origin(),
                                                          dynamicStates[i].fScissorRect);
             }
         }
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index 9209a3b..85a3bca 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -30,7 +30,8 @@
 
     ~GrVkGpuTextureCommandBuffer() override;
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+    void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+              const SkIPoint& dstPoint) override;
 
     void insertEventMarker(const char*) override;
 
@@ -38,12 +39,14 @@
     void submit() override;
 
     struct CopyInfo {
-        CopyInfo(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint)
-            : fSrc(src), fSrcRect(srcRect), fDstPoint(dstPoint) {}
+        CopyInfo(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+                 const SkIPoint& dstPoint)
+            : fSrc(src), fSrcOrigin(srcOrigin), fSrcRect(srcRect), fDstPoint(dstPoint) {}
 
-        GrSurface* fSrc;
-        SkIRect    fSrcRect;
-        SkIPoint   fDstPoint;
+        GrSurface*      fSrc;
+        GrSurfaceOrigin fSrcOrigin;
+        SkIRect         fSrcRect;
+        SkIPoint        fDstPoint;
     };
 
     GrVkGpu*                    fGpu;
@@ -68,7 +71,8 @@
 
     void inlineUpload(GrOpFlushState* state, GrDrawOp::DeferredUploadFn& upload) override;
 
-    void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+    void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+              const SkIPoint& dstPoint) override;
 
     void submit() override;
 
@@ -138,12 +142,14 @@
     };
 
     struct CopyInfo {
-        CopyInfo(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint)
-            : fSrc(src), fSrcRect(srcRect), fDstPoint(dstPoint) {}
+        CopyInfo(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+                 const SkIPoint& dstPoint)
+            : fSrc(src), fSrcOrigin(srcOrigin), fSrcRect(srcRect), fDstPoint(dstPoint) {}
 
-        GrSurface* fSrc;
-        SkIRect    fSrcRect;
-        SkIPoint   fDstPoint;
+        GrSurface*      fSrc;
+        GrSurfaceOrigin fSrcOrigin;
+        SkIRect         fSrcRect;
+        SkIPoint        fDstPoint;
     };
 
     struct CommandBufferInfo {
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index 22777df..11dd982 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -497,6 +497,7 @@
 void GrVkPipeline::SetDynamicScissorRectState(GrVkGpu* gpu,
                                               GrVkCommandBuffer* cmdBuffer,
                                               const GrRenderTarget* renderTarget,
+                                              GrSurfaceOrigin rtOrigin,
                                               SkIRect scissorRect) {
     if (!scissorRect.intersect(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()))) {
         scissorRect.setEmpty();
@@ -505,10 +506,10 @@
     VkRect2D scissor;
     scissor.offset.x = scissorRect.fLeft;
     scissor.extent.width = scissorRect.width();
-    if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) {
+    if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
         scissor.offset.y = scissorRect.fTop;
     } else {
-        SkASSERT(kBottomLeft_GrSurfaceOrigin == renderTarget->origin());
+        SkASSERT(kBottomLeft_GrSurfaceOrigin == rtOrigin);
         scissor.offset.y = renderTarget->height() - scissorRect.fBottom;
     }
     scissor.extent.height = scissorRect.height();
diff --git a/src/gpu/vk/GrVkPipeline.h b/src/gpu/vk/GrVkPipeline.h
index d05974b..88c3d5f 100644
--- a/src/gpu/vk/GrVkPipeline.h
+++ b/src/gpu/vk/GrVkPipeline.h
@@ -40,7 +40,7 @@
     VkPipeline pipeline() const { return fPipeline; }
 
     static void SetDynamicScissorRectState(GrVkGpu*, GrVkCommandBuffer*, const GrRenderTarget*,
-                                           SkIRect);
+                                           GrSurfaceOrigin, SkIRect);
     static void SetDynamicViewportState(GrVkGpu*, GrVkCommandBuffer*, const GrRenderTarget*);
     static void SetDynamicBlendConstantState(GrVkGpu*, GrVkCommandBuffer*, GrPixelConfig,
                                              const GrXferProcessor&);
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index a19556b..8c2dfa0 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -266,9 +266,8 @@
         return nullptr;
     }
 
-    sk_sp<GrTexture> tex = ctx->resourceProvider()->wrapBackendTexture(backendTex,
-                                                                       origin,
-                                                                       ownership);
+    SkASSERT(kDefault_GrSurfaceOrigin != origin);
+    sk_sp<GrTexture> tex = ctx->resourceProvider()->wrapBackendTexture(backendTex, ownership);
     if (!tex) {
         return nullptr;
     }
@@ -491,7 +490,7 @@
 
     sk_sp<GrSemaphore> sema = context->getGpu()->prepareTextureForCrossContextUsage(texture.get());
 
-    auto gen = GrBackendTextureImageGenerator::Make(std::move(texture),
+    auto gen = GrBackendTextureImageGenerator::Make(std::move(texture), proxy->origin(),
                                                     std::move(sema), codecImage->alphaType(),
                                                     std::move(texColorSpace));
     return SkImage::MakeFromGenerator(std::move(gen));
diff --git a/tests/GrSurfaceTest.cpp b/tests/GrSurfaceTest.cpp
index 5c665d1..abf2973 100644
--- a/tests/GrSurfaceTest.cpp
+++ b/tests/GrSurfaceTest.cpp
@@ -58,7 +58,7 @@
                                                                backendTexHandle);
 
     sk_sp<GrSurface> texRT2 = context->resourceProvider()->wrapRenderableBackendTexture(
-            backendTex, kTopLeft_GrSurfaceOrigin, 0, kBorrow_GrWrapOwnership);
+            backendTex, 0, kBorrow_GrWrapOwnership);
 
     REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asRenderTarget());
     REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asTexture());
diff --git a/tests/ProxyConversionTest.cpp b/tests/ProxyConversionTest.cpp
index 78465f9..9f5801c 100644
--- a/tests/ProxyConversionTest.cpp
+++ b/tests/ProxyConversionTest.cpp
@@ -27,7 +27,7 @@
                                     desc.fConfig, fboInfo);
 
     SkASSERT(kDefault_GrSurfaceOrigin != desc.fOrigin);
-    sk_sp<GrRenderTarget> defaultFBO(provider->wrapBackendRenderTarget(backendRT, desc.fOrigin));
+    sk_sp<GrRenderTarget> defaultFBO(provider->wrapBackendRenderTarget(backendRT));
     SkASSERT(!defaultFBO->asTexture());
 
     return GrSurfaceProxy::MakeWrapped(std::move(defaultFBO), desc.fOrigin);
diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp
index a9b4643..453cb5e 100644
--- a/tests/ProxyTest.cpp
+++ b/tests/ProxyTest.cpp
@@ -63,7 +63,6 @@
         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() != rt->uniqueID().asUInt());
     }
 
-    REPORTER_ASSERT(reporter, rt->origin() == rtProxy->origin());
     if (SkBackingFit::kExact == fit) {
         REPORTER_ASSERT(reporter, rt->width() == rtProxy->width());
         REPORTER_ASSERT(reporter, rt->height() == rtProxy->height());
@@ -98,7 +97,6 @@
         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() != tex->uniqueID().asUInt());
     }
 
-    REPORTER_ASSERT(reporter, tex->origin() == texProxy->origin());
     if (SkBackingFit::kExact == fit) {
         REPORTER_ASSERT(reporter, tex->width() == texProxy->width());
         REPORTER_ASSERT(reporter, tex->height() == texProxy->height());
@@ -234,7 +232,7 @@
                                                         config, fboInfo);
 
                         sk_sp<GrRenderTarget> defaultFBO(
-                            provider->wrapBackendRenderTarget(backendRT, origin));
+                            provider->wrapBackendRenderTarget(backendRT));
 
                         sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(defaultFBO,
                                                                                  origin));
diff --git a/tests/ResourceAllocatorTest.cpp b/tests/ResourceAllocatorTest.cpp
index 4c40619..ffe7e35 100644
--- a/tests/ResourceAllocatorTest.cpp
+++ b/tests/ResourceAllocatorTest.cpp
@@ -54,7 +54,7 @@
                                                                *backendTexHandle);
 
     SkASSERT(kDefault_GrSurfaceOrigin != p.fOrigin);
-    sk_sp<GrSurface> tex = context->resourceProvider()->wrapBackendTexture(backendTex, p.fOrigin,
+    sk_sp<GrSurface> tex = context->resourceProvider()->wrapBackendTexture(backendTex,
                                                                            kBorrow_GrWrapOwnership);
     return GrSurfaceProxy::MakeWrapped(std::move(tex), p.fOrigin);
 }
@@ -169,9 +169,8 @@
         // Two non-overlapping intervals w/ different RT classifications should never share
         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
         { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kDontShare },
-        // Two non-overlapping intervals w/ different origins should not share
-        // TODO: rm this test case
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kBL }, kDontShare },
+        // Two non-overlapping intervals w/ different origins should share
+        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kBL }, kShare },
     };
 
     for (auto test : gNonOverlappingTests) {
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 48f50a0..c10d581 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -96,9 +96,10 @@
     GrContext* context = ctxInfo.grContext();
     GrSurfaceDesc smallDesc;
     smallDesc.fFlags = kRenderTarget_GrSurfaceFlag;
-    smallDesc.fConfig = kRGBA_8888_GrPixelConfig;
+    smallDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
     smallDesc.fWidth = 4;
     smallDesc.fHeight = 4;
+    smallDesc.fConfig = kRGBA_8888_GrPixelConfig;
     smallDesc.fSampleCnt = 0;
 
     if (context->caps()->avoidStencilBuffers()) {
@@ -136,9 +137,10 @@
     // An RT with a much larger size should not share.
     GrSurfaceDesc bigDesc;
     bigDesc.fFlags = kRenderTarget_GrSurfaceFlag;
-    bigDesc.fConfig = kRGBA_8888_GrPixelConfig;
+    bigDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
     bigDesc.fWidth = 400;
     bigDesc.fHeight = 200;
+    bigDesc.fConfig = kRGBA_8888_GrPixelConfig;
     bigDesc.fSampleCnt = 0;
     sk_sp<GrTexture> bigRT(resourceProvider->createTexture(bigDesc, SkBudgeted::kNo));
     if (bigRT && bigRT->asRenderTarget()) {
@@ -228,7 +230,7 @@
                                                                 kRGBA_8888_GrPixelConfig,
                                                                 texHandles[0]);
     sk_sp<GrTexture> borrowed(context->resourceProvider()->wrapBackendTexture(
-            backendTex1, kTopLeft_GrSurfaceOrigin, kBorrow_GrWrapOwnership));
+            backendTex1, kBorrow_GrWrapOwnership));
 
     GrBackendTexture backendTex2 = GrTest::CreateBackendTexture(context->contextPriv().getBackend(),
                                                                 kW,
@@ -236,7 +238,7 @@
                                                                 kRGBA_8888_GrPixelConfig,
                                                                 texHandles[1]);
     sk_sp<GrTexture> adopted(context->resourceProvider()->wrapBackendTexture(
-            backendTex2, kTopLeft_GrSurfaceOrigin, kAdopt_GrWrapOwnership));
+            backendTex2, kAdopt_GrWrapOwnership));
 
     REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr);
     if (!borrowed || !adopted) {
@@ -1636,6 +1638,7 @@
                                             int sampleCnt) {
     GrSurfaceDesc desc;
     desc.fFlags = flags;
+    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
     desc.fWidth = width;
     desc.fHeight = height;
     desc.fConfig = kRGBA_8888_GrPixelConfig;
diff --git a/tests/TransferPixelsTest.cpp b/tests/TransferPixelsTest.cpp
index daeaada..722707a 100755
--- a/tests/TransferPixelsTest.cpp
+++ b/tests/TransferPixelsTest.cpp
@@ -109,7 +109,7 @@
     REPORTER_ASSERT(reporter, result);
 
     memset(dstBuffer.get(), 0xCDCD, size);
-    result = context->getGpu()->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight,
+    result = context->getGpu()->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight,
                                            config, dstBuffer.get(), rowBytes);
     if (result) {
         REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
@@ -141,7 +141,7 @@
     REPORTER_ASSERT(reporter, result);
 
     memset(dstBuffer.get(), 0xCDCD, size);
-    result = context->getGpu()->readPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight,
+    result = context->getGpu()->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight,
                                            config, dstBuffer.get(), rowBytes);
     if (result) {
         REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
diff --git a/tests/VkWrapTests.cpp b/tests/VkWrapTests.cpp
index f64043d..4f4c833 100644
--- a/tests/VkWrapTests.cpp
+++ b/tests/VkWrapTests.cpp
@@ -37,42 +37,30 @@
     const GrVkImageInfo* imageInfo = reinterpret_cast<const GrVkImageInfo*>(backendObj);
 
     GrBackendTexture backendTex = GrBackendTexture(kW, kH, *imageInfo);
-    sk_sp<GrTexture> tex = gpu->wrapBackendTexture(backendTex,
-                                                   kTopLeft_GrSurfaceOrigin,
-                                                   kBorrow_GrWrapOwnership);
+    sk_sp<GrTexture> tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership);
     REPORTER_ASSERT(reporter, tex);
 
     // image is null
     GrVkImageInfo backendCopy = *imageInfo;
     backendCopy.fImage = VK_NULL_HANDLE;
     backendTex = GrBackendTexture(kW, kH, backendCopy);
-    tex = gpu->wrapBackendTexture(backendTex,
-                                  kTopLeft_GrSurfaceOrigin,
-                                  kBorrow_GrWrapOwnership);
+    tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
-    tex = gpu->wrapBackendTexture(backendTex,
-                                  kTopLeft_GrSurfaceOrigin,
-                                  kAdopt_GrWrapOwnership);
+    tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
 
     // alloc is null
     backendCopy.fImage = imageInfo->fImage;
     backendCopy.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
     backendTex = GrBackendTexture(kW, kH, backendCopy);
-    tex = gpu->wrapBackendTexture(backendTex,
-                                  kTopLeft_GrSurfaceOrigin,
-                                  kBorrow_GrWrapOwnership);
+    tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
-    tex = gpu->wrapBackendTexture(backendTex,
-                                  kTopLeft_GrSurfaceOrigin,
-                                  kAdopt_GrWrapOwnership);
+    tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
     // check adopt creation
     backendCopy.fAlloc = imageInfo->fAlloc;
     backendTex = GrBackendTexture(kW, kH, backendCopy);
-    tex = gpu->wrapBackendTexture(backendTex,
-                                  kTopLeft_GrSurfaceOrigin,
-                                  kAdopt_GrWrapOwnership);
+    tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership);
 
     REPORTER_ASSERT(reporter, tex);
 
@@ -88,14 +76,14 @@
 
     GrBackendRenderTarget backendRT(kW, kH, 0, 0, *backendTex);
 
-    sk_sp<GrRenderTarget> rt = gpu->wrapBackendRenderTarget(backendRT, kTopLeft_GrSurfaceOrigin);
+    sk_sp<GrRenderTarget> rt = gpu->wrapBackendRenderTarget(backendRT);
     REPORTER_ASSERT(reporter, rt);
 
     // image is null
     GrVkImageInfo backendCopy = *backendTex;
     backendCopy.fImage = VK_NULL_HANDLE;
     GrBackendRenderTarget backendRT2(kW, kH, 0, 0, backendCopy);
-    rt = gpu->wrapBackendRenderTarget(backendRT2, kTopLeft_GrSurfaceOrigin);
+    rt = gpu->wrapBackendRenderTarget(backendRT2);
     REPORTER_ASSERT(reporter, !rt);
 
     // alloc is null
@@ -103,7 +91,7 @@
     backendCopy.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
     // can wrap null alloc
     GrBackendRenderTarget backendRT3(kW, kH, 0, 0, backendCopy);
-    rt = gpu->wrapBackendRenderTarget(backendRT3, kTopLeft_GrSurfaceOrigin);
+    rt = gpu->wrapBackendRenderTarget(backendRT3);
     REPORTER_ASSERT(reporter, rt);
 
     // When we wrapBackendRenderTarget it is always borrowed, so we must make sure to free the
@@ -119,9 +107,7 @@
     const GrVkImageInfo* imageInfo = reinterpret_cast<const GrVkImageInfo*>(backendObj);
 
     GrBackendTexture backendTex = GrBackendTexture(kW, kH, *imageInfo);
-    sk_sp<GrTexture> tex = gpu->wrapRenderableBackendTexture(backendTex,
-                                                             kTopLeft_GrSurfaceOrigin,
-                                                             0,
+    sk_sp<GrTexture> tex = gpu->wrapRenderableBackendTexture(backendTex, 0,
                                                              kBorrow_GrWrapOwnership);
     REPORTER_ASSERT(reporter, tex);
 
@@ -129,39 +115,24 @@
     GrVkImageInfo backendCopy = *imageInfo;
     backendCopy.fImage = VK_NULL_HANDLE;
     backendTex = GrBackendTexture(kW, kH, backendCopy);
-    tex = gpu->wrapRenderableBackendTexture(backendTex,
-                                            kTopLeft_GrSurfaceOrigin,
-                                            0,
-                                            kBorrow_GrWrapOwnership);
+    tex = gpu->wrapRenderableBackendTexture(backendTex, 0, kBorrow_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
-    tex = gpu->wrapRenderableBackendTexture(backendTex,
-                                            kTopLeft_GrSurfaceOrigin,
-                                            0,
-                                            kAdopt_GrWrapOwnership);
+    tex = gpu->wrapRenderableBackendTexture(backendTex, 0, kAdopt_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
 
     // alloc is null
     backendCopy.fImage = imageInfo->fImage;
     backendCopy.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
     backendTex = GrBackendTexture(kW, kH, backendCopy);
-    tex = gpu->wrapRenderableBackendTexture(backendTex,
-                                            kTopLeft_GrSurfaceOrigin,
-                                            0,
-                                            kBorrow_GrWrapOwnership);
+    tex = gpu->wrapRenderableBackendTexture(backendTex, 0, kBorrow_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
-    tex = gpu->wrapRenderableBackendTexture(backendTex,
-                                            kTopLeft_GrSurfaceOrigin,
-                                            0,
-                                            kAdopt_GrWrapOwnership);
+    tex = gpu->wrapRenderableBackendTexture(backendTex, 0, kAdopt_GrWrapOwnership);
     REPORTER_ASSERT(reporter, !tex);
 
     // check adopt creation
     backendCopy.fAlloc = imageInfo->fAlloc;
     backendTex = GrBackendTexture(kW, kH, backendCopy);
-    tex = gpu->wrapRenderableBackendTexture(backendTex,
-                                            kTopLeft_GrSurfaceOrigin,
-                                            0,
-                                            kAdopt_GrWrapOwnership);
+    tex = gpu->wrapRenderableBackendTexture(backendTex, 0, kAdopt_GrWrapOwnership);
     REPORTER_ASSERT(reporter, tex);
 
     gpu->deleteTestingOnlyBackendTexture(backendObj, true);