Move draw on upload decision in GrGpu
authorbsalomon <bsalomon@google.com>
Tue, 28 Jul 2015 20:26:15 +0000 (13:26 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 28 Jul 2015 20:26:16 +0000 (13:26 -0700)
BUG=skia:

Committed: https://skia.googlesource.com/skia/+/0341b4427e5f037e3b501ed6e57dfdb7b40f150e

Review URL: https://codereview.chromium.org/1257073003

src/gpu/GrContext.cpp
src/gpu/GrGpu.cpp
src/gpu/GrGpu.h
src/gpu/GrTest.cpp
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLGpu.h
tests/WritePixelsTest.cpp

index 1db2cbe..9077bc0 100755 (executable)
@@ -329,76 +329,111 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
                                    GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
                                    uint32_t pixelOpsFlags) {
     RETURN_FALSE_IF_ABANDONED
-    {
-        GrTexture* texture = NULL;
-        if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asTexture()) &&
-            fGpu->canWriteTexturePixels(texture, srcConfig) &&
-            (!fCaps->useDrawInsteadOfPartialRenderTargetWrite() || !surface->asRenderTarget() ||
-              (width == texture->width() && height == texture->height()))) {
-
-            if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
-                surface->surfacePriv().hasPendingIO()) {
-                this->flush();
-            }
-            return fGpu->writeTexturePixels(texture, left, top, width, height,
-                                            srcConfig, buffer, rowBytes);
-            // Don't need to check kFlushWrites_PixelOp here, we just did a direct write so the
-            // upload is already flushed.
-        }
-    }
 
     // Trim the params here so that if we wind up making a temporary surface it can be as small as
-    // necessary.
+    // necessary and because GrGpu::getWritePixelsInfo requires it.
     if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
                                                GrBytesPerPixel(srcConfig), &left, &top, &width,
                                                &height, &buffer, &rowBytes)) {
         return false;
     }
 
-    // If we didn't do a direct texture write then we upload the pixels to a texture and draw.
-    GrRenderTarget* renderTarget = surface->asRenderTarget();
-    if (!renderTarget) {
+    bool applyPremulToSrc = false;
+    if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
+        if (!GrPixelConfigIs8888(srcConfig)) {
+            return false;
+        }
+        applyPremulToSrc = true;
+    }
+    GrGpu::DrawPreference drawPreference = applyPremulToSrc ?
+                                            GrGpu::kCallerPrefersDraw_DrawPreference :
+                                            GrGpu::kNoDraw_DrawPreference;
+    GrGpu::WritePixelTempDrawInfo tempDrawInfo;
+    if (!fGpu->getWritePixelsInfo(surface, width, height, rowBytes, srcConfig, &drawPreference,
+                                  &tempDrawInfo)) {
         return false;
     }
 
-    // We ignore the preferred config unless it is a R/B swap of the src config. In that case
-    // we will upload the original src data to a scratch texture but we will spoof it as the swapped
-    // config. This scratch will then have R and B swapped. We correct for this by swapping again
-    // when drawing the scratch to the dst using a conversion effect.
-    bool swapRAndB = false;
-    GrPixelConfig writeConfig = srcConfig;
-    if (GrPixelConfigSwapRAndB(srcConfig) ==
-        fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
-        writeConfig = GrPixelConfigSwapRAndB(srcConfig);
-        swapRAndB = true;
-    }
-
-    GrSurfaceDesc desc;
-    desc.fWidth = width;
-    desc.fHeight = height;
-    desc.fConfig = writeConfig;
-    SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(desc,
-        GrTextureProvider::kApprox_ScratchTexMatch));
-    if (!texture) {
-        return false;
+    if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
+        this->flush();
     }
 
-    SkAutoTUnref<const GrFragmentProcessor> fp;
-    SkMatrix textureMatrix;
-    textureMatrix.setIDiv(texture->width(), texture->height());
+    SkAutoTUnref<GrTexture> tempTexture;
+    if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
+        tempTexture.reset(this->textureProvider()->refScratchTexture(
+            tempDrawInfo.fTempSurfaceDesc, GrTextureProvider::kApprox_ScratchTexMatch));
+        if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
+            return false;
+        }
+    }
 
