Make GM render to render targets that are also textures.
Review URL: https://codereview.chromium.org/13211002

git-svn-id: http://skia.googlecode.com/svn/trunk@8438 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 55e1c2a..7150452 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -50,7 +50,6 @@
 
 #if SK_SUPPORT_GPU
 #include "GrContextFactory.h"
-#include "GrRenderTarget.h"
 #include "SkGpuDevice.h"
 typedef GrContextFactory::GLContextType GLContextType;
 #define DEFAULT_CACHE_VALUE -1
@@ -59,7 +58,7 @@
 #else
 class GrContextFactory;
 class GrContext;
-class GrRenderTarget;
+class GrSurface;
 typedef int GLContextType;
 #endif
 
@@ -373,8 +372,7 @@
     }
 
     static ErrorCombination generate_image(GM* gm, const ConfigData& gRec,
-                                           GrContext* context,
-                                           GrRenderTarget* rt,
+                                           GrSurface* gpuTarget,
                                            SkBitmap* bitmap,
                                            bool deferred) {
         SkISize size (gm->getISize());
@@ -394,10 +392,7 @@
         }
 #if SK_SUPPORT_GPU
         else {  // GPU
-            if (NULL == context) {
-                return ErrorCombination(kNoGpuContext_ErrorType);
-            }
-            SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, rt));
+            SkAutoTUnref<SkDevice> device(SkGpuDevice::Create(gpuTarget));
             if (deferred) {
                 canvas.reset(new SkDeferredCanvas(device));
             } else {
@@ -826,15 +821,14 @@
     ErrorCombination test_drawing(GM* gm,
                                   const ConfigData& gRec,
                                   const char writePath [],
-                                  GrContext* context,
-                                  GrRenderTarget* rt,
+                                  GrSurface* gpuTarget,
                                   SkBitmap* bitmap) {
         SkDynamicMemoryWStream document;
 
         if (gRec.fBackend == kRaster_Backend ||
             gRec.fBackend == kGPU_Backend) {
             // Early exit if we can't generate the image.
-            ErrorCombination errors = generate_image(gm, gRec, context, rt, bitmap, false);
+            ErrorCombination errors = generate_image(gm, gRec, gpuTarget, bitmap, false);
             if (!errors.isEmpty()) {
                 // TODO: Add a test to exercise what the stdout and
                 // JSON look like if we get an "early error" while
@@ -858,8 +852,7 @@
     ErrorCombination test_deferred_drawing(GM* gm,
                                            const ConfigData& gRec,
                                            const SkBitmap& referenceBitmap,
-                                           GrContext* context,
-                                           GrRenderTarget* rt) {
+                                           GrSurface* gpuTarget) {
         SkDynamicMemoryWStream document;
 
         if (gRec.fBackend == kRaster_Backend ||
@@ -867,7 +860,7 @@
             SkBitmap bitmap;
             // Early exit if we can't generate the image, but this is
             // expected in some cases, so don't report a test failure.
-            ErrorCombination errors = generate_image(gm, gRec, context, rt, &bitmap, true);
+            ErrorCombination errors = generate_image(gm, gRec, gpuTarget, &bitmap, true);
             // TODO(epoger): This logic is the opposite of what is
             // described above... if we succeeded in generating the
             // -deferred image, we exit early!  We should fix this
@@ -1183,9 +1176,9 @@
         // Now we know that we want to run this test and record its
         // success or failure.
         ErrorCombination errorsForThisConfig;
-        GrRenderTarget* renderTarget = NULL;
+        GrSurface* gpuTarget = NULL;
 #if SK_SUPPORT_GPU
-        SkAutoTUnref<GrRenderTarget> rt;
+        SkAutoTUnref<GrSurface> auGpuTarget;
         AutoResetGr autogr;
         if ((errorsForThisConfig.isEmpty()) && (kGPU_Backend == config.fBackend)) {
             GrContext* gr = grFactory->get(config.fGLContextType);
@@ -1198,26 +1191,23 @@
                 desc.fWidth = gm->getISize().width();
                 desc.fHeight = gm->getISize().height();
                 desc.fSampleCnt = config.fSampleCnt;
-                GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0);
-                if (tex) {
-                    rt.reset(tex->asRenderTarget());
-                    rt.get()->ref();
-                    tex->unref();
+                auGpuTarget.reset(gr->createUncachedTexture(desc, NULL, 0));
+                if (NULL != auGpuTarget) {
+                    gpuTarget = auGpuTarget;
+                    grSuccess = true;
                     autogr.set(gr);
-                    renderTarget = rt.get();
-                    grSuccess = NULL != renderTarget;
+                    // Set the user specified cache limits if non-default.
+                    size_t bytes;
+                    int count;
+                    gr->getTextureCacheLimits(&count, &bytes);
+                    if (DEFAULT_CACHE_VALUE != gGpuCacheSizeBytes) {
+                        bytes = static_cast<size_t>(gGpuCacheSizeBytes);
+                    }
+                    if (DEFAULT_CACHE_VALUE != gGpuCacheSizeCount) {
+                        count = gGpuCacheSizeCount;
+                    }
+                    gr->setTextureCacheLimits(count, bytes);
                 }
-                // Set the user specified cache limits if non-default.
-                size_t bytes;
-                int count;
-                gr->getTextureCacheLimits(&count, &bytes);
-                if (DEFAULT_CACHE_VALUE != gGpuCacheSizeBytes) {
-                    bytes = static_cast<size_t>(gGpuCacheSizeBytes);
-                }
-                if (DEFAULT_CACHE_VALUE != gGpuCacheSizeCount) {
-                    count = gGpuCacheSizeCount;
-                }
-                gr->setTextureCacheLimits(count, bytes);
             }
             if (!grSuccess) {
                 errorsForThisConfig.add(kNoGpuContext_ErrorType);
@@ -1234,14 +1224,14 @@
             writePath = NULL;
         }
         if (errorsForThisConfig.isEmpty()) {
-            errorsForThisConfig.add(gmmain.test_drawing(gm, config, writePath, GetGr(),
-                                                        renderTarget, &comparisonBitmap));
+            errorsForThisConfig.add(gmmain.test_drawing(gm,config, writePath, gpuTarget,
+                                                        &comparisonBitmap));
         }
 
         if (FLAGS_deferred && errorsForThisConfig.isEmpty() &&
             (kGPU_Backend == config.fBackend || kRaster_Backend == config.fBackend)) {
             errorsForThisConfig.add(gmmain.test_deferred_drawing(gm, config, comparisonBitmap,
-                                                                 GetGr(), renderTarget));
+                                                                 gpuTarget));
         }
 
         errorsForAllConfigs.add(errorsForThisConfig);
@@ -1595,8 +1585,7 @@
         SkBitmap comparisonBitmap;
         const ConfigData compareConfig =
             { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "comparison", false };
-        testErrors.add(gmmain.generate_image(
-            gm, compareConfig, NULL, NULL, &comparisonBitmap, false));
+        testErrors.add(gmmain.generate_image(gm, compareConfig, NULL, &comparisonBitmap, false));
 
         // TODO(epoger): only run this if gmmain.generate_image() succeeded?
         // Otherwise, what are we comparing against?
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index a6087c8..8aa7d4a 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -27,16 +27,24 @@
  */
 class SK_API SkGpuDevice : public SkDevice {
 public:
+
+    /**
+     * Creates an SkGpuDevice from a GrSurface. This will fail if the surface is not a render
+     * target. The caller owns a ref on the returned device.
+     */
+    static SkGpuDevice* Create(GrSurface* surface);
+
     /**
      *  New device that will create an offscreen renderTarget based on the
      *  config, width, height, and sampleCount. The device's storage will not
      *  count against the GrContext's texture cache budget. The device's pixels
-     *  will be uninitialized.
+     *  will be uninitialized. TODO: This can fail, replace with a factory function.
      */
     SkGpuDevice(GrContext*, SkBitmap::Config, int width, int height, int sampleCount = 0);
 
     /**
      *  New device that will render to the specified renderTarget.
+     *  DEPRECATED: Use Create(surface)
      */
     SkGpuDevice(GrContext*, GrRenderTarget*);
 
@@ -44,6 +52,7 @@
      *  New device that will render to the texture (as a rendertarget).
      *  The GrTexture's asRenderTarget() must be non-NULL or device will not
      *  function.
+     *  DEPRECATED: Use Create(surface)
      */
     SkGpuDevice(GrContext*, GrTexture*);
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index aca3ba6..49d6562 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -167,6 +167,18 @@
     return bitmap;
 }
 
+SkGpuDevice* SkGpuDevice::Create(GrSurface* surface) {
+    GrAssert(NULL != surface);
+    if (NULL == surface->asRenderTarget() || NULL == surface->getContext()) {
+        return NULL;
+    }
+    if (surface->asTexture()) {
+        return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asTexture()));
+    } else {
+        return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asRenderTarget()));
+    }
+}
+
 SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture)
 : SkDevice(make_bitmap(context, texture->asRenderTarget())) {
     this->initFromRenderTarget(context, texture->asRenderTarget(), false);