Don't crash if device creation fails in bench.

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://chromiumcodereview.appspot.com/16256011

git-svn-id: http://skia.googlecode.com/svn/trunk@9417 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 7aeeba6..f86d603 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -782,6 +782,8 @@
         for (int x = 0; x < configs.count(); ++x) {
             int configIndex = configs[x];
 
+            bool setupFailed = false;
+
             if (kNonRendering_Backend == gConfigs[configIndex].fBackend) {
                 if (bench->isRendering()) {
                     continue;
@@ -816,155 +818,163 @@
 
             if (kNonRendering_Backend != backend) {
                 device = make_device(outConfig, dim, backend, sampleCount, context);
-
-                switch(benchMode) {
-                    case kDeferredSilent_benchModes:
-                    case kDeferred_benchModes:
-                        canvas =
+                if (NULL == device) {
+                    SkString error;
+                    error.printf("Device creation failure for config %s. Will skip.\n", configName);
+                    logger.logError(error.c_str());
+                    setupFailed = true;
+                } else {
+                    switch(benchMode) {
+                        case kDeferredSilent_benchModes:
+                        case kDeferred_benchModes:
+                            canvas =
 #if SK_DEFERRED_CANVAS_USES_FACTORIES
-                            SkDeferredCanvas::Create(device);
+                                SkDeferredCanvas::Create(device);
 #else
-                            SkNEW_ARGS(SkDeferredCanvas, (device));
+                                SkNEW_ARGS(SkDeferredCanvas, (device));
 #endif
-                        break;
-                    case kRecord_benchModes:
-                        canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
-                            SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                        canvas->ref();
-                        break;
-                    case kPictureRecord_benchModes: {
-                        // This sets up picture-to-picture recording.
-                        // The C++ drawing calls for the benchmark are recorded into
-                        // pictureRecordFrom. As the benchmark, we will time how
-                        // long it takes to playback pictureRecordFrom into
-                        // pictureRecordTo.
-                        SkCanvas* tempCanvas = pictureRecordFrom.beginRecording(dim.fX, dim.fY,
-                            SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                        bench->draw(tempCanvas);
-                        pictureRecordFrom.endRecording();
-                        canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
-                            SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                        canvas->ref();
-                        break;
+                            break;
+                        case kRecord_benchModes:
+                            canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
+                                SkPicture::kUsePathBoundsForClip_RecordingFlag);
+                            canvas->ref();
+                            break;
+                        case kPictureRecord_benchModes: {
+                            // This sets up picture-to-picture recording.
+                            // The C++ drawing calls for the benchmark are recorded into
+                            // pictureRecordFrom. As the benchmark, we will time how
+                            // long it takes to playback pictureRecordFrom into
+                            // pictureRecordTo.
+                            SkCanvas* tempCanvas = pictureRecordFrom.beginRecording(dim.fX, dim.fY,
+                                SkPicture::kUsePathBoundsForClip_RecordingFlag);
+                            bench->draw(tempCanvas);
+                            pictureRecordFrom.endRecording();
+                            canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
+                                SkPicture::kUsePathBoundsForClip_RecordingFlag);
+                            canvas->ref();
+                            break;
+                        }
+                        case kNormal_benchModes:
+                            canvas = new SkCanvas(device);
+                            break;
+                        default:
+                            SkASSERT(0);
                     }
-                    case kNormal_benchModes:
-                        canvas = new SkCanvas(device);
-                        break;
-                    default:
-                        SkASSERT(0);
+                    device->unref();
+                    canvas->clear(SK_ColorWHITE);
                 }
-                device->unref();
-                canvas->clear(SK_ColorWHITE);
             }
             SkAutoUnref canvasUnref(canvas);
-
-            if (NULL != canvas) {
-                if (doClip) {
-                    performClip(canvas, dim.fX, dim.fY);
-                }
-                if (doScale) {
-                    performScale(canvas, dim.fX, dim.fY);
-                }
-                if (doRotate) {
-                    performRotate(canvas, dim.fX, dim.fY);
-                }
-            }
-
-            if (!loggedBenchStart) {
-                loggedBenchStart = true;
-                SkString str;
-                str.printf("running bench [%d %d] %28s", dim.fX, dim.fY, bench->getName());
-                logger.logProgress(str);
-            }
-
-            // warm up caches if needed
-            if (repeatDraw > 1 && NULL != canvas) {
-#if SK_SUPPORT_GPU
-                // purge the GPU resources to reduce variance
-                if (NULL != context) {
-                    context->freeGpuResources();
-                }
-#endif
-                SkAutoCanvasRestore acr(canvas, true);
-                if (benchMode == kPictureRecord_benchModes) {
-                    pictureRecordFrom.draw(canvas);
-                } else {
-                    bench->draw(canvas);
-                }
-
-                if (kDeferredSilent_benchModes == benchMode) {
-                    static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
-                } else {
-                    canvas->flush();
-                }
-#if SK_SUPPORT_GPU
-                if (NULL != context) {
-                    context->flush();
-                    SK_GL(*glContext, Finish());
-                }
-#endif
-            }
-
-            // record timer values for each repeat, and their sum
-            TimerData timerData(perIterTimeformat, normalTimeFormat);
-            for (int i = 0; i < repeatDraw; i++) {
-                if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)) {
-                    // This will clear the recorded commands so that they do not
-                    // accumulate.
-                    canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
-                        SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                }
-
-                timer->start(bench->getDurationScale());
+            if (!setupFailed) {
                 if (NULL != canvas) {
-                    canvas->save();
-                }
-                if (benchMode == kPictureRecord_benchModes) {
-                    pictureRecordFrom.draw(canvas);
-                } else {
-                    bench->draw(canvas);
+                    if (doClip) {
+                        performClip(canvas, dim.fX, dim.fY);
+                    }
+                    if (doScale) {
+                        performScale(canvas, dim.fX, dim.fY);
+                    }
+                    if (doRotate) {
+                        performRotate(canvas, dim.fX, dim.fY);
+                    }
                 }
 
-                if (kDeferredSilent_benchModes == benchMode) {
-                    static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
-                } else if (NULL != canvas) {
-                    canvas->flush();
+                if (!loggedBenchStart) {
+                    loggedBenchStart = true;
+                    SkString str;
+                    str.printf("running bench [%d %d] %28s", dim.fX, dim.fY, bench->getName());
+                    logger.logProgress(str);
                 }
 
-                if (NULL != canvas) {
-                    canvas->restore();
-                }
-
-                // stop the truncated timer after the last canvas call but
-                // don't wait for all the GL calls to complete
-                timer->truncatedEnd();
+                // warm up caches if needed
+                if (repeatDraw > 1 && NULL != canvas) {
 #if SK_SUPPORT_GPU
-                if (NULL != glContext) {
-                    context->flush();
-                    SK_GL(*glContext, Finish());
-                }
+                    // purge the GPU resources to reduce variance
+                    if (NULL != context) {
+                        context->freeGpuResources();
+                    }
 #endif
-                // stop the inclusive and gpu timers once all the GL calls
-                // have completed
-                timer->end();
+                    SkAutoCanvasRestore acr(canvas, true);
+                    if (benchMode == kPictureRecord_benchModes) {
+                        pictureRecordFrom.draw(canvas);
+                    } else {
+                        bench->draw(canvas);
+                    }
 
-                timerData.appendTimes(timer, repeatDraw - 1 == i);
+                    if (kDeferredSilent_benchModes == benchMode) {
+                        static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
+                    } else {
+                        canvas->flush();
+                    }
+#if SK_SUPPORT_GPU
+                    if (NULL != context) {
+                        context->flush();
+                        SK_GL(*glContext, Finish());
+                    }
+#endif
+                }
 
+                // record timer values for each repeat, and their sum
+                TimerData timerData(perIterTimeformat, normalTimeFormat);
+                for (int i = 0; i < repeatDraw; i++) {
+                    if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)) {
+                        // This will clear the recorded commands so that they do not
+                        // accumulate.
+                        canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
+                            SkPicture::kUsePathBoundsForClip_RecordingFlag);
+                    }
+
+                    timer->start(bench->getDurationScale());
+                    if (NULL != canvas) {
+                        canvas->save();
+                    }
+                    if (benchMode == kPictureRecord_benchModes) {
+                        pictureRecordFrom.draw(canvas);
+                    } else {
+                        bench->draw(canvas);
+                    }
+
+                    if (kDeferredSilent_benchModes == benchMode) {
+                        static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
+                    } else if (NULL != canvas) {
+                        canvas->flush();
+                    }
+
+                    if (NULL != canvas) {
+                        canvas->restore();
+                    }
+
+                    // stop the truncated timer after the last canvas call but
+                    // don't wait for all the GL calls to complete
+                    timer->truncatedEnd();
+#if SK_SUPPORT_GPU
+                    if (NULL != glContext) {
+                        context->flush();
+                        SK_GL(*glContext, Finish());
+                    }
+#endif
+                    // stop the inclusive and gpu timers once all the GL calls
+                    // have completed
+                    timer->end();
+
+                    timerData.appendTimes(timer, repeatDraw - 1 == i);
+
+                }
+                if (repeatDraw > 1) {
+                    SkString result = timerData.getResult(
+                                        logPerIter, printMin, repeatDraw, configName,
+                                        timerWall, truncatedTimerWall, timerCpu,
+                                        truncatedTimerCpu,
+                                        timerGpu && NULL != context);
+                    logger.logProgress(result);
+                }
+                if (outDir.size() > 0 && kNonRendering_Backend != backend) {
+                    saveFile(bench->getName(), configName, outDir.c_str(),
+                             device->accessBitmap(false));
+                }
             }
-            if (repeatDraw > 1) {
-                SkString result = timerData.getResult(logPerIter, printMin, repeatDraw, configName,
-                                                      timerWall, truncatedTimerWall, timerCpu,
-                                                      truncatedTimerCpu,
-                                                      timerGpu && NULL != context);
-                logger.logProgress(result);
+            if (loggedBenchStart) {
+                logger.logProgress(SkString("\n"));
             }
-            if (outDir.size() > 0 && kNonRendering_Backend != backend) {
-                saveFile(bench->getName(), configName, outDir.c_str(),
-                         device->accessBitmap(false));
-            }
-        }
-        if (loggedBenchStart) {
-            logger.logProgress(SkString("\n"));
         }
     }
 #if SK_SUPPORT_GPU