-    // allocate a tmp buffer and sw convert the pixels to premul
+    // temp buffer for doing sw premul conversion, if needed.
     SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
+    if (tempTexture) {
+        SkAutoTUnref<const GrFragmentProcessor> fp;
+        SkMatrix textureMatrix;
+        textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
+        GrPaint paint;
+        if (applyPremulToSrc) {
+            fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(), tempTexture,
+                                               tempDrawInfo.fSwapRAndB, textureMatrix));
+            // If premultiplying was the only reason for the draw, fall back to a straight write.
+            if (!fp) {
+                if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
+                    tempTexture.reset(NULL);
+                }
+            } else {
+                applyPremulToSrc = false;
+            }
+        }
+        if (tempTexture) {
+            if (!fp) {
+                fp.reset(GrConfigConversionEffect::Create(
+                    paint.getProcessorDataManager(), tempTexture, tempDrawInfo.fSwapRAndB,
+                    GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
+                if (!fp) {
+                    return false;
+                }
+            }
+            GrRenderTarget* renderTarget = surface->asRenderTarget();
+            SkASSERT(renderTarget);
+            if (tempTexture->surfacePriv().hasPendingIO()) {
+                this->flush();
+            }
+            if (applyPremulToSrc) {
+                size_t tmpRowBytes = 4 * width;
+                tmpPixels.reset(width * height);
+                if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
+                                          tmpPixels.get())) {
+                    return false;
+                }
+                rowBytes = tmpRowBytes;
+                buffer = tmpPixels.get();
+                applyPremulToSrc = false;
+            }
+            if (!fGpu->writeTexturePixels(tempTexture, 0, 0, width, height,
+                                          tempDrawInfo.fTempSurfaceDesc.fConfig, buffer,
+                                          rowBytes)) {
+                return false;
+            }
+            SkMatrix matrix;
+            matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
+            GrDrawContext* drawContext = this->drawContext();
+            if (!drawContext) {
+                return false;
+            }
+            paint.addColorProcessor(fp);
+            SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+            drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
 
-    GrPaint paint;
-    if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
-        if (!GrPixelConfigIs8888(srcConfig)) {
-            return false;
+            if (kFlushWrites_PixelOp & pixelOpsFlags) {
+                this->flushSurfaceWrites(surface);
+            }
         }
-        fp.reset(this->createUPMToPMEffect(paint.getProcessorDataManager(), texture, swapRAndB,
-                                           textureMatrix));
-        // handle the unpremul step on the CPU if we couldn't create an effect to do it.
-        if (!fp) {
+    }
+    if (!tempTexture) {
+        SkASSERT(surface->asTexture());
+        if (applyPremulToSrc) {
             size_t tmpRowBytes = 4 * width;
             tmpPixels.reset(width * height);
             if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
@@ -407,46 +442,11 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
             }
             rowBytes = tmpRowBytes;
             buffer = tmpPixels.get();
+            applyPremulToSrc = false;
         }
+        return fGpu->writeTexturePixels(surface->asTexture(), left, top, width, height, srcConfig,
+                                        buffer, rowBytes);
     }
-
-    if (!fp) {
-        fp.reset(GrConfigConversionEffect::Create(paint.getProcessorDataManager(),
-                                                  texture,
-                                                  swapRAndB,
-                                                  GrConfigConversionEffect::kNone_PMConversion,
-                                                  textureMatrix));
-    }
-
-    // Even if the client told us not to flush, we still flush here. The client may have known that
-    // writes to the original surface caused no data hazards, but they can't know that the scratch
-    // we just got is safe.
-    if (texture->surfacePriv().hasPendingIO()) {
-        this->flush();
-    }
-    if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
-                                  writeConfig, buffer, rowBytes)) {
-        return false;
-    }
-
-    SkMatrix matrix;
-    matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
-
-    GrDrawContext* drawContext = this->drawContext();
-    if (!drawContext) {
-        return false;
-    }
-
-    paint.addColorProcessor(fp);
-
-    SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
-
-    drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
-
-    if (kFlushWrites_PixelOp & pixelOpsFlags) {
-        this->flushSurfaceWrites(surface);
-    }
-
     return true;
 }
 
