Create GPU-less build of Skia.



git-svn-id: http://skia.googlecode.com/svn/trunk@4912 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/BenchTimer.cpp b/bench/BenchTimer.cpp
index c3a1190..8ac08a7 100644
--- a/bench/BenchTimer.cpp
+++ b/bench/BenchTimer.cpp
@@ -16,7 +16,9 @@
     #include "BenchSysTimer_c.h"
 #endif
 
+#if SK_SUPPORT_GPU
 #include "BenchGpuTimer_gl.h"
+#endif
 
 BenchTimer::BenchTimer(SkGLContext* gl)
         : fCpu(-1.0)
@@ -24,32 +26,40 @@
         , fGpu(-1.0)
 {
     fSysTimer = new BenchSysTimer();
+#if SK_SUPPORT_GPU
     if (gl) {
         fGpuTimer = new BenchGpuTimer(gl);
     } else {
         fGpuTimer = NULL;
     }
+#endif
 }
 
 BenchTimer::~BenchTimer() {
     delete fSysTimer;
+#if SK_SUPPORT_GPU
     delete fGpuTimer;
+#endif
 }
 
 void BenchTimer::start() {
     fSysTimer->startWall();
+#if SK_SUPPORT_GPU
     if (fGpuTimer) {
         fGpuTimer->startGpu();
     }
+#endif
     fSysTimer->startCpu();
 }
 
 void BenchTimer::end() {
     fCpu = fSysTimer->endCpu();
+#if SK_SUPPORT_GPU
     //It is important to stop the cpu clocks first,
     //as the following will cpu wait for the gpu to finish.
     if (fGpuTimer) {
         fGpu = fGpuTimer->endGpu();
     }
+#endif
     fWall = fSysTimer->endWall();
 }
diff --git a/bench/BenchTimer.h b/bench/BenchTimer.h
index 080bc6d..a00707c 100644
--- a/bench/BenchTimer.h
+++ b/bench/BenchTimer.h
@@ -33,7 +33,9 @@
     
 private:
     BenchSysTimer *fSysTimer;
+#if SK_SUPPORT_GPU
     BenchGpuTimer *fGpuTimer;
+#endif
 };
 
 #endif
diff --git a/bench/GrMemoryPoolBench.cpp b/bench/GrMemoryPoolBench.cpp
index 2fad7fc..98fd6e5 100644
--- a/bench/GrMemoryPoolBench.cpp
+++ b/bench/GrMemoryPoolBench.cpp
@@ -5,6 +5,9 @@
  * found in the LICENSE file.
  */
 
+// This tests a Gr class
+#if SK_SUPPORT_GPU
+
 #include "GrMemoryPool.h"
 #include "SkBenchmark.h"
 #include "SkRandom.h"
@@ -162,3 +165,4 @@
 static BenchRegistry gReg02(Fact2);
 static BenchRegistry gReg03(Fact3);
 
+#endif
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 2cff880..92889f6 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -9,22 +9,24 @@
 
 #include "BenchTimer.h"
 
+#if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrRenderTarget.h"
+#if SK_ANGLE
+#include "gl/SkANGLEGLContext.h"
+#endif // SK_ANGLE
+#include "gl/SkNativeGLContext.h"
+#include "gl/SkNullGLContext.h"
+#include "gl/SkDebugGLContext.h"
+#include "SkGpuDevice.h"
+#endif // SK_SUPPORT_GPU
 
 #include "SkBenchmark.h"
 #include "SkCanvas.h"
 #include "SkDeferredCanvas.h"
 #include "SkColorPriv.h"
-#include "SkGpuDevice.h"
 #include "SkGraphics.h"
 #include "SkImageEncoder.h"
-#if SK_ANGLE
-#include "gl/SkANGLEGLContext.h"
-#endif
-#include "gl/SkNativeGLContext.h"
-#include "gl/SkNullGLContext.h"
-#include "gl/SkDebugGLContext.h"
 #include "SkNWayCanvas.h"
 #include "SkPicture.h"
 #include "SkString.h"
@@ -187,6 +189,7 @@
     kPDF_Backend,
 };
 
+#if SK_SUPPORT_GPU
 class GLHelper {
 public:
     GLHelper() {
@@ -254,8 +257,11 @@
 static GLHelper gDebugGLHelper;
 #if SK_ANGLE
 static GLHelper gANGLEGLHelper;
-#endif
-
+#endif // SK_ANGLE
+#else  // !SK_SUPPORT_GPU
+class GLHelper;
+class SkGLContext;
+#endif // !SK_SUPPORT_GPU
 static SkDevice* make_device(SkBitmap::Config config, const SkIPoint& size,
                              Backend backend, GLHelper* glHelper) {
     SkDevice* device = NULL;
@@ -268,10 +274,12 @@
             erase(bitmap);
             device = new SkDevice(bitmap);
             break;
+#if SK_SUPPORT_GPU
         case kGPU_Backend:
             device = new SkGpuDevice(glHelper->grContext(),
                                      glHelper->renderTarget());
             break;
+#endif
         case kPDF_Backend:
         default:
             SkASSERT(!"unsupported");
@@ -287,14 +295,16 @@
 } gConfigs[] = {
     { SkBitmap::kARGB_8888_Config,  "8888",     kRaster_Backend, NULL },
     { SkBitmap::kRGB_565_Config,    "565",      kRaster_Backend, NULL },
+#if SK_SUPPORT_GPU
     { SkBitmap::kARGB_8888_Config,  "GPU",      kGPU_Backend, &gRealGLHelper },
 #if SK_ANGLE
     { SkBitmap::kARGB_8888_Config,  "ANGLE",    kGPU_Backend, &gANGLEGLHelper },
-#endif
+#endif // SK_ANGLE
 #ifdef SK_DEBUG
     { SkBitmap::kARGB_8888_Config,  "Debug",    kGPU_Backend, &gDebugGLHelper },
-#endif
+#endif // SK_DEBUG
     { SkBitmap::kARGB_8888_Config,  "NULLGPU",  kGPU_Backend, &gNullGLHelper },
+#endif // SK_SUPPORT_GPU
 };
 
 static int findConfig(const char config[]) {
@@ -370,8 +380,13 @@
              "                 record, Benchmark the time to record to an SkPicture;\n"
              "                 picturerecord, Benchmark the time to do record from a \n"
              "                                SkPicture to a SkPicture.\n");
+#if SK_SUPPORT_GPU
     SkDebugf("    -config 8888|565|GPU|ANGLE|NULLGPU : "
              "Run bench in corresponding config mode.\n");
+#else
+    SkDebugf("    -config 8888|565: "
+             "Run bench in corresponding config mode.\n");
+#endif
     SkDebugf("    -Dfoo bar : Add extra definition to bench.\n");
     SkDebugf("    -h|--help : Show this help message.\n");
 }
@@ -640,26 +655,26 @@
         log_progress(str);
     }
 
+    SkGLContext* timerCtx = NULL;
     //Don't do GL when fixed.
-#if !defined(SK_SCALAR_IS_FIXED)
+#if !defined(SK_SCALAR_IS_FIXED) && SK_SUPPORT_GPU
     int contextWidth = 1024;
     int contextHeight = 1024;
     determine_gpu_context_size(defineDict, &contextWidth, &contextHeight);
     SkAutoTUnref<SkGLContext> realGLCtx(new SkNativeGLContext);
     SkAutoTUnref<SkGLContext> nullGLCtx(new SkNullGLContext);
     SkAutoTUnref<SkGLContext> debugGLCtx(new SkDebugGLContext);
-#if SK_ANGLE
-    SkAutoTUnref<SkGLContext> angleGLCtx(new SkANGLEGLContext);
-#endif
     gRealGLHelper.init(realGLCtx.get(), contextWidth, contextHeight);
     gNullGLHelper.init(nullGLCtx.get(), contextWidth, contextHeight);
     gDebugGLHelper.init(debugGLCtx.get(), contextWidth, contextHeight);
 #if SK_ANGLE
+    SkAutoTUnref<SkGLContext> angleGLCtx(new SkANGLEGLContext);
     gANGLEGLHelper.init(angleGLCtx.get(), contextWidth, contextHeight);
-#endif
-#endif
+#endif // SK_ANGLE
+    timerCtx = gRealGLHelper.glContext();
+#endif // !defined(SK_SCALAR_IS_FIXED) && SK_SUPPORT_GPU
 
-    BenchTimer timer = BenchTimer(gRealGLHelper.glContext());
+    BenchTimer timer = BenchTimer(timerCtx);
     Iter iter(&defineDict);
     SkBenchmark* bench;
     while ((bench = iter.next()) != NULL) {
@@ -696,11 +711,12 @@
             backend = gConfigs[configIndex].fBackend;
             glHelper = gConfigs[configIndex].fGLHelper;
 
+#if SK_SUPPORT_GPU
             if (kGPU_Backend == backend &&
                 (NULL == glHelper || !glHelper->isValid())) {
                 continue;
             }
-            
+#endif
             SkDevice* device = make_device(outConfig, dim, backend, glHelper);
             SkCanvas* canvas = NULL;
             SkPicture pictureRecordFrom;
@@ -754,10 +770,12 @@
                     bench->draw(canvas);
                 }
                 canvas->flush();
+#if SK_SUPPORT_GPU
                 if (glHelper) {
                     glHelper->grContext()->flush();
                     SK_GL(*glHelper->glContext(), Finish());
                 }
+#endif
             }
 
             // record timer values for each repeat, and their sum
@@ -783,9 +801,11 @@
                     bench->draw(canvas);
                 }
                 canvas->flush();
+#if SK_SUPPORT_GPU
                 if (glHelper) {
                     glHelper->grContext()->flush();
                 }
+#endif
                 timer.end();
 
                 if (i == repeatDraw - 1) {
@@ -805,10 +825,11 @@
                 fCpuSum += timer.fCpu;
                 fGpuSum += timer.fGpu;
             }
