Add a convenience to downcast contexts into GrDirectContext

This pattern of needing a safe downcast will continue to grow as we
add more explicit use of GrDirectContext and it's causing long ternary
operations that span multiple lines.

Change-Id: I9e2ebe5156e4245524a52d7c92ed3a8509e53151
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/300901
Commit-Queue: Adlai Holler <adlai@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
Auto-Submit: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/bench/GMBench.cpp b/bench/GMBench.cpp
index d9cd1cb..58c3186 100644
--- a/bench/GMBench.cpp
+++ b/bench/GMBench.cpp
@@ -25,8 +25,7 @@
 }
 
 void GMBench::onPerCanvasPreDraw(SkCanvas* canvas) {
-    auto direct = canvas->recordingContext() ? canvas->recordingContext()->asDirectContext()
-                                             : nullptr;
+    auto direct = GrAsDirectContext(canvas->recordingContext());
 
     if (fGM->gpuSetup(direct, canvas) != skiagm::DrawResult::kOk) {
         fGpuSetupFailed = true;
diff --git a/gm/asyncrescaleandread.cpp b/gm/asyncrescaleandread.cpp
index 43e8167..f61ec15 100644
--- a/gm/asyncrescaleandread.cpp
+++ b/gm/asyncrescaleandread.cpp
@@ -133,11 +133,9 @@
                                           bool doYUV420,
                                           SkString* errorMsg,
                                           int pad = 0) {
-    if (doYUV420) {
-        if (!canvas->recordingContext() || !canvas->recordingContext()->asDirectContext()) {
-            errorMsg->printf("YUV420 only supported on direct GPU for now.");
-            return skiagm::DrawResult::kSkip;
-        }
+    if (doYUV420 && !GrAsDirectContext(canvas->recordingContext())) {
+        errorMsg->printf("YUV420 only supported on direct GPU for now.");
+        return skiagm::DrawResult::kSkip;
     }
     if (canvas->imageInfo().colorType() == kUnknown_SkColorType) {
         *errorMsg = "Not supported on recording/vector backends.";
diff --git a/include/private/GrContext_Base.h b/include/private/GrContext_Base.h
index 42d8f71..29530af 100644
--- a/include/private/GrContext_Base.h
+++ b/include/private/GrContext_Base.h
@@ -89,4 +89,11 @@
     typedef SkRefCnt INHERITED;
 };
 
+/**
+ * Safely cast a base context to direct context.
+ */
+static inline GrDirectContext* GrAsDirectContext(GrContext_Base* base) {
+    return base ? base->asDirectContext() : nullptr;
+}
+
 #endif
diff --git a/tools/fm/fm.cpp b/tools/fm/fm.cpp
index d6bab75..7ccd1a8 100644
--- a/tools/fm/fm.cpp
+++ b/tools/fm/fm.cpp
@@ -132,8 +132,7 @@
     source->size  = gm->getISize();
     source->tweak = [gm](GrContextOptions* options) { gm->modifyGrContextOptions(options); };
     source->draw  = [gm](SkCanvas* canvas) {
-        auto direct = canvas->recordingContext() ? canvas->recordingContext()->asDirectContext()
-                                                 : nullptr;
+        auto direct = GrAsDirectContext(canvas->recordingContext());
 
         SkString err;
         switch (gm->gpuSetup(direct, canvas, &err)) {
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index 80c13a5..3198247 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -309,9 +309,7 @@
         auto restore = testCtx->makeCurrentAndAutoRestore();
         // CONTEXT TODO: makeGrContext should return an sk_sp<GrDirectContext>
         auto tmp = testCtx->makeGrContext(grOptions);
-        if (tmp) {
-            grCtx = sk_ref_sp<GrDirectContext>(tmp->asDirectContext());
-        }
+        grCtx = sk_ref_sp(GrAsDirectContext(tmp.get()));
     }
     if (!grCtx.get()) {
         return ContextInfo();
diff --git a/tools/viewer/GMSlide.cpp b/tools/viewer/GMSlide.cpp
index 788d21d..b244d9f 100644
--- a/tools/viewer/GMSlide.cpp
+++ b/tools/viewer/GMSlide.cpp
@@ -31,9 +31,7 @@
 void GMSlide::draw(SkCanvas* canvas) {
     SkString msg;
 
-    auto direct = canvas->recordingContext() ? canvas->recordingContext()->asDirectContext()
-                                             : nullptr;
-
+    auto direct = GrAsDirectContext(canvas->recordingContext());
     auto result = fGM->gpuSetup(direct, canvas, &msg);
     if (result != skiagm::GM::DrawResult::kOk) {
         return;