index 728fb88..c61979b 100644 (file)
@@ -232,6 +232,61 @@ void GrGpu::clearStencilClip(const SkIRect& rect,
     this->onClearStencilClip(renderTarget, rect, insideClip);
 }
 
+bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
+                              GrPixelConfig readConfig, DrawPreference* drawPreference,
+                              ReadPixelTempDrawInfo* tempDrawInfo) {
+    SkASSERT(drawPreference);
+    SkASSERT(tempDrawInfo);
+    SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
+
+    if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference,
+                                   tempDrawInfo)) {
+        return false;
+    }
+
+    // Check to see if we're going to request that the caller draw when drawing is not possible.
+    if (!srcSurface->asTexture() ||
+        !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig, false)) {
+        // If we don't have a fallback to a straight read then fail.
+        if (kRequireDraw_DrawPreference == *drawPreference) {
+            return false;
+        }
+        *drawPreference = kNoDraw_DrawPreference;
+    }
+
+    return true;
+}
+bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
+                               GrPixelConfig srcConfig, DrawPreference* drawPreference,
+                               WritePixelTempDrawInfo* tempDrawInfo) {
+    SkASSERT(drawPreference);
+    SkASSERT(tempDrawInfo);
+    SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
+
+    if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() &&
+        SkToBool(dstSurface->asRenderTarget()) &&
+        (width < dstSurface->width() || height < dstSurface->height())) {
+        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+    }
+
+    if (!this->onGetWritePixelsInfo(dstSurface, width, height, rowBytes, srcConfig, drawPreference,
+                                    tempDrawInfo)) {
+        return false;
+    }
+
+    // Check to see if we're going to request that the caller draw when drawing is not possible.
+    if (!dstSurface->asRenderTarget() ||
+        !this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
+        // If we don't have a fallback to a straight upload then fail.
+        if (kRequireDraw_DrawPreference == *drawPreference ||
+            !this->caps()->isConfigTexturable(srcConfig)) {
+            return false;
+        }
+        *drawPreference = kNoDraw_DrawPreference;
+    }
+    return true;
+}
+
 bool GrGpu::readPixels(GrRenderTarget* target,
                        int left, int top, int width, int height,
                        GrPixelConfig config, void* buffer,
index 857efd0..8bb676d 100644 (file)
@@ -133,7 +133,7 @@ public:
      */
     void resolveRenderTarget(GrRenderTarget* target);
 
-    /** Info struct returned by getReadPixelsInfo about performing intermediate draws before 
+    /** Info struct returned by getReadPixelsInfo about performing intermediate draws before
         reading pixels for performance or correctness. */
     struct ReadPixelTempDrawInfo {
         /** If the GrGpu is requesting that the caller do a draw to an intermediate surface then
@@ -173,28 +173,39 @@ public:
         kRequireDraw_DrawPreference
     };
 
-    /** Used to negotiates whether and how an intermediate draw should or must be performed before
-        a readPixels call. If this returns false then GrGpu could not deduce an intermediate draw
-        that would allow a successful readPixels call. */
-    virtual bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight,
-                                   size_t rowBytes, GrPixelConfig readConfig, DrawPreference*,
-                                   ReadPixelTempDrawInfo *) = 0;
-
     /**
-     * Gets a preferred 8888 config to use for writing pixel data to a surface with
-     * config surfaceConfig. The returned config must have at least as many bits per channel as the
-     * writeConfig param.
+     * Used to negotiate whether and how an intermediate draw should or must be performed before
+     * a readPixels call. If this returns false then GrGpu could not deduce an intermediate draw
+     * 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.
      */
-    virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig,
-                                                     GrPixelConfig surfaceConfig) const {
-        return writeConfig;
-    }
+    bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+                           GrPixelConfig readConfig, DrawPreference*, ReadPixelTempDrawInfo*);
+
+    /** Info struct returned by getWritePixelsInfo about performing an intermediate draw in order 
+        to write pixels to a GrSurface for either performance or correctness reasons. */
+    struct WritePixelTempDrawInfo {
+        /** If the GrGpu is requesting that the caller upload to an intermediate surface and draw
+            that to the dst then this is the descriptor for the intermediate surface. The caller
+            should upload the pixels such that the upper left pixel of the upload rect is at 0,0 in
+            the intermediate surface.*/
+        GrSurfaceDesc   fTempSurfaceDesc;
+        /** If set, fTempSurfaceDesc's config will be a R/B swap of the src pixel config. The caller
+            should upload the pixels as is such that R and B will be swapped in the intermediate
+            surface. When the intermediate is drawn to the dst the shader should swap R/B again
+            such that the correct swizzle results in the dst. This is done to work around either
+            performance or API restrictions in the backend 3D API implementation. */
+        bool            fSwapRAndB;
+    };
 
     /**
-     * Called before uploading writing pixels to a GrTexture when the src pixel config doesn't
-     * match the texture's config.
+     * Used to negotiate whether and how an intermediate surface should be used to write pixels to
+     * a GrSurface. If this returns false then GrGpu could not deduce an intermediate draw
+     * 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.
      */
-    virtual bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const = 0;
+    bool getWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
+                            GrPixelConfig srcConfig, DrawPreference*, WritePixelTempDrawInfo*);
 
     /**
      * Reads a rectangle of pixels from a render target.
@@ -401,6 +412,16 @@ protected:
                                           unsigned int* ref,
                                           unsigned int* mask);
 
+    static void ElevateDrawPreference(GrGpu::DrawPreference* preference,
+                                      GrGpu::DrawPreference elevation) {
+        GR_STATIC_ASSERT(GrGpu::kCallerPrefersDraw_DrawPreference > GrGpu::kNoDraw_DrawPreference);
+        GR_STATIC_ASSERT(GrGpu::kGpuPrefersDraw_DrawPreference >
+                         GrGpu::kCallerPrefersDraw_DrawPreference);
+        GR_STATIC_ASSERT(GrGpu::kRequireDraw_DrawPreference >
+                         GrGpu::kGpuPrefersDraw_DrawPreference);
+        *preference = SkTMax(*preference, elevation);
+    }
+
     const GrTraceMarkerSet& getActiveTraceMarkers() const { return fActiveTraceMarkers; }
 
     Stats                                   fStats;
@@ -440,6 +461,13 @@ private:
     // overridden by backend-specific derived class to perform the draw call.
     virtual void onDraw(const DrawArgs&, const GrNonInstancedVertices&) = 0;
 
+    virtual bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight,
+                                     size_t rowBytes, GrPixelConfig readConfig, DrawPreference*,
+                                     ReadPixelTempDrawInfo*) = 0;
+    virtual bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
+                                      GrPixelConfig srcConfig, DrawPreference*,
+                                      WritePixelTempDrawInfo*) = 0;
+
     virtual bool onReadPixels(GrRenderTarget* target,
                               int left, int top, int width, int height,
                               GrPixelConfig,
index c6902d0..fd2908e 100644 (file)
@@ -146,13 +146,14 @@ public:
         fCaps.reset(SkNEW_ARGS(GrCaps, (options)));
     }
     ~MockGpu() override {}
-    bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const override {
-        return true;
-    }
 
-    bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
-                           GrPixelConfig readConfig, DrawPreference*,
-                           ReadPixelTempDrawInfo*) override { return false; }
+    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+                             GrPixelConfig readConfig, DrawPreference*,
+                             ReadPixelTempDrawInfo*) override { return false; }
+
+    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, size_t rowBytes,
+                              GrPixelConfig srcConfig, DrawPreference*,
+                              WritePixelTempDrawInfo*) override { return false; }
 
     void buildProgramDesc(GrProgramDesc*,const GrPrimitiveProcessor&,
                           const GrPipeline&,
index 101bb21..41cf62c 100644 (file)
@@ -268,38 +268,6 @@ void GrGLGpu::contextAbandoned() {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrPixelConfig GrGLGpu::preferredWritePixelsConfig(GrPixelConfig writeConfig,
-                                                  GrPixelConfig surfaceConfig) const {
-    if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == writeConfig) {
-        return kBGRA_8888_GrPixelConfig;
-    } else {
-        return writeConfig;
-    }
-}
-
-bool GrGLGpu::canWriteTexturePixels(const GrTexture* texture, GrPixelConfig srcConfig) const {
-    if (kIndex_8_GrPixelConfig == srcConfig || kIndex_8_GrPixelConfig == texture->config()) {
-        return false;
-    }
-    if (srcConfig != texture->config() && kGLES_GrGLStandard == this->glStandard()) {
-        // In general ES2 requires the internal format of the texture and the format of the src
-        // pixels to match. However, It may or may not be possible to upload BGRA data to a RGBA
-        // texture. It depends upon which extension added BGRA. The Apple extension allows it
-        // (BGRA's internal format is RGBA) while the EXT extension does not (BGRA is its own
-        // internal format).
-        if (this->glCaps().isConfigTexturable(kBGRA_8888_GrPixelConfig) &&
-            !this->glCaps().bgraIsInternalFormat() &&
-            kBGRA_8888_GrPixelConfig == srcConfig &&
-            kRGBA_8888_GrPixelConfig == texture->config()) {
-            return true;
-        } else {
-            return false;
-        }
-    } else {
-        return true;
-    }
-}
-
 void GrGLGpu::onResetContext(uint32_t resetBits) {
     // we don't use the zb at all
     if (resetBits & kMisc_GrGLBackendState) {
@@ -537,6 +505,53 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+                                   size_t rowBytes, GrPixelConfig srcConfig,
+                                   DrawPreference* drawPreference,
+                                   WritePixelTempDrawInfo* tempDrawInfo) {
+    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
+        return false;
+    }
+
+    tempDrawInfo->fSwapRAndB = false;
+
+    // These settings we will always want if a temp draw is performed. Initially set the config
+    // to srcConfig, though that may be modified if we decide to do a R/G swap.
+    tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
+    tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
+    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
+    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
+    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
+    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
+
+    bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
+
+    if (configsAreRBSwaps) {
+        if (!this->caps()->isConfigTexturable(srcConfig)) {
+            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+            tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
+            tempDrawInfo->fSwapRAndB = true;
+        } else if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == srcConfig) {
+            ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
+            tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
+            tempDrawInfo->fSwapRAndB = true;
+        } else if (kGLES_GrGLStandard == this->glStandard() &&
+                   this->glCaps().bgraIsInternalFormat()) {
+            // The internal format and external formats must match texture uploads so we can't
+            // swizzle while uploading when BGRA is a distinct internal format.
+            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+            tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
+            tempDrawInfo->fSwapRAndB = true;
+        }
+    }
+
+    if (!this->glCaps().unpackFlipYSupport() &&
+        kBottomLeft_GrSurfaceOrigin == dstSurface->origin()) {
+        ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
+    }
+
+    return true;
+}
 
 bool GrGLGpu::onWriteTexturePixels(GrTexture* texture,
                                    int left, int top, int width, int height,
@@ -1704,21 +1719,9 @@ static bool read_pixels_pays_for_y_flip(GrRenderTarget* renderTarget, const GrGL
     return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes;
 }
 
-void elevate_draw_preference(GrGpu::DrawPreference* preference, GrGpu::DrawPreference elevation) {
-    GR_STATIC_ASSERT(GrGpu::kCallerPrefersDraw_DrawPreference > GrGpu::kNoDraw_DrawPreference);
-    GR_STATIC_ASSERT(GrGpu::kGpuPrefersDraw_DrawPreference >
-                     GrGpu::kCallerPrefersDraw_DrawPreference);
-    GR_STATIC_ASSERT(GrGpu::kRequireDraw_DrawPreference > GrGpu::kGpuPrefersDraw_DrawPreference);
-    *preference = SkTMax(*preference, elevation);
-}
-
-bool GrGLGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
-                                GrPixelConfig readConfig, DrawPreference* drawPreference,
-                                ReadPixelTempDrawInfo* tempDrawInfo) {
-    SkASSERT(drawPreference);
-    SkASSERT(tempDrawInfo);
-    SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
-
+bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
+                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
+                                  ReadPixelTempDrawInfo* tempDrawInfo) {
     if (GrPixelConfigIsCompressed(readConfig)) {
         return false;
     }
@@ -1750,26 +1753,23 @@ bool GrGLGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, si
         // Better to do a draw with a R/B swap and then read as the original config.
         tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
         tempDrawInfo->fSwapRAndB = true;
-        elevate_draw_preference(drawPreference, kGpuPrefersDraw_DrawPreference);
+        ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
     } else if (readConfig == kBGRA_8888_GrPixelConfig &&
                !this->glCaps().readPixelsSupported(this->glInterface(), GR_GL_BGRA,
                                                    GR_GL_UNSIGNED_BYTE, srcConfig)) {
         tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
         tempDrawInfo->fSwapRAndB = true;
-        elevate_draw_preference(drawPreference, kRequireDraw_DrawPreference);
+        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
     }
 
     GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
     if (!srcAsRT) {
-        elevate_draw_preference(drawPreference, kRequireDraw_DrawPreference);
+        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
     } else if (read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig,
                                            rowBytes)) {
-        elevate_draw_preference(drawPreference, kGpuPrefersDraw_DrawPreference);
+        ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
     }
 
-    if (kRequireDraw_DrawPreference == *drawPreference && !srcSurface->asTexture()) {
-        return false;
-    }
     return true;
 }
 
index 066a237..0442e11 100644 (file)
@@ -57,15 +57,13 @@ public:
     // Used by GrGLProgram to configure OpenGL state.
     void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
 
-    bool getReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
-                           GrPixelConfig readConfig, DrawPreference*,
-                           ReadPixelTempDrawInfo*) override;
+    bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
+                             GrPixelConfig readConfig, DrawPreference*,
+                             ReadPixelTempDrawInfo*) override;
 
-
-    // GrGpu overrides
-    GrPixelConfig preferredWritePixelsConfig(GrPixelConfig writeConfig,
-                                             GrPixelConfig surfaceConfig) const override;
-    bool canWriteTexturePixels(const GrTexture*, GrPixelConfig srcConfig) const override;
+    bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
+                              size_t rowBytes, GrPixelConfig srcConfig, DrawPreference*,
+                              WritePixelTempDrawInfo*) override;
 
     bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const override;
 
index fa99d4c..a06130e 100644 (file)
@@ -27,7 +27,7 @@ static const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1,
                                                 DEV_H * SK_Scalar1);
 static const U8CPU DEV_PAD = 0xee;
 
-static SkPMColor getCanvasColor(int x, int y) {
+static SkPMColor get_canvas_color(int x, int y) {
     SkASSERT(x >= 0 && x < DEV_W);
     SkASSERT(y >= 0 && y < DEV_H);
 
@@ -57,7 +57,7 @@ static SkPMColor getCanvasColor(int x, int y) {
 }
 
 // assumes any premu/.unpremul has been applied
-static uint32_t packColorType(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+static uint32_t pack_color_type(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     uint32_t r32;
     uint8_t* result = reinterpret_cast<uint8_t*>(&r32);
     switch (ct) {
@@ -80,7 +80,7 @@ static uint32_t packColorType(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b
     return r32;
 }
 
-static uint32_t getBitmapColor(int x, int y, int w, SkColorType ct, SkAlphaType at) {
+static uint32_t get_bitmap_color(int x, int y, int w, SkColorType ct, SkAlphaType at) {
     int n = y * w + x;
     U8CPU b = n & 0xff;
     U8CPU g = (n >> 8) & 0xff;
@@ -108,16 +108,16 @@ static uint32_t getBitmapColor(int x, int y, int w, SkColorType ct, SkAlphaType
         g = SkMulDiv255Ceiling(g, a);
         b = SkMulDiv255Ceiling(b, a);
     }
-    return packColorType(ct, a, r, g , b);
+    return pack_color_type(ct, a, r, g , b);
 }
 
-static void fillCanvas(SkCanvas* canvas) {
+static void fill_canvas(SkCanvas* canvas) {
     SkBitmap bmp;
     if (bmp.isNull()) {
         bmp.allocN32Pixels(DEV_W, DEV_H);
         for (int y = 0; y < DEV_H; ++y) {
             for (int x = 0; x < DEV_W; ++x) {
-                *bmp.getAddr32(x, y) = getCanvasColor(x, y);
+                *bmp.getAddr32(x, y) = get_canvas_color(x, y);
             }
         }
     }
@@ -164,7 +164,7 @@ static SkPMColor convert_to_PMColor(SkColorType ct, SkAlphaType at, uint32_t col
     return color;
 }
 
-static bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
+static bool check_pixel(SkPMColor a, SkPMColor b, bool didPremulConversion) {
     if (!didPremulConversion) {
         return a == b;
     }
@@ -219,21 +219,21 @@ static bool check_write(skiatest::Reporter* reporter, SkCanvas* canvas, const Sk
             if (writeRect.contains(cx, cy)) {
                 int bx = cx - writeX;
                 int by = cy - writeY;
-                uint32_t bmpColor8888 = getBitmapColor(bx, by, bitmap.width(),
+                uint32_t bmpColor8888 = get_bitmap_color(bx, by, bitmap.width(),
                                                        bmInfo.colorType(), bmInfo.alphaType());
                 bool mul = (kUnpremul_SkAlphaType == bmInfo.alphaType());
                 SkPMColor bmpPMColor = convert_to_PMColor(bmInfo.colorType(), bmInfo.alphaType(),
                                                           bmpColor8888);
-                bool check = checkPixel(bmpPMColor, canvasPixel, mul);
-                REPORTER_ASSERT(reporter, check);
-                if (!check) {
+                if (!check_pixel(bmpPMColor, canvasPixel, mul)) {
+                    ERRORF(reporter, "Expected canvas pixel at %d, %d to be 0x%08x, got 0x%08x. "
+                           "Write performed premul: %d", cx, cy, bmpPMColor, canvasPixel, mul);
                     return false;
                 }
             } else {
-                bool check;
-                SkPMColor testColor = getCanvasColor(cx, cy);
-                REPORTER_ASSERT(reporter, check = (canvasPixel == testColor));
-                if (!check) {
+                SkPMColor testColor = get_canvas_color(cx, cy);
+                if (canvasPixel != testColor) {
+                    ERRORF(reporter, "Canvas pixel outside write rect at %d, %d changed."
+                           " Should be 0x%08x, got 0x%08x. ", cx, cy, testColor, canvasPixel);
                     return false;
                 }
             }
@@ -282,7 +282,7 @@ static const CanvasConfig gCanvasConfigs[] = {
 // a custom pixelRef (which also has to specify its rowBytes), so we have to be
 // sure that the two rowBytes match (and the infos match).
 //
-static bool allocRowBytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
+static bool alloc_row_bytes(SkBitmap* bm, const SkImageInfo& info, size_t rowBytes) {
     if (!bm->setInfo(info, rowBytes)) {
         return false;
     }
@@ -328,13 +328,13 @@ static SkSurface* create_surface(const CanvasConfig& c, GrContext* grCtx) {
 static bool setup_bitmap(SkBitmap* bm, SkColorType ct, SkAlphaType at, int w, int h, int tightRB) {
     size_t rowBytes = tightRB ? 0 : 4 * w + 60;
     SkImageInfo info = SkImageInfo::Make(w, h, ct, at);
-    if (!allocRowBytes(bm, info, rowBytes)) {
+    if (!alloc_row_bytes(bm, info, rowBytes)) {
         return false;
     }
     SkAutoLockPixels alp(*bm);
     for (int y = 0; y < h; ++y) {
         for (int x = 0; x < w; ++x) {
-            *bm->getAddr32(x, y) = getBitmapColor(x, y, w, ct, at);
+            *bm->getAddr32(x, y) = get_bitmap_color(x, y, w, ct, at);
         }
     }
     return true;
@@ -451,7 +451,7 @@ DEF_GPUTEST(WritePixels, reporter, factory) {
                         const SkColorType ct = gSrcConfigs[c].fColorType;
                         const SkAlphaType at = gSrcConfigs[c].fAlphaType;
 
-                        fillCanvas(&canvas);
+                        fill_canvas(&canvas);
                         SkBitmap bmp;
                         REPORTER_ASSERT(reporter, setup_bitmap(&bmp, ct, at, rect.width(),
                                                                rect.height(), SkToBool(tightBmp)));