+#if SK_SUPPORT_GPU
            if (glHelper) {
                 SK_GL(*glHelper->glContext(), Finish());
            }
-
+#endif
             if (repeatDraw > 1) {
                 // output each repeat (no average) if logPerIter is set,
                 // otherwise output only the average
@@ -840,9 +861,9 @@
         }
         log_progress("\n");
     }
-
+#if SK_SUPPORT_GPU
     // need to clean up here rather than post-main to allow leak detection to work
     gDebugGLHelper.cleanup();
-
+#endif
     return 0;
 }
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index ba8c590..4cebe7f 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -7,15 +7,11 @@
 
 #include "gm.h"
 #include "system_preferences.h"
-#include "GrContextFactory.h"
-#include "GrRenderTarget.h"
 #include "SkColorPriv.h"
 #include "SkData.h"
 #include "SkDeferredCanvas.h"
 #include "SkDevice.h"
 #include "SkGPipe.h"
-#include "SkGpuCanvas.h"
-#include "SkGpuDevice.h"
 #include "SkGraphics.h"
 #include "SkImageDecoder.h"
 #include "SkImageEncoder.h"
@@ -24,6 +20,18 @@
 #include "SkStream.h"
 #include "SamplePipeControllers.h"
 
+#if SK_SUPPORT_GPU
+#include "GrContextFactory.h"
+#include "GrRenderTarget.h"
+#include "SkGpuDevice.h"
+#include "SkGpuCanvas.h"
+typedef GrContextFactory::GLContextType GLContextType;
+#else
+class GrContext;
+class GrRenderTarget;
+typedef int GLContextType;
+#endif
+
 static bool gForceBWtext;
 
 extern bool gSkSuppressFontCachePurgeSpew;
@@ -242,7 +250,7 @@
 struct ConfigData {
     SkBitmap::Config                fConfig;
     Backend                         fBackend;
-    GrContextFactory::GLContextType fGLContextType; // GPU backend only
+    GLContextType                   fGLContextType; // GPU backend only
     int                             fSampleCnt;     // GPU backend only
     ConfigFlags                     fFlags;
     const char*                     fName;
@@ -308,7 +316,9 @@
         SkAutoUnref canvasUnref(canvas);
         invokeGM(gm, canvas);
         canvas->flush();
-    } else {  // GPU
+    }
+#if SK_SUPPORT_GPU
+    else {  // GPU
         if (NULL == context) {
             return ERROR_NO_GPU_CONTEXT;
         }
@@ -328,6 +338,7 @@
                                                        size.fHeight);
         gc->readPixels(bitmap, 0, 0);
     }
+#endif
     return ERROR_NONE;
 }
 
@@ -711,8 +722,11 @@
     }
 }
 
-static const GrContextFactory::GLContextType kDontCare_GLContextType =
-    GrContextFactory::kNative_GLContextType;
+#if SK_SUPPORT_GPU
+static const GLContextType kDontCare_GLContextType = GrContextFactory::kNative_GLContextType;
+#else
+static const GLContextType kDontCare_GLContextType = 0;
+#endif
 
 // If the platform does not support writing PNGs of PDFs then there will be no
 // comparison images to read. However, we can always write the .pdf files
@@ -723,26 +737,26 @@
     { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "8888" },
     { SkBitmap::kARGB_4444_Config, kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "4444" },
     { SkBitmap::kRGB_565_Config,   kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "565" },
-#ifdef SK_SCALAR_IS_FLOAT
+#if defined(SK_SCALAR_IS_FLOAT) && SK_SUPPORT_GPU
     { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kNative_GLContextType,  0, kRW_ConfigFlag,    "gpu" },
     { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kNative_GLContextType, 16, kRW_ConfigFlag,    "msaa16" },
     /* The debug context does not generate images */
     { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kDebug_GLContextType,   0, kNone_ConfigFlag,  "debug" },
-  #ifdef SK_ANGLE
+#if SK_ANGLE
     { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kANGLE_GLContextType,   0, kRW_ConfigFlag,    "angle" },
     { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kANGLE_GLContextType,  16, kRW_ConfigFlag,    "anglemsaa16" },
-  #endif
-  #ifdef SK_MESA
+#endif // SK_ANGLE
+#ifdef SK_MESA
     { SkBitmap::kARGB_8888_Config, kGPU_Backend,    GrContextFactory::kMESA_GLContextType,    0, kRW_ConfigFlag,    "mesa" },
-  #endif
-#endif
+#endif // SK_MESA
+#endif // 
 #ifdef SK_SUPPORT_XPS
     /* At present we have no way of comparing XPS files (either natively or by converting to PNG). */
     { SkBitmap::kARGB_8888_Config, kXPS_Backend,    kDontCare_GLContextType,                  0, kWrite_ConfigFlag, "xps" },
-#endif
+#endif // defined(SK_SCALAR_IS_FLOAT) && SK_SUPPORT_GPU
 #ifdef SK_SUPPORT_PDF
     { SkBitmap::kARGB_8888_Config, kPDF_Backend,    kDontCare_GLContextType,                  0, kPDFConfigFlags,   "pdf" },
-#endif
+#endif // SK_SUPPORT_PDF
 };
 
 static void usage(const char * argv0) {
@@ -806,6 +820,7 @@
 }
 
 namespace skiagm {
+#if SK_SUPPORT_GPU
 SkAutoTUnref<GrContext> gGrContext;
 /**
  * Sets the global GrContext, accessible by indivual GMs
@@ -840,6 +855,9 @@
 private:
     GrContext* fOld;
 };
+#else
+GrContext* GetGr() { return NULL; }
+#endif
 }
 
 int main(int argc, char * const argv[]) {
@@ -969,8 +987,6 @@
 
     GM::SetResourcePath(resourcePath);
 
-    GrContextFactory* grFactory = new GrContextFactory;
-
     if (readPath) {
         fprintf(stderr, "reading from %s\n", readPath);
     }
@@ -990,9 +1006,12 @@
     int testsFailed = 0;
     int testsMissingReferenceImages = 0;
 
+#if SK_SUPPORT_GPU
+    GrContextFactory* grFactory = new GrContextFactory;
     if (disableTextureCache) {
         skiagm::GetGr()->setTextureCacheLimits(0, 0);
     }
+#endif
 
     Iter iter;
     GM* gm;
@@ -1010,32 +1029,6 @@
 
         for (int i = 0; i < configs.count(); i++) {
             ConfigData config = gRec[configs[i]];
-            SkAutoTUnref<GrRenderTarget> rt;
-            AutoResetGr autogr;
-            if (kGPU_Backend == config.fBackend) {
-                GrContext* gr = grFactory->get(config.fGLContextType);
-                if (!gr) {
-                    continue;
-                }
-
-                // create a render target to back the device
-                GrTextureDesc desc;
-                desc.fConfig = kSkia8888_PM_GrPixelConfig;
-                desc.fFlags = kRenderTarget_GrTextureFlagBit;
-                desc.fWidth = gm->getISize().width();
-                desc.fHeight = gm->getISize().height();
-                desc.fSampleCnt = config.fSampleCnt;
-                GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0);
-                if (!tex) {
-                    continue;
-                }
-                rt.reset(tex->asRenderTarget());
-                rt.get()->ref();
-                tex->unref();
-
-                autogr.set(gr);
-            }
-
             // Skip any tests that we don't even need to try.
             uint32_t gmFlags = gm->getFlags();
             if ((kPDF_Backend == config.fBackend) &&
@@ -1047,19 +1040,43 @@
             // Now we know that we want to run this test and record its
             // success or failure.
             ErrorBitfield testErrors = ERROR_NONE;
-
+            GrRenderTarget* renderTarget = NULL;
+#if SK_SUPPORT_GPU
+            SkAutoTUnref<GrRenderTarget> rt;
+            AutoResetGr autogr;
             if ((ERROR_NONE == testErrors) &&
-                (kGPU_Backend == config.fBackend) &&
-                (NULL == rt.get())) {
-                fprintf(stderr, "Could not create render target for gpu.\n");
-                testErrors |= ERROR_NO_GPU_CONTEXT;
+                kGPU_Backend == config.fBackend) {
+                GrContext* gr = grFactory->get(config.fGLContextType);
+                bool grSuccess = false;
+                if (gr) {
+                    // create a render target to back the device
+                    GrTextureDesc desc;
+                    desc.fConfig = kSkia8888_PM_GrPixelConfig;
+                    desc.fFlags = kRenderTarget_GrTextureFlagBit;
+                    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();
+                        autogr.set(gr);
+                        renderTarget = rt.get();
+                        grSuccess = NULL != renderTarget;
+                    }
+                }
+                if (!grSuccess) {
+                    testErrors |= ERROR_NO_GPU_CONTEXT;
+                }
             }
+#endif
 
             if (ERROR_NONE == testErrors) {
                 testErrors |= test_drawing(gm, config,
                                            writePath, readPath, diffPath,
                                            GetGr(),
-                                           rt.get(), &forwardRenderedBitmap);
+                                           renderTarget, &forwardRenderedBitmap);
             }
 
             if (doDeferred && !testErrors &&
@@ -1067,7 +1084,7 @@
                  kRaster_Backend == config.fBackend)) {
                 testErrors |= test_deferred_drawing(gm, config,
                                                     forwardRenderedBitmap,
-                                                    diffPath, GetGr(), rt.get());
+                                                    diffPath, GetGr(), renderTarget);
             }
 
             if ((ERROR_NONE == testErrors) && doReplay &&
@@ -1120,8 +1137,9 @@
     }
     printf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
            testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
-
+#if SK_SUPPORT_GPU
     delete grFactory;
+#endif
     SkGraphics::Term();
 
     return (0 == testsFailed) ? 0 : -1;
diff --git a/gm/ninepatchstretch.cpp b/gm/ninepatchstretch.cpp
index d1d4dda..226649d 100644
--- a/gm/ninepatchstretch.cpp
+++ b/gm/ninepatchstretch.cpp
@@ -7,7 +7,11 @@
 
 #include "gm.h"
 
+#if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#else
+class GrContext;
+#endif
 
 static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) {
     SkDevice* dev;
@@ -16,11 +20,14 @@
     const int kFixed = 28;
     const int kStretchy = 8;
     const int kSize = 2*kFixed + kStretchy;
-    
+
+#if SK_SUPPORT_GPU
     if (ctx) {
         dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize);
         *bitmap = dev->accessBitmap(false);
-    } else {
+    } else
+#endif
+    {
         bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize);
         bitmap->allocPixels();
         dev = new SkDevice(*bitmap);
diff --git a/gm/texdata.cpp b/gm/texdata.cpp
index 1d13177..2c9b6ed 100644
--- a/gm/texdata.cpp
+++ b/gm/texdata.cpp
@@ -5,6 +5,10 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
+// This test only works with the GPU backend.
+#if SK_SUPPORT_GPU
+
 #include "gm.h"
 #include "GrContext.h"
 #include "effects/GrSingleTextureEffect.h"
@@ -147,3 +151,4 @@
 
 }
 
+#endif
diff --git a/gyp/SampleApp.gyp b/gyp/SampleApp.gyp
index 852d7f7..2db2a18 100644
--- a/gyp/SampleApp.gyp
+++ b/gyp/SampleApp.gyp
@@ -9,7 +9,6 @@
         '../src/core', # needed to get SkConcaveToTriangle, maybe this should be moved to include dir?
         '../gm',       # needed to pull gm.h
         '../samplecode', # To pull SampleApp.h and SampleCode.h
-        '../src/gpu', # To pull gl/GrGLUtil.h
         '../src/pipe/utils', # For TiledPipeController
       ],
       'includes': [
@@ -151,8 +150,6 @@
         'animator.gyp:animator',
         'xml.gyp:xml',
         'experimental.gyp:experimental',
-        'gpu.gyp:gr',
-        'gpu.gyp:skgr',
         'pdf.gyp:pdf',
         'views_animated.gyp:views_animated',
       ],
@@ -237,7 +234,6 @@
             '../experimental/iOSSampleApp/iPad',
             '../experimental/iOSSampleApp/iPhone',
             '../include/utils/ios',
-            '../../include/gpu',
           ],
           'xcode_config_file': '../experimental/iOSSampleApp/SkiOSSampleApp-Base.xcconfig',
           'mac_bundle_resources' : [
@@ -258,6 +254,15 @@
             'android_system.gyp:SampleAppAndroid',
           ],
         }],
+        [ 'skia_gpu == 1', {
+          'include_dirs': [
+            '../src/gpu', # To pull gl/GrGLUtil.h
+          ],
+          'dependencies': [
+            'gpu.gyp:gr',
+            'gpu.gyp:skgr',
+          ],
+        }],
       ],
       'msvs_settings': {
         'VCLinkerTool': {
diff --git a/gyp/bench.gyp b/gyp/bench.gyp
index dcf9b5f..44ebbf2 100644
--- a/gyp/bench.gyp
+++ b/gyp/bench.gyp
@@ -10,7 +10,6 @@
       'type': 'executable',
       'include_dirs' : [
         '../src/core',
-        '../src/gpu',
       ],
       'includes': [
         'bench.gypi'
@@ -18,13 +17,24 @@
       'dependencies': [
         'core.gyp:core',
         'effects.gyp:effects',
-        'gpu.gyp:gr',
-        'gpu.gyp:skgr',
         'images.gyp:images',
         'ports.gyp:ports',
         'utils.gyp:utils',
         'bench_timer',
       ],
+      'conditions': [
+        ['skia_gpu == 1',
+          {
+            'include_dirs' : [
+              '../src/gpu',
+            ],
+            'dependencies': [
+              'gpu.gyp:gr',
+              'gpu.gyp:skgr',
+            ],
+          },
+        ],
+      ],
     },
     {
       'target_name' : 'bench_timer',
@@ -38,8 +48,6 @@
         '../bench/BenchSysTimer_posix.cpp',
         '../bench/BenchSysTimer_windows.h',
         '../bench/BenchSysTimer_windows.cpp',
-        '../bench/BenchGpuTimer_gl.h',
-        '../bench/BenchGpuTimer_gl.cpp',
       ],
         'include_dirs': [
         '../src/core',
@@ -47,7 +55,6 @@
       ],
       'dependencies': [
         'core.gyp:core',
-        'gpu.gyp:gr',
       ],
       'conditions': [
         [ 'skia_os != "mac"', {
@@ -75,6 +82,15 @@
             '../bench/BenchSysTimer_windows.cpp',
           ],
         }],
+        ['skia_gpu == 1', {
+          'dependencies': [
+            'gpu.gyp:gr',
+          ],
+          'sources': [
+            '../bench/BenchGpuTimer_gl.h',
+            '../bench/BenchGpuTimer_gl.cpp',
+          ],
+        }],
       ],
     }
   ],
diff --git a/gyp/common_conditions.gypi b/gyp/common_conditions.gypi
index 6dcfd81..143e854 100644
--- a/gyp/common_conditions.gypi
+++ b/gyp/common_conditions.gypi
@@ -2,7 +2,17 @@
 #
 {
   'conditions' : [
-
+    ['skia_gpu == 1',
+      {
+        'defines': [
+          'SK_SUPPORT_GPU=1',
+        ],
+      }, {
+        'defines': [
+          'SK_SUPPORT_GPU=0',
+        ],
+      },
+    ],
     ['skia_os == "win"',
       {
         'defines': [
diff --git a/gyp/common_variables.gypi b/gyp/common_variables.gypi
index 88e710e..d46ec5e 100644
--- a/gyp/common_variables.gypi
+++ b/gyp/common_variables.gypi
@@ -67,6 +67,7 @@
       'skia_arch_type%': 'x86',
       'skia_arch_width%': 32,
       'android_make_apk%': 1,
+      'skia_gpu%': 1,
     },
 
     # Re-define all variables defined within the level-2 'variables' dict,
@@ -80,6 +81,7 @@
     'skia_arch_type%': '<(skia_arch_type)',
     'skia_arch_width%': '<(skia_arch_width)',
     'android_make_apk%': '<(android_make_apk)',
+    'skia_gpu%': '<(skia_gpu)',
   },
 }
 # Local Variables:
diff --git a/gyp/debugger.gyp b/gyp/debugger.gyp
index 34ff403..f2c3fe9 100644
--- a/gyp/debugger.gyp
+++ b/gyp/debugger.gyp
@@ -7,7 +7,6 @@
         '../src/core',
         '../debugger', # To pull SkDebugger.h
         '../debugger/QT', # For all the QT UI Goodies
-        '../include/gpu/',
         '../src/gpu', # To pull gl/GrGLUtil.h
       ],
       'sources': [
diff --git a/gyp/effects.gyp b/gyp/effects.gyp
index 28369ae..0a9e8d7 100644
--- a/gyp/effects.gyp
+++ b/gyp/effects.gyp
@@ -5,7 +5,6 @@
       'type': 'static_library',
       'include_dirs': [
         '../include/effects',
-        '../src/gpu',
       ],
       'sources': [
         '../include/effects/Sk1DPathEffect.h',
@@ -98,7 +97,16 @@
       },
       'dependencies': [
         'core.gyp:core',
-        'gpu.gyp:gr',
+      ],
+      'conditions': [
+        ['skia_gpu == 1', {
+          'include_dirs': [
+            '../src/gpu',
+          ],
+          'dependencies': [
+            'gpu.gyp:gr',
+          ],
+        }],
       ],
     },
   ],
diff --git a/gyp/gm.gyp b/gyp/gm.gyp
index 20fe09e..13f1976 100644
--- a/gyp/gm.gyp
+++ b/gyp/gm.gyp
@@ -10,7 +10,6 @@
       'include_dirs' : [
         '../src/core',
         '../src/pipe/utils/',
-        '../src/gpu',
       ],
       'includes': [
         'gmslides.gypi',
@@ -25,8 +24,6 @@
       'dependencies': [
         'core.gyp:core',
         'effects.gyp:effects',
-        'gpu.gyp:gr',
-        'gpu.gyp:skgr',
         'images.gyp:images',
         'pdf.gyp:pdf',
         'ports.gyp:ports',
@@ -52,7 +49,16 @@
             'xps.gyp:xps',
           ],
         }],
-      ],  
+        ['skia_gpu == 1', {
+          'include_dirs': [
+            '../src/gpu',
+          ],
+          'dependencies': [
+            'gpu.gyp:gr',
+            'gpu.gyp:skgr',
+          ],
+        }],
+      ],
     },
   ],
 }
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp
index 6a2445d..c9526ef 100644
--- a/gyp/gpu.gyp
+++ b/gyp/gpu.gyp
@@ -46,6 +46,31 @@
           'GR_WIN32_BUILD=1',
         ],
       }],
+      # nullify the targets in this gyp file if skia_gpu is 0
+      [ 'skia_gpu == 0', {
+        'sources/': [
+          ['exclude', '.*'],
+        ],
+        'defines/': [
+          ['exclude', '.*'],
+        ],
+        'include_dirs/': [
+           ['exclude', '.*'],
+        ],
+        'link_settings': {
+          'libraries/': [
+            ['exclude', '.*'],
+          ],
+        },
+        'direct_dependent_settings': {
+          'defines/': [
+            ['exclude', '.*'],
+          ],
+          'include_dirs/': [
+            ['exclude', '.*'],
+          ],
+        },
+      }],
     ],
     'direct_dependent_settings': {
       'conditions': [
diff --git a/gyp/shapeops_demo.gyp b/gyp/shapeops_demo.gyp
index 038b282..cb1b743 100644
--- a/gyp/shapeops_demo.gyp
+++ b/gyp/shapeops_demo.gyp
@@ -61,8 +61,6 @@
         'xml.gyp:xml',
         'svg.gyp:svg',
         'experimental.gyp:experimental',
-        'gpu.gyp:gr',
-        'gpu.gyp:skgr',
         'pdf.gyp:pdf',
       ],
       'conditions' : [
@@ -96,6 +94,12 @@
             '../experimental/Intersection/EdgeDemoApp.xib',
           ],
         }],
+        [ 'skia_gpu == 1', {
+          'dependencies': [
+            'gpu.gyp:gr',
+            'gpu.gyp:skgr',
+          ],
+        }],
       ],
       'msvs_settings': {
         'VCLinkerTool': {
diff --git a/gyp/shapeops_edge.gyp b/gyp/shapeops_edge.gyp
index a862c5d..55ec5fd 100644
--- a/gyp/shapeops_edge.gyp
+++ b/gyp/shapeops_edge.gyp
@@ -10,7 +10,6 @@
       'type': 'executable',
       'include_dirs' : [
         '../src/core',
-        '../src/gpu',
       ],
       'sources': [
         '../experimental/Intersection/ActiveEdge_Test.cpp',
@@ -100,13 +99,22 @@
         'core.gyp:core',
         'effects.gyp:effects',
         'experimental.gyp:experimental',
-        'gpu.gyp:gr',
-        'gpu.gyp:skgr',
         'images.gyp:images',
         'ports.gyp:ports',
         'pdf.gyp:pdf',
         'utils.gyp:utils',
       ],
+      'conditions': [
+        [ 'skia_gpu == 1', {
+          'include_dirs': [
+            '../src/gpu',
+          ],
+          'dependencies': [
+            'gpu.gyp:gr',
+            'gpu.gyp:skgr',
+          ],
+        }],
+      ],
     },
   ],
 }
diff --git a/gyp/tests.gyp b/gyp/tests.gyp
index b30a749..278dce7 100644
--- a/gyp/tests.gyp
+++ b/gyp/tests.gyp
@@ -10,7 +10,6 @@
       'include_dirs' : [
         '../src/core',
         '../src/effects',
-        '../src/gpu',
         '../src/pdf',
         '../src/utils',
         '../tools/',
@@ -96,14 +95,23 @@
         'core.gyp:core',
         'effects.gyp:effects',
         'experimental.gyp:experimental',
-        'gpu.gyp:gr',
-        'gpu.gyp:skgr',
         'images.gyp:images',
         'ports.gyp:ports',
         'pdf.gyp:pdf',
         'tools.gyp:picture_utils',
         'utils.gyp:utils',
       ],
+      'conditions': [
+        [ 'skia_gpu == 1', {
+          'include_dirs': [
+            '../src/gpu',
+          ],
+          'dependencies': [
+            'gpu.gyp:gr',
+            'gpu.gyp:skgr',
+          ],
+        }],
+      ],
     },
   ],
 }
diff --git a/gyp/views.gyp b/gyp/views.gyp
index fa0a29a..ec3fd79 100644
--- a/gyp/views.gyp
+++ b/gyp/views.gyp
@@ -18,7 +18,6 @@
         '../include/images',
         '../include/effects',
         '../include/views/unix',
-        '../include/gpu',
       ],
       'dependencies': [
         'angle.gyp:*',
@@ -112,6 +111,11 @@
             '../src/views/win/skia_win.cpp',
           ],
         }],
+        [ 'skia_gpu == 1', {
+          'include_dirs': [
+            '../include/gpu',
+          ],
+        }],
       ],
       'direct_dependent_settings': {
         'include_dirs': [
diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h
index b180c89..b51a801 100644
--- a/include/config/SkUserConfig.h
+++ b/include/config/SkUserConfig.h
@@ -176,4 +176,13 @@
         #define SK_A32_SHIFT    24
 #endif
 
+
+/* Determines whether to build code that supports the GPU backend. Some classes
+   that are not GPU-specific, such as SkShader subclasses, have optional code
+   that is used allows them to interact with the GPU backend. If you'd like to
+   omit this code set SK_SUPPORT_GPU to 0. This also allows you to omit the gpu
+   directories from your include search path when you're not building the GPU
+   backend. Defaults to 1 (build the GPU code).
+ */
+//#define SK_SUPPORT_GPU 1
 #endif
diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h
index 9130a3a..cc00f79 100644
--- a/include/core/SkPostConfig.h
+++ b/include/core/SkPostConfig.h
@@ -55,6 +55,10 @@
     #endif
 #endif
 
+#if !defined(SK_SUPPORT_GPU)
+    #define SK_SUPPORT_GPU 1
+#endif
+
 /**
  * The clang static analyzer likes to know that when the program is not
  * expected to continue (crash, assertion failure, etc). It will notice that
diff --git a/include/views/SkOSWindow_Mac.h b/include/views/SkOSWindow_Mac.h
index e3bcea9..3391785 100644
--- a/include/views/SkOSWindow_Mac.h
+++ b/include/views/SkOSWindow_Mac.h
@@ -21,7 +21,9 @@
                                  void* owner);
     enum SkBackEndTypes {
         kNone_BackEndType,
+#if SK_SUPPORT_GPU
         kNativeGL_BackEndType,
+#endif
     };
 
     void    detach();
@@ -42,7 +44,9 @@
     void*   fHWND;
     bool    fInvalEventIsPending;
     void*   fNotifier;
+#if SK_SUPPORT_GPU
     void*   fGLContext;
+#endif
     typedef SkWindow INHERITED;
 };
 
diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h
index f61c80a..5add420 100644
--- a/include/views/SkOSWindow_Win.h
+++ b/include/views/SkOSWindow_Win.h
@@ -29,10 +29,12 @@
 
     enum SkBackEndTypes {
         kNone_BackEndType,
+#if SK_SUPPORT_GPU
         kNativeGL_BackEndType,
 #if SK_ANGLE
         kANGLE_BackEndType,
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
     };
 
     bool attach(SkBackEndTypes attachType, int msaaSampleCount);
@@ -62,17 +64,20 @@
     
     void                doPaint(void* ctx);
 
+#if SK_SUPPORT_GPU
     void*               fHGLRC;
 #if SK_ANGLE
     EGLDisplay          fDisplay;
     EGLContext          fContext;
     EGLSurface          fSurface;
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
 
     HMENU               fMBar;
 
     SkBackEndTypes      fAttached;
 
+#if SK_SUPPORT_GPU
     bool attachGL(int msaaSampleCount);
     void detachGL();
     void presentGL();
@@ -81,7 +86,8 @@
     bool attachANGLE(int msaaSampleCount);
     void detachANGLE();
     void presentANGLE();
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
 
     typedef SkWindow INHERITED; 
 };
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 6adc1b4..a101853 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -9,7 +9,6 @@
 #include "SkData.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
-#include "SkGpuDevice.h"
 #include "SkGraphics.h"
 #include "SkImageEncoder.h"
 #include "SkPaint.h"
@@ -19,12 +18,17 @@
 #include "SkWindow.h"
 
 #include "SampleCode.h"
-#include "GrContext.h"
 #include "SkTypeface.h"
 
+#if SK_SUPPORT_GPU
 #include "gl/GrGLInterface.h"
 #include "gl/GrGLUtil.h"
 #include "GrRenderTarget.h"
+#include "GrContext.h"
+#include "SkGpuDevice.h"
+#else
+class GrContext;
+#endif
 
 #include "SkOSFile.h"
 #include "SkPDFDevice.h"
@@ -147,18 +151,22 @@
 class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
 public:
 
-    DefaultDeviceManager()
-        : fCurContext(NULL)
-        , fCurIntf(NULL)
-        , fCurRenderTarget(NULL)
-        , fBackend(kNone_BackEndType)
-        , fMSAASampleCount(0) {
+    DefaultDeviceManager() {
+#if SK_SUPPORT_GPU
+        fCurContext = NULL;
+        fCurIntf = NULL;
+        fCurRenderTarget = NULL;
+        fMSAASampleCount = 0;
+#endif
+        fBackend = kNone_BackEndType;
     }
 
     virtual ~DefaultDeviceManager() {
+#if SK_SUPPORT_GPU
         SkSafeUnref(fCurContext);
         SkSafeUnref(fCurIntf);
         SkSafeUnref(fCurRenderTarget);
+#endif
     }
 
     virtual void setUpBackend(SampleWindow* win, int msaaSampleCount) {
@@ -166,6 +174,7 @@
 
         fBackend = kNone_BackEndType;
 
+#if SK_SUPPORT_GPU
         switch (win->getDeviceType()) {
             case kRaster_DeviceType:
                 // fallthrough
@@ -182,7 +191,7 @@
                 // ANGLE is really the only odd man out
                 fBackend = kANGLE_BackEndType;
                 break;
-#endif
+#endif // SK_ANGLE
             default:
                 SkASSERT(false);
                 break;
@@ -209,7 +218,7 @@
             case kANGLE_DeviceType:
                 fCurIntf = GrGLCreateANGLEInterface();
                 break;
-#endif
+#endif // SK_ANGLE
             case kNullGPU_DeviceType:
                 fCurIntf = GrGLCreateNullInterface();
                 break;
@@ -230,13 +239,13 @@
 
             win->detach();
         }
-
+#endif // SK_SUPPORT_GPU
         // call windowSizeChanged to create the render target
-        windowSizeChanged(win);
+        this->windowSizeChanged(win);
     }
 
     virtual void tearDownBackend(SampleWindow *win) {
-
+#if SK_SUPPORT_GPU
         SkSafeUnref(fCurContext);
         fCurContext = NULL;
 
@@ -245,7 +254,7 @@
 
         SkSafeUnref(fCurRenderTarget);
         fCurRenderTarget = NULL;
-
+#endif
         win->detach();
         fBackend = kNone_BackEndType;
     }
@@ -262,6 +271,7 @@
             case kANGLE_DeviceType:
 #endif
                 break;
+#if SK_SUPPORT_GPU
             case kGPU_DeviceType:
             case kNullGPU_DeviceType:
                 if (fCurContext) {
@@ -271,6 +281,7 @@
                     return false;
                 }
                 break;
+#endif
             default:
                 SkASSERT(false);
                 return false;
@@ -281,6 +292,7 @@
     virtual void publishCanvas(SampleWindow::DeviceType dType,
                                SkCanvas* canvas,
                                SampleWindow* win) {
+#if SK_SUPPORT_GPU
         if (fCurContext) {
             // in case we have queued drawing calls
             fCurContext->flush();
@@ -295,12 +307,13 @@
                                              bm.rowBytes());
             }
         }
+#endif
 
         win->present();
     }
 
     virtual void windowSizeChanged(SampleWindow* win) {
-
+#if SK_SUPPORT_GPU
         if (fCurContext) {
             win->attach(fBackend, fMSAASampleCount);
 
@@ -317,23 +330,35 @@
             SkSafeUnref(fCurRenderTarget);
             fCurRenderTarget = fCurContext->createPlatformRenderTarget(desc);
         }
+#endif
     }
 
     virtual GrContext* getGrContext() {
+#if SK_SUPPORT_GPU
         return fCurContext;
+#else
+        return NULL;
+#endif
     }
 
     virtual GrRenderTarget* getGrRenderTarget() SK_OVERRIDE {
+#if SK_SUPPORT_GPU
         return fCurRenderTarget;
+#else
+        return NULL;
+#endif
     }
 
 private:
+
+#if SK_SUPPORT_GPU
     GrContext*              fCurContext;
     const GrGLInterface*    fCurIntf;
     GrRenderTarget*         fCurRenderTarget;
+    int fMSAASampleCount;
+#endif
 
     SkOSWindow::SkBackEndTypes fBackend;
-    int fMSAASampleCount;
 
     typedef SampleWindow::DeviceManager INHERITED;
 };
@@ -657,13 +682,16 @@
 static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType ct) {
     static const SampleWindow::DeviceType gCT[] = {
         SampleWindow::kPicture_DeviceType,
+#if SK_SUPPORT_GPU
         SampleWindow::kGPU_DeviceType,
 #if SK_ANGLE
         SampleWindow::kANGLE_DeviceType,
-#endif
+#endif // SK_ANGLE
         SampleWindow::kRaster_DeviceType, // skip the null gpu device in normal cycling
+#endif // SK_SUPPORT_GPU
         SampleWindow::kRaster_DeviceType
     };
+    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gCT) == SampleWindow::kDeviceTypeCnt, array_size_mismatch);
     return gCT[ct];
 }
 
@@ -1233,19 +1261,23 @@
         switch (fDeviceType) {
             case kRaster_DeviceType:
                 // fallthrough
+#if SK_SUPPORT_GPU
             case kGPU_DeviceType:
                 // fallthrough
 #if SK_ANGLE
             case kANGLE_DeviceType:
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
                 canvas = this->INHERITED::beforeChildren(canvas);
                 break;
             case kPicture_DeviceType:
                 fPicture = new SkPicture;
                 canvas = fPicture->beginRecording(9999, 9999);
                 break;
+#if SK_SUPPORT_GPU
             case kNullGPU_DeviceType:
                 break;
+#endif
             default:
                 SkASSERT(false);
                 break;
@@ -1737,6 +1769,7 @@
             this->inval(NULL);
             this->updateTitle();
             return true;
+#if SK_SUPPORT_GPU
         case '\\':
             this->setDeviceType(kNullGPU_DeviceType);
             this->inval(NULL);
@@ -1753,6 +1786,7 @@
                 }
             }
             return true;
+#endif
         case 's':
             fScale = !fScale;
             this->inval(NULL);
@@ -1967,22 +2001,31 @@
 static const char* gDeviceTypePrefix[] = {
     "raster: ",
     "picture: ",
+#if SK_SUPPORT_GPU
     "opengl: ",
 #if SK_ANGLE
     "angle: ",
-#endif
+#endif // SK_ANGLE
     "null-gl: "
+#endif // SK_SUPPORT_GPU
 };
+SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gDeviceTypePrefix) == SampleWindow::kDeviceTypeCnt,
+                  array_size_mismatch);
 
 static const bool gDeviceTypeIsGPU[] = {
     false,
     false,
+#if SK_SUPPORT_GPU
     true,
 #if SK_ANGLE
     true,
-#endif
+#endif // SK_ANGLE
     true
+#endif // SK_SUPPORT_GPU
 };
+SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gDeviceTypeIsGPU) == SampleWindow::kDeviceTypeCnt,
+                  array_size_mismatch);
+
 
 static const char* trystate_str(SkOSMenu::TriState state,
                                 const char trueStr[], const char falseStr[]) {
@@ -2051,12 +2094,14 @@
         title.prepend("! ");
     }
 
+#if SK_SUPPORT_GPU
     if (gDeviceTypeIsGPU[fDeviceType] &&
         NULL != fDevManager &&
         fDevManager->getGrRenderTarget()->numSamples() > 0) {
         title.appendf(" [MSAA: %d]",
                        fDevManager->getGrRenderTarget()->numSamples());
     }
+#endif
 
     this->setTitle(title.c_str());
 }
diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h
index 9435652..6d24bd5 100644
--- a/samplecode/SampleApp.h
+++ b/samplecode/SampleApp.h
@@ -35,11 +35,15 @@
     enum DeviceType {
         kRaster_DeviceType,
         kPicture_DeviceType,
+#if SK_SUPPORT_GPU
         kGPU_DeviceType,
 #if SK_ANGLE
         kANGLE_DeviceType,
-#endif
-        kNullGPU_DeviceType
+#endif // SK_ANGLE
+        kNullGPU_DeviceType,
+#endif // SK_SUPPORT_GPU
+
+        kDeviceTypeCnt
     };
     /**
      * SampleApp ports can subclass this manager class if they want to:
@@ -70,10 +74,10 @@
         // at least once before first draw (after init)
         virtual void windowSizeChanged(SampleWindow* win) = 0;
 
-        // return the GrContext backing gpu devices
+        // return the GrContext backing gpu devices (NULL if not built with GPU support)
         virtual GrContext* getGrContext() = 0;
 
-        // return the GrRenderTarget backing gpu devices
+        // return the GrRenderTarget backing gpu devices (NULL if not built with GPU support)
         virtual GrRenderTarget* getGrRenderTarget() = 0;
     };
 
diff --git a/samplecode/SampleBitmapRect.cpp b/samplecode/SampleBitmapRect.cpp
index 95ea1a7..684c976 100644
--- a/samplecode/SampleBitmapRect.cpp
+++ b/samplecode/SampleBitmapRect.cpp
@@ -24,16 +24,24 @@
 #include "SkOSFile.h"
 #include "SkStream.h"
 
+#if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#else
+class GrContext;
+#endif
+
 
 static void make_bitmap(SkBitmap* bitmap, GrContext* ctx) {
     SkCanvas canvas;
 
+#if SK_SUPPORT_GPU
     if (ctx) {
         SkDevice* dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, 64, 64);
         canvas.setDevice(dev)->unref();
         *bitmap = dev->accessBitmap(false);
-    } else {
+    } else 
+#endif
+    {
         bitmap->setConfig(SkBitmap::kARGB_8888_Config, 64, 64);
         bitmap->allocPixels();
         canvas.setBitmapDevice(*bitmap);
diff --git a/samplecode/SampleNinePatch.cpp b/samplecode/SampleNinePatch.cpp
index bab7b23..4286ed3 100644
--- a/samplecode/SampleNinePatch.cpp
+++ b/samplecode/SampleNinePatch.cpp
@@ -5,10 +5,16 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "SampleCode.h"
 #include "SkCanvas.h"
+#include "SkDevice.h"
 #include "SkPaint.h"
+#if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#else
+class GrContext;
+#endif
 
 static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) {
     SkDevice* dev;
@@ -18,10 +24,13 @@
     const int kStretchy = 8;
     const int kSize = 2*kFixed + kStretchy;
 
+#if SK_SUPPORT_GPU
     if (ctx) {
         dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize);
         *bitmap = dev->accessBitmap(false);
-    } else {
+    } else 
+#endif
+    {
         bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize);
         bitmap->allocPixels();
         dev = new SkDevice(*bitmap);
@@ -52,7 +61,7 @@
 
 class NinePatchView : public SampleView {
 public:
-	NinePatchView() {}
+    NinePatchView() {}
 
 protected:
     // overrides from SkEventSink
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index ed76743..f3e96e0 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -8,7 +8,9 @@
 #include "SkBitmap.h"
 #include "SkBlurImageFilter.h"
 #include "SkColorPriv.h"
+#if SK_SUPPORT_GPU
 #include "GrContext.h"
+#endif
 
 SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer)
   : INHERITED(buffer) {
@@ -184,8 +186,13 @@
 }
 
 GrTexture* SkBlurImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rect) {
+#if SK_SUPPORT_GPU
     return src->getContext()->gaussianBlur(src, false, rect,
                                            fSigma.width(), fSigma.height());
+#else
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+#endif
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurImageFilter)
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 9971c56..98c294c 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -9,6 +9,8 @@
 #include "SkBitmap.h"
 #include "SkColorPriv.h"
 #include "SkTypes.h"
+
+#if SK_SUPPORT_GPU
 #include "GrProgramStageFactory.h"
 #include "effects/GrSingleTextureEffect.h"
 #include "gl/GrGLProgramStage.h"
@@ -21,6 +23,7 @@
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
+#endif
 
 namespace {
 
@@ -29,6 +32,7 @@
 const SkScalar gOneHalf = SkFloatToScalar(0.5f);
 const SkScalar gOneQuarter = SkFloatToScalar(0.25f);
 
+#if SK_SUPPORT_GPU
 void setUniformPoint3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) {
     GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat));
     uman.set3fv(uni, 0, 1, &point.fX);
@@ -44,6 +48,7 @@
                            int height) {
     setUniformPoint3(uman, uni, SkPoint3(point.fX, height-point.fY, point.fZ));
 }
+#endif
 
 // Shift matrix components to the left, as we advance pixels to the right.
 inline void shiftMatrixLeft(int m[9]) {
@@ -298,6 +303,7 @@
     SkScalar fShininess;
 };
 
+#if SK_SUPPORT_GPU
 
 class GrLightingEffect : public GrSingleTextureEffect {
 public:
@@ -437,6 +443,11 @@
     UniformHandle   fConeScaleUni;
     UniformHandle   fSUni;
 };
+#else
+
+class GrGLLight;
+
+#endif
 
 };
 
@@ -493,7 +504,14 @@
     SkPoint3 lightColor(const SkPoint3&) const { return color(); }
     virtual LightType type() const { return kDistant_LightType; }
     const SkPoint3& direction() const { return fDirection; }
-    virtual GrGLLight* createGLLight() const SK_OVERRIDE;
+    virtual GrGLLight* createGLLight() const SK_OVERRIDE {
+#if SK_SUPPORT_GPU
+        return SkNEW(GrGLDistantLight);
+#else
+        SkDEBUGFAIL("Should not call in GPU-less build");
+        return NULL;
+#endif
+    }
     virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
         if (other.type() != kDistant_LightType) {
             return false;
@@ -538,7 +556,12 @@
     virtual LightType type() const { return kPoint_LightType; }
     const SkPoint3& location() const { return fLocation; }
     virtual GrGLLight* createGLLight() const SK_OVERRIDE {
+#if SK_SUPPORT_GPU
         return SkNEW(GrGLPointLight);
+#else
+        SkDEBUGFAIL("Should not call in GPU-less build");
+        return NULL;
+#endif
     }
     virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
         if (other.type() != kPoint_LightType) {
@@ -603,7 +626,12 @@
         return color() * scale;
     }
     virtual GrGLLight* createGLLight() const SK_OVERRIDE {
+#if SK_SUPPORT_GPU
         return SkNEW(GrGLSpotLight);
+#else
+        SkDEBUGFAIL("Should not call in GPU-less build");
+        return NULL;
+#endif
     }
     virtual LightType type() const { return kSpot_LightType; }
     const SkPoint3& location() const { return fLocation; }
@@ -790,11 +818,16 @@
 
 bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage,
                                                     GrTexture* texture) const {
+#if SK_SUPPORT_GPU
     if (stage) {
         SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
         *stage = SkNEW_ARGS(GrDiffuseLightingEffect, (texture, light(), scale, kd()));
     }
     return true;
+#else
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return false;
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -854,15 +887,21 @@
 
 bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage,
                                                      GrTexture* texture) const {
+#if SK_SUPPORT_GPU
     if (stage) {
         SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
         *stage = SkNEW_ARGS(GrSpecularLightingEffect, (texture, light(), scale, ks(), shininess()));
     }
     return true;
+#else
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return false;
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
 class GrGLLightingEffect  : public GrGLProgramStage {
 public:
     GrGLLightingEffect(const GrProgramStageFactory& factory,
@@ -1176,10 +1215,6 @@
     setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
 }
 
-GrGLLight* SkDistantLight::createGLLight() const {
-    return SkNEW(GrGLDistantLight);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 void GrGLDistantLight::setupVariables(GrGLShaderBuilder* builder) {
@@ -1299,6 +1334,8 @@
     out->appendf("lightColor(%s)", surfaceToLight);
 }
 
+#endif
+
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 3c2e385..b0fc289 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -8,8 +8,10 @@
 #include "SkMorphologyImageFilter.h"
 #include "SkBitmap.h"
 #include "SkColorPriv.h"
+#if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrTexture.h"
+#endif
 
 SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer)
   : INHERITED(buffer) {
@@ -213,15 +215,25 @@
 }
 
 GrTexture* SkDilateImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rect) {
+#if SK_SUPPORT_GPU
     return src->getContext()->applyMorphology(src, rect,
                                               GrContext::kDilate_MorphologyType,
                                               radius());
+#else
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+#endif
 }
 
 GrTexture* SkErodeImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rect) {
+#if SK_SUPPORT_GPU
     return src->getContext()->applyMorphology(src, rect,
                                               GrContext::kErode_MorphologyType,
                                               radius());
+#else
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+#endif
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkDilateImageFilter)
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 0dfb186..e415c62 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -671,6 +671,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
+
+#include "SkGr.h"
+
 GrGLGradientStage::GrGLGradientStage(const GrProgramStageFactory& factory)
                                      : INHERITED(factory) { }
 
@@ -728,3 +732,4 @@
     return fTexture;
 }
 
+#endif
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index af15ecd..9e80fd3 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -18,9 +18,6 @@
 #include "SkTemplates.h"
 #include "SkBitmapCache.h"
 #include "SkShader.h"
-#include "GrSamplerState.h"
-#include "SkGr.h"
-#include "gl/GrGLProgramStage.h"
 
 #ifndef SK_DISABLE_DITHER_32BIT_GRADIENT
     #define USE_DITHER_32BIT_GRADIENT
@@ -192,6 +189,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
+
+#include "gl/GrGLProgramStage.h"
+
 class GrSamplerState;
 class GrProgramStageFactory;
 
@@ -262,3 +263,5 @@
 
 #endif
 
+#endif
+
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index 9d4ee6d..cd44d3f 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -472,6 +472,8 @@
     }
 }
 
+#if SK_SUPPORT_GPU
+
 /////////////////////////////////////////////////////////////////////
 
 class GrGLLinearGradient : public GrGLGradientStage {
@@ -541,3 +543,12 @@
     return SkNEW_ARGS(GrLinearGradient, (context, *this, sampler));
 }
 
+#else
+
+GrCustomStage* SkLinearGradient::asNewCustomStage(GrContext* context,
+                                                  GrSamplerState* sampler) const {
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+}
+
+#endif
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index be2e46f..32083dc 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -471,6 +471,8 @@
 
 /////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
+
 class GrGLRadialGradient : public GrGLGradientStage {
 public:
 
@@ -541,3 +543,12 @@
     return SkNEW_ARGS(GrRadialGradient, (context, *this, sampler));
 }
 
+#else
+
+GrCustomStage* SkRadialGradient::asNewCustomStage(GrContext* context,
+    GrSamplerState* sampler) const {
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+}
+
+#endif
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index b4e013a..1daaa7d 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -380,6 +380,8 @@
 
 /////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
+
 class GrGLSweepGradient : public GrGLGradientStage {
 public:
 
@@ -448,3 +450,12 @@
     return SkNEW_ARGS(GrSweepGradient, (context, *this, sampler));
 }
 
+#else
+
+GrCustomStage* SkSweepGradient::asNewCustomStage(GrContext* context,
+    GrSamplerState* sampler) const {
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+}
+
+#endif
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index ae20cae..9fe180a 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -315,6 +315,8 @@
 
 /////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
+
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
@@ -659,3 +661,12 @@
     return SkNEW_ARGS(GrConical2Gradient, (context, *this, sampler));
 }
 
+#else
+
+GrCustomStage* SkTwoPointConicalGradient::asNewCustomStage(
+    GrContext* context, GrSamplerState* sampler) const {
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
index 582c435..06e27fe 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -347,6 +347,8 @@
 
 /////////////////////////////////////////////////////////////////////
 
+#if SK_SUPPORT_GPU
+
 // For brevity
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
@@ -630,3 +632,12 @@
     return SkNEW_ARGS(GrRadial2Gradient, (context, *this, sampler));
 }
 
+#else
+
+GrCustomStage* SkTwoPointRadialGradient::asNewCustomStage(
+    GrContext* context, GrSamplerState* sampler) const {
+    SkDEBUGFAIL("Should not call in GPU-less build");
+    return NULL;
+}
+
+#endif
diff --git a/src/views/mac/SkNSView.h b/src/views/mac/SkNSView.h
index bf6e67c..8b83b34 100644
--- a/src/views/mac/SkNSView.h
+++ b/src/views/mac/SkNSView.h
@@ -24,13 +24,17 @@
     
     NSString* fTitle;
     SkOSWindow* fWind;
+#if SK_SUPPORT_GPU
     NSOpenGLContext* fGLContext;
+#endif
     id<SkNSViewOptionsDelegate> fOptionsDelegate;
 }
 
 @property (nonatomic, readonly) SkOSWindow *fWind;
 @property (nonatomic, retain) NSString* fTitle;
+#if SK_SUPPORT_GPU
 @property (nonatomic, retain) NSOpenGLContext* fGLContext;
+#endif
 @property (nonatomic, assign) id<SkNSViewOptionsDelegate> fOptionsDelegate;
 
 - (id)initWithDefaults;
diff --git a/src/views/mac/SkNSView.mm b/src/views/mac/SkNSView.mm
index dfb646d..92a357d 100644
--- a/src/views/mac/SkNSView.mm
+++ b/src/views/mac/SkNSView.mm
@@ -6,14 +6,18 @@
  * found in the LICENSE file.
  */
 
-#import "SkNSView.h"s
+#import "SkNSView.h"
 #include "SkCanvas.h"
 #include "SkCGUtils.h"
 #include "SkEvent.h"
 
 //#define FORCE_REDRAW
 @implementation SkNSView
-@synthesize fWind, fTitle, fOptionsDelegate, fGLContext;
+@synthesize fWind, fTitle, fOptionsDelegate;
+
+#if SK_SUPPORT_GPU
+@synthesize fGLContext;
+#endif
 
 - (id)initWithCoder:(NSCoder*)coder {
     if ((self = [super initWithCoder:coder])) {
@@ -42,6 +46,7 @@
         fWind->setVisibleP(true);
         fWind->resize((int) self.frame.size.width, (int) self.frame.size.height, 
                       SkBitmap::kARGB_8888_Config);
+        [self attach:SkOSWindow::kNone_BackEndType withMSAASampleCount:0];
     }
 }
 
@@ -56,8 +61,10 @@
 - (void)resizeSkView:(NSSize)newSize {
     if (NULL != fWind && (fWind->width() != newSize.width || fWind->height() != newSize.height)) {
         fWind->resize((int) newSize.width, (int) newSize.height);
+#if SK_SUPPORT_GPU
         glClear(GL_STENCIL_BUFFER_BIT);
         [fGLContext update];
+#endif
     }
 }
 
@@ -68,7 +75,9 @@
 
 - (void)dealloc {
     delete fWind;
+#if SK_SUPPORT_GPU
     self.fGLContext = nil;
+#endif
     self.fTitle = nil;
     [super dealloc];
 }
@@ -115,13 +124,13 @@
 
 #include "SkKey.h"
 enum {
-	SK_MacReturnKey		= 36,
-	SK_MacDeleteKey		= 51,
-	SK_MacEndKey		= 119,
-	SK_MacLeftKey		= 123,
-	SK_MacRightKey		= 124,
-	SK_MacDownKey		= 125,
-	SK_MacUpKey			= 126,
+    SK_MacReturnKey        = 36,
+    SK_MacDeleteKey        = 51,
+    SK_MacEndKey        = 119,
+    SK_MacLeftKey        = 123,
+    SK_MacRightKey        = 124,
+    SK_MacDownKey        = 125,
+    SK_MacUpKey            = 126,
     SK_Mac0Key          = 0x52,
     SK_Mac1Key          = 0x53,
     SK_Mac2Key          = 0x54,
@@ -136,17 +145,17 @@
 
 static SkKey raw2key(UInt32 raw)
 {
-	static const struct {
-		UInt32  fRaw;
-		SkKey   fKey;
-	} gKeys[] = {
-		{ SK_MacUpKey,		kUp_SkKey		},
-		{ SK_MacDownKey,	kDown_SkKey		},
-		{ SK_MacLeftKey,	kLeft_SkKey		},
-		{ SK_MacRightKey,   kRight_SkKey	},
-		{ SK_MacReturnKey,  kOK_SkKey		},
-		{ SK_MacDeleteKey,  kBack_SkKey		},
-		{ SK_MacEndKey,		kEnd_SkKey		},
+    static const struct {
+        UInt32  fRaw;
+        SkKey   fKey;
+    } gKeys[] = {
+        { SK_MacUpKey,      kUp_SkKey       },
+        { SK_MacDownKey,    kDown_SkKey     },
+        { SK_MacLeftKey,    kLeft_SkKey     },
+        { SK_MacRightKey,   kRight_SkKey    },
+        { SK_MacReturnKey,  kOK_SkKey       },
+        { SK_MacDeleteKey,  kBack_SkKey     },
+        { SK_MacEndKey,     kEnd_SkKey      },
         { SK_Mac0Key,       k0_SkKey        },
         { SK_Mac1Key,       k1_SkKey        },
         { SK_Mac2Key,       k2_SkKey        },
@@ -157,12 +166,12 @@
         { SK_Mac7Key,       k7_SkKey        },
         { SK_Mac8Key,       k8_SkKey        },
         { SK_Mac9Key,       k9_SkKey        }
-	};
+    };
     
-	for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
-		if (gKeys[i].fRaw == raw)
-			return gKeys[i].fKey;
-	return kNONE_SkKey;
+    for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
+        if (gKeys[i].fRaw == raw)
+            return gKeys[i].fKey;
+    return kNONE_SkKey;
 }
 
 - (void)keyDown:(NSEvent *)event {
@@ -222,8 +231,8 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+#if SK_SUPPORT_GPU
 #include <OpenGL/OpenGL.h>
-
 namespace { 
 CGLContextObj createGLContext(int msaaSampleCount) {
     GLint major, minor;
@@ -266,46 +275,75 @@
     return ctx;
 }
 }
+#endif
 
 - (void)viewDidMoveToWindow {
     [super viewDidMoveToWindow];
     
+#if SK_SUPPORT_GPU
     //Attaching view to fGLContext requires that the view to be part of a window,
     //and that the NSWindow instance must have a CoreGraphics counterpart (or 
     //it must NOT be deferred or should have been on screen at least once)
     if ([fGLContext view] != self && nil != self.window) {
         [fGLContext setView:self];
     }
+#endif
 }
-- (bool)attach:(SkOSWindow::SkBackEndTypes)attachType
-        withMSAASampleCount:(int) sampleCount {
-    if (nil == fGLContext) {
-        CGLContextObj ctx = createGLContext(sampleCount);
-        fGLContext = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx];
-        CGLReleaseContext(ctx);
-        if (NULL == fGLContext) {
-            return false;
+- (bool)attach:(SkOSWindow::SkBackEndTypes)attachType withMSAASampleCount:(int) sampleCount {
+#if SK_SUPPORT_GPU
+    if (SkOSWindow::kNativeGL_BackEndType == attachType) {
+        [self setWantsLayer:NO];
+        self.layer = nil;
+        if (nil == fGLContext) {
+            CGLContextObj ctx = createGLContext(sampleCount);
+            fGLContext = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx];
+            CGLReleaseContext(ctx);
+            if (NULL == fGLContext) {
+                return false;
+            }
+            [fGLContext setView:self];
         }
-        [fGLContext setView:self];
+        
+        [fGLContext makeCurrentContext];
+        
+        glViewport(0, 0, (int) self.bounds.size.width, (int) self.bounds.size.width);
+        glClearColor(0, 0, 0, 0);
+        glClearStencil(0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+        return true;
     }
-    
-    [fGLContext makeCurrentContext];
-    
-    glViewport(0, 0, (int) self.bounds.size.width, (int) self.bounds.size.width);
-    glClearColor(0, 0, 0, 0);
-    glClearStencil(0);
-    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-    return true;
+#endif
+    if (SkOSWindow::kNone_BackEndType == attachType) {
+        [self detach];
+        [self setLayer:[CALayer layer]];
+        [self setWantsLayer:YES];
+        return true;
+    }
+    return false;
 }
 
 - (void)detach {
+#if SK_SUPPORT_GPU
     [fGLContext release];
     fGLContext = nil;
+#endif
 }
 
+#include "SkCGUtils.h"
+
 - (void)present {
+#if SK_SUPPORT_GPU
     if (nil != fGLContext) {
         [fGLContext flushBuffer];
+        return;
     }
+#endif
+    const SkBitmap& bmp = fWind->getBitmap();
+    SkASSERT(self.layer);
+    // FIXME: This causes the layer to flicker during animation. Making a copy of the CGImage does
+    // not help.
+    CGImageRef img = SkCreateCGImageRef(bmp);
+    self.layer.contents = (id) img;
+    CGImageRelease(img);
 }
 @end
diff --git a/src/views/mac/SkOSWindow_Mac.mm b/src/views/mac/SkOSWindow_Mac.mm
index a5d3fef..3e499ba 100644
--- a/src/views/mac/SkOSWindow_Mac.mm
+++ b/src/views/mac/SkOSWindow_Mac.mm
@@ -19,7 +19,9 @@
 
 SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) {
     fInvalEventIsPending = false;
+#if SK_SUPPORT_GPU
     fGLContext = NULL;
+#endif
     fNotifier = [[SkEventNotifier alloc] init];
 }
 SkOSWindow::~SkOSWindow() {
@@ -38,7 +40,9 @@
         fInvalEventIsPending = false;
         const SkIRect& r = this->getDirtyBounds();
         [(SkNSView*)fHWND postInvalWithRect:&r];
+#if SK_SUPPORT_GPU
         [(NSOpenGLContext*)fGLContext update];
+#endif
         return true;
     }
     if ([(SkNSView*)fHWND onHandleEvent:evt]) {
diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp
index 2f8e015..88a0a36 100644
--- a/src/views/win/SkOSWindow_win.cpp
+++ b/src/views/win/SkOSWindow_win.cpp
@@ -38,19 +38,22 @@
     PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
 }
 
-SkOSWindow::SkOSWindow(void* hWnd) 
-    : fHWND(hWnd) 
+SkOSWindow::SkOSWindow(void* hWnd) {
+    fHWND = hWnd;
+#if SK_SUPPORT_GPU
 #if SK_ANGLE
-    , fDisplay(EGL_NO_DISPLAY)
-    , fContext(EGL_NO_CONTEXT)
-    , fSurface(EGL_NO_SURFACE)
+    fDisplay = EGL_NO_DISPLAY;
+    fContext = EGL_NO_CONTEXT;
+    fSurface = EGL_NO_SURFACE;
 #endif
-    , fHGLRC(NULL)
-    , fAttached(kNone_BackEndType) {
+    fHGLRC = NULL;
+#endif
+    fAttached = kNone_BackEndType;
     gEventTarget = (HWND)hWnd;
 }
 
 SkOSWindow::~SkOSWindow() {
+#if SK_SUPPORT_GPU
     if (NULL != fHGLRC) {
         wglDeleteContext((HGLRC)fHGLRC);
     }
@@ -69,7 +72,8 @@
         eglTerminate(fDisplay);
         fDisplay = EGL_NO_DISPLAY;
     }
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
 }
 
 static SkKey winToskKey(WPARAM vk) {
@@ -305,6 +309,7 @@
     }
 }
 
+#if SK_SUPPORT_GPU
 HGLRC create_gl(HWND hwnd, int msaaSampleCount) {
 
     HDC dc = GetDC(hwnd);
@@ -563,7 +568,8 @@
 
     eglSwapBuffers(fDisplay, fSurface);
 }
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
 
 // return true on success
 bool SkOSWindow::attach(SkBackEndTypes attachType, int msaaSampleCount) {
@@ -578,6 +584,7 @@
     case kNone_BackEndType:
         // nothing to do
         break; 
+#if SK_SUPPORT_GPU
     case kNativeGL_BackEndType:
         result = attachGL(msaaSampleCount);
         break;
@@ -585,7 +592,8 @@
     case kANGLE_BackEndType:
         result = attachANGLE(msaaSampleCount);
         break;
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
     default:
         SkASSERT(false);
         result = false;
@@ -604,6 +612,7 @@
     case kNone_BackEndType:
         // nothing to do
         break; 
+#if SK_SUPPORT_GPU
     case kNativeGL_BackEndType:
         detachGL();
         break;
@@ -611,7 +620,8 @@
     case kANGLE_BackEndType:
         detachANGLE();
         break;
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
     default:
         SkASSERT(false);
         break;
@@ -624,6 +634,7 @@
     case kNone_BackEndType:
         // nothing to do
         return; 
+#if SK_SUPPORT_GPU
     case kNativeGL_BackEndType:
         presentGL();
         break;
@@ -631,7 +642,8 @@
     case kANGLE_BackEndType:
         presentANGLE();
         break;
-#endif
+#endif // SK_ANGLE
+#endif // SK_SUPPORT_GPU
     default:
         SkASSERT(false);
         break;
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
index a02f0d3..db6ffd0 100644
--- a/tests/ClipCacheTest.cpp
+++ b/tests/ClipCacheTest.cpp
@@ -5,6 +5,11 @@
  * found in the LICENSE file.
  */
 
+
+// This is a GR test
+
+#if SK_SUPPORT_GPU
+
 #include "Test.h"
 #include "SkGpuDevice.h"
 #include "../../src/gpu/GrClipMaskManager.h"
@@ -223,3 +228,5 @@
 ////////////////////////////////////////////////////////////////////////////////
 #include "TestClassDef.h"
 DEFINE_GPUTESTCLASS("ClipCache", ClipCacheTestClass, TestClipCache)
+
+#endif
diff --git a/tests/GLInterfaceValidation.cpp b/tests/GLInterfaceValidation.cpp
index 9ca2cc2..881a4c9 100755
--- a/tests/GLInterfaceValidation.cpp
+++ b/tests/GLInterfaceValidation.cpp
@@ -6,6 +6,10 @@
  * found in the LICENSE file.
  */
 
+
+// This is a GPU-backend specific test
+#if SK_SUPPORT_GPU
+
 #include "Test.h"
 #if SK_ANGLE
 #include "gl/SkANGLEGLContext.h"
@@ -77,3 +81,4 @@
                  GLInterfaceValidationTestClass,
                  GLInterfaceValidationTest)
 
+#endif
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 1eb0579..7e333f9 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -6,6 +6,9 @@
  * found in the LICENSE file.
  */
 
+// This is a GPU-backend specific test
+#if SK_SUPPORT_GPU
+
 #include "Test.h"
 #include "GrContext.h"
 #include "gl/GrGpuGL.h"
@@ -19,3 +22,4 @@
 #include "TestClassDef.h"
 DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest)
 
+#endif
diff --git a/tests/GrMemoryPoolTest.cpp b/tests/GrMemoryPoolTest.cpp
index 0426944..6c14dbe 100644
--- a/tests/GrMemoryPoolTest.cpp
+++ b/tests/GrMemoryPoolTest.cpp
@@ -5,6 +5,9 @@
  * found in the LICENSE file.
  */
 
+// This is a GPU-backend specific test
+#if SK_SUPPORT_GPU
+
 #include "Test.h"
 #include "GrMemoryPool.h"
 #include "SkRandom.h"
@@ -241,3 +244,4 @@
 #include "TestClassDef.h"
 DEFINE_TESTCLASS("GrMemoryPool", GrMemoryPoolClass, test_memory_pool)
 
+#endif
diff --git a/tests/PremulAlphaRoundTripTest.cpp b/tests/PremulAlphaRoundTripTest.cpp
index c4ec6ab..a22ff5a 100644
--- a/tests/PremulAlphaRoundTripTest.cpp
+++ b/tests/PremulAlphaRoundTripTest.cpp
@@ -9,7 +9,11 @@
 #include "Test.h"
 #include "SkCanvas.h"
 #include "SkConfig8888.h"
+#include "SkDevice.h"
+
+#if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#endif
 
 
 namespace {
@@ -52,14 +56,15 @@
                                           256,
                                           false))->unref();
         } else {
-#if SK_SCALAR_IS_FIXED
+#if !SK_SUPPORT_GPU || defined(SK_SCALAR_IS_FIXED)
             // GPU device known not to work in the fixed pt build.
             continue;
-#endif
+#else
             canvas.setDevice(new SkGpuDevice(context,
                                              SkBitmap::kARGB_8888_Config,
                                              256,
                                              256))->unref();
+#endif
         }
 
         SkBitmap readBmp1;
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index 4e0fcc6..730be05 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -8,8 +8,12 @@
 
 #include "Test.h"
 #include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkDevice.h"
 #include "SkRegion.h"
+#if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#endif
 
 
 static const int DEV_W = 100, DEV_H = 100;
@@ -305,14 +309,15 @@
                                           DEV_H,
                                           false))->unref();
         } else {
-#if SK_SCALAR_IS_FIXED
-            // GPU device known not to work in the fixed pt build.
+// GPU device known not to work in the fixed pt build.
+#if defined(SK_SCALAR_IS_FIXED) || !SK_SUPPORT_GPU
             continue;
-#endif
+#else
             canvas.setDevice(new SkGpuDevice(context,
                                              SkBitmap::kARGB_8888_Config,
                                              DEV_W,
                                              DEV_H))->unref();
+#endif
         }
         fillCanvas(&canvas);
 
diff --git a/tests/ReadWriteAlphaTest.cpp b/tests/ReadWriteAlphaTest.cpp
index fb818b3..6c1c912 100644
--- a/tests/ReadWriteAlphaTest.cpp
+++ b/tests/ReadWriteAlphaTest.cpp
@@ -6,6 +6,9 @@
  * found in the LICENSE file.
  */
 
+// This test is specific to the GPU backend.
+#if SK_SUPPORT_GPU
+
 #include "Test.h"
 #include "SkGpuDevice.h"
 
@@ -105,3 +108,4 @@
 #include "TestClassDef.h"
 DEFINE_GPUTESTCLASS("ReadWriteAlpha", ReadWriteAlphaTestClass, ReadWriteAlphaTest)
 
+#endif
diff --git a/tests/Test.cpp b/tests/Test.cpp
index 62df731..0441ab0 100644
--- a/tests/Test.cpp
+++ b/tests/Test.cpp
@@ -7,9 +7,14 @@
  */
 #include "Test.h"
 
+#include "SkTLazy.h"
+
+#if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "gl/SkNativeGLContext.h"
-#include "SkTLazy.h"
+#else
+class GrContext;
+#endif
 
 using namespace skiatest;
 
@@ -78,6 +83,7 @@
 
 
 GrContext* GpuTest::GetContext() {
+#if SK_SUPPORT_GPU
     // preserve this order, we want gGrContext destroyed after gEGLContext
     static SkTLazy<SkNativeGLContext> gGLContext;
     static SkAutoTUnref<GrContext> gGrContext;
@@ -93,5 +99,8 @@
         gGLContext.get()->makeCurrent();
     }
     return gGrContext.get();
+#else
+    return NULL;
+#endif
 }
 
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index 12b57ca..688aa5d 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -8,8 +8,14 @@
 
 #include "Test.h"
 #include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkDevice.h"
 #include "SkRegion.h"
+#if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#else
+class GrContext;
+#endif
 
 static const int DEV_W = 100, DEV_H = 100;
 static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
@@ -182,7 +188,8 @@
             b = static_cast<U8CPU>(c[2]);
             break;
         default:
-            GrCrash("Unexpected Config8888");
+            SkDEBUGFAIL("Unexpected Config8888");
+            break;
     }
     if (*premul) {
         r = SkMulDiv255Ceiling(r, a);
@@ -276,7 +283,9 @@
 
 enum DevType {
     kRaster_DevType,
+#if SK_SUPPORT_GPU
     kGpu_DevType,
+#endif
 };
 
 struct CanvasConfig {
@@ -287,7 +296,7 @@
 static const CanvasConfig gCanvasConfigs[] = {
     {kRaster_DevType, true},
     {kRaster_DevType, false},
-#ifdef SK_SCALAR_IS_FLOAT
+#if SK_SUPPORT_GPU && defined(SK_SCALAR_IS_FLOAT)
     {kGpu_DevType, true}, // row bytes has no meaning on gpu devices
 #endif
 };
@@ -307,12 +316,15 @@
                 memset(bmp.getPixels(), DEV_PAD, bmp.getSafeSize());
             }
             canvas->setDevice(new SkDevice(bmp))->unref();
-            } break;
+            break;
+        }
+#if SK_SUPPORT_GPU
         case kGpu_DevType:
             canvas->setDevice(new SkGpuDevice(grCtx,
                                               SkBitmap::kARGB_8888_Config,
                                               DEV_W, DEV_H))->unref();
             break;
+#endif
     }
     return true;
 }