Add GrD3DGpu and GrD3DCaps.

With this, can specify d3d config for dm and it will create a GrContext
with GrD3DGpu (stubbed in).

Bug: skia:9935
Change-Id: I0b8635bc541c61833b08b60a9f6e1341d1373090
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271743
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 0d2e676..6be7409 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -727,6 +727,10 @@
 ]
 
 skia_direct3d_sources = [
+  "$_src/gpu/d3d/GrD3DCaps.cpp",
+  "$_src/gpu/d3d/GrD3DCaps.h",
+  "$_src/gpu/d3d/GrD3DGpu.cpp",
+  "$_src/gpu/d3d/GrD3DGpu.h",
 ]
 
 skia_dawn_sources = [
diff --git a/src/gpu/GrLegacyDirectContext.cpp b/src/gpu/GrLegacyDirectContext.cpp
index 76a0607..6b23633 100644
--- a/src/gpu/GrLegacyDirectContext.cpp
+++ b/src/gpu/GrLegacyDirectContext.cpp
@@ -23,6 +23,9 @@
 #ifdef SK_VULKAN
 #include "src/gpu/vk/GrVkGpu.h"
 #endif
+#ifdef SK_DIRECT3D
+#include "src/gpu/d3d/GrD3DGpu.h"
+#endif
 #ifdef SK_DAWN
 #include "src/gpu/dawn/GrDawnGpu.h"
 #endif
@@ -230,18 +233,17 @@
 
 sk_sp<GrContext> GrContext::MakeDirect3D(const GrD3DBackendContext& backendContext,
                                          const GrContextOptions& options) {
-    return nullptr;
-    //sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDirect3D, options));
+    sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDirect3D, options));
 
-    //context->fGpu = GrD3DGpu::Make(backendContext, options, context.get());
-    //if (!context->fGpu) {
-    //    return nullptr;
-    //}
+    context->fGpu = GrD3DGpu::Make(backendContext, options, context.get());
+    if (!context->fGpu) {
+        return nullptr;
+    }
 
-    //if (!context->init(context->fGpu->refCaps())) {
-    //    return nullptr;
-    //}
-    //return context;
+    if (!context->init(context->fGpu->refCaps())) {
+        return nullptr;
+    }
+    return context;
 }
 #endif
 
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index bd7c6ec..916d0fc 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -69,6 +69,7 @@
 
 protected:
     friend class GrDawnCaps;
+    friend class GrD3DCaps;
     friend class GrGLCaps;
     friend class GrMockCaps;
     friend class GrMtlCaps;
diff --git a/src/gpu/d3d/GrD3DCaps.cpp b/src/gpu/d3d/GrD3DCaps.cpp
new file mode 100644
index 0000000..fffc242
--- /dev/null
+++ b/src/gpu/d3d/GrD3DCaps.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/d3d/GrD3DBackendContext.h"
+
+#include "src/gpu/GrProgramDesc.h"
+#include "src/gpu/GrShaderCaps.h"
+#include "src/gpu/d3d/GrD3DCaps.h"
+#include "src/gpu/d3d/GrD3DGpu.h"
+
+GrD3DCaps::GrD3DCaps(const GrContextOptions& contextOptions, GrProtected isProtected)
+        : INHERITED(contextOptions) {
+    /**************************************************************************
+     * GrCaps fields
+     **************************************************************************/
+    fMipMapSupport = true;   // always available in Direct3D
+    fNPOTTextureTileSupport = false;  // TODO: figure this out
+    fReuseScratchTextures = true; //TODO: figure this out
+    fGpuTracingSupport = false; //TODO: figure this out
+    fOversizedStencilSupport = false; //TODO: figure this out
+    fInstanceAttribSupport = true;
+
+    // TODO: implement these
+    fSemaphoreSupport = false;
+    fFenceSyncSupport = false;
+    fCrossContextTextureSupport = false;
+    fHalfFloatVertexAttributeSupport = false;
+
+    // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
+    fReadPixelsRowBytesSupport = true;
+    fWritePixelsRowBytesSupport = true;
+
+    // TODO: figure this out
+    fTransferFromBufferToTextureSupport = false;
+    fTransferFromSurfaceToBufferSupport = false;
+
+    // TODO: figure this out
+    fMaxRenderTargetSize = 4096;
+    fMaxTextureSize = 4096;
+
+    fDynamicStateArrayGeometryProcessorTextureSupport = false; // TODO: figure this out
+
+    fShaderCaps.reset(new GrShaderCaps(contextOptions));
+
+    this->init(contextOptions);
+}
+
+bool GrD3DCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
+                                const SkIRect& srcRect, const SkIPoint& dstPoint) const {
+    return false;
+}
+
+void GrD3DCaps::init(const GrContextOptions& contextOptions) {
+    // TODO
+
+    this->finishInitialization(contextOptions);
+}
+
+
+
+bool GrD3DCaps::isFormatSRGB(const GrBackendFormat& format) const {
+    // TODO
+    return false;
+}
+
+SkImage::CompressionType GrD3DCaps::compressionType(const GrBackendFormat& format) const {
+    // TODO
+    return SkImage::CompressionType::kNone;
+}
+
+bool GrD3DCaps::isFormatTexturableAndUploadable(GrColorType ct,
+                                               const GrBackendFormat& format) const {
+    // TODO
+    return false;
+}
+
+bool GrD3DCaps::isFormatTexturable(const GrBackendFormat& format) const {
+    // TODO
+    return false;
+}
+
+bool GrD3DCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
+                                             int sampleCount) const {
+    if (!this->isFormatRenderable(format, sampleCount)) {
+        return false;
+    }
+    // TODO
+    return false;
+}
+
+bool GrD3DCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
+    // TODO
+    return false;
+}
+
+int GrD3DCaps::getRenderTargetSampleCount(int requestedCount,
+                                         const GrBackendFormat& format) const {
+    // TODO
+    return 0;
+}
+
+int GrD3DCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
+    // TODO
+    return 0;
+}
+
+size_t GrD3DCaps::bytesPerPixel(const GrBackendFormat& format) const {
+    // TODO
+    return 0;
+}
+
+GrCaps::SupportedWrite GrD3DCaps::supportedWritePixelsColorType(GrColorType surfaceColorType,
+                                                               const GrBackendFormat& surfaceFormat,
+                                                               GrColorType srcColorType) const {
+    // TODO
+    return {GrColorType::kUnknown, 0};
+}
+
+GrCaps::SurfaceReadPixelsSupport GrD3DCaps::surfaceSupportsReadPixels(
+        const GrSurface* surface) const {
+    if (surface->isProtected()) {
+        return SurfaceReadPixelsSupport::kUnsupported;
+    }
+    // TODO
+    return SurfaceReadPixelsSupport::kUnsupported;
+}
+
+bool GrD3DCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
+    // TODO
+    return false;
+}
+
+bool GrD3DCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
+                                                 const GrBackendFormat& format) const {
+    // TODO
+    return false;
+}
+
+GrColorType GrD3DCaps::getYUVAColorTypeFromBackendFormat(const GrBackendFormat& format,
+                                                        bool isAlphaChannel) const {
+    // TODO
+    return GrColorType::kUnknown;
+}
+
+GrBackendFormat GrD3DCaps::onGetDefaultBackendFormat(GrColorType ct,
+                                                    GrRenderable renderable) const {
+    // TODO
+    return GrBackendFormat();
+}
+
+GrBackendFormat GrD3DCaps::getBackendFormatFromCompressionType(
+        SkImage::CompressionType compressionType) const {
+    // TODO
+    return {};
+}
+
+GrSwizzle GrD3DCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+    // TODO
+    return GrSwizzle::RGBA();
+}
+
+GrSwizzle GrD3DCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+    // TODO
+    return GrSwizzle::RGBA();
+}
+
+uint64_t GrD3DCaps::computeFormatKey(const GrBackendFormat& format) const {
+    // TODO
+    return (uint64_t)0;
+}
+
+GrCaps::SupportedRead GrD3DCaps::onSupportedReadPixelsColorType(
+        GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
+        GrColorType dstColorType) const {
+    // TODO
+    return {GrColorType::kUnknown, 0};
+}
+
+void GrD3DCaps::addExtraSamplerKey(GrProcessorKeyBuilder* b,
+                                  GrSamplerState samplerState,
+                                  const GrBackendFormat& format) const {
+    // TODO
+}
+
+/**
+ * TODO: Determin what goes in the ProgramDesc
+ */
+GrProgramDesc GrD3DCaps::makeDesc(const GrRenderTarget* rt, const GrProgramInfo& programInfo) const {
+    GrProgramDesc desc;
+    if (!GrProgramDesc::Build(&desc, rt, programInfo, *this)) {
+        SkASSERT(!desc.isValid());
+        return desc;
+    }
+
+    GrProcessorKeyBuilder b(&desc.key());
+
+    // TODO: add D3D-specific information
+
+    return desc;
+}
+
+#if GR_TEST_UTILS
+std::vector<GrCaps::TestFormatColorTypeCombination> GrD3DCaps::getTestingCombinations() const {
+    std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
+        // TODO: fill in combos
+    };
+
+    return combos;
+}
+#endif
diff --git a/src/gpu/d3d/GrD3DCaps.h b/src/gpu/d3d/GrD3DCaps.h
new file mode 100644
index 0000000..5627e0e
--- /dev/null
+++ b/src/gpu/d3d/GrD3DCaps.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrD3DCaps_DEFINED
+#define GrD3DCaps_DEFINED
+
+#include "src/gpu/GrCaps.h"
+
+class GrShaderCaps;
+
+/**
+ * Stores some capabilities of a D3D backend.
+ */
+class GrD3DCaps : public GrCaps {
+public:
+    /**
+     * Creates a GrD3DCaps that is set such that nothing is supported. The init function should
+     * be called to fill out the caps.
+     */
+    GrD3DCaps(const GrContextOptions& contextOptions, GrProtected isProtected = GrProtected::kNo);
+
+    bool isFormatSRGB(const GrBackendFormat&) const override;
+    SkImage::CompressionType compressionType(const GrBackendFormat&) const override;
+
+    bool isFormatTexturableAndUploadable(GrColorType, const GrBackendFormat&) const override;
+    bool isFormatTexturable(const GrBackendFormat&) const override;
+
+    bool isFormatCopyable(const GrBackendFormat&) const override { return true; }
+
+    bool isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
+                                       int sampleCount = 1) const override;
+    bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override;
+
+    int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override;
+
+    int maxRenderTargetSampleCount(const GrBackendFormat&) const override;
+
+    size_t bytesPerPixel(const GrBackendFormat&) const override;
+
+    SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType,
+                                                 const GrBackendFormat& surfaceFormat,
+                                                 GrColorType srcColorType) const override;
+
+    SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;
+
+    GrColorType getYUVAColorTypeFromBackendFormat(const GrBackendFormat&,
+                                                  bool isAlphaChannel) const override;
+
+    GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
+
+    GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override;
+    GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
+
+    uint64_t computeFormatKey(const GrBackendFormat&) const override;
+
+    void addExtraSamplerKey(GrProcessorKeyBuilder*,
+                            GrSamplerState,
+                            const GrBackendFormat&) const override;
+
+    GrProgramDesc makeDesc(const GrRenderTarget*, const GrProgramInfo&) const override;
+
+#if GR_TEST_UTILS
+    std::vector<TestFormatColorTypeCombination> getTestingCombinations() const override;
+#endif
+
+private:
+    void init(const GrContextOptions& contextOptions);
+
+    bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
+    bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
+                          const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
+    GrBackendFormat onGetDefaultBackendFormat(GrColorType, GrRenderable) const override;
+
+    bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override;
+
+    SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
+                                                 GrColorType) const override;
+
+    typedef GrCaps INHERITED;
+};
+
+#endif
diff --git a/src/gpu/d3d/GrD3DGpu.cpp b/src/gpu/d3d/GrD3DGpu.cpp
new file mode 100644
index 0000000..aad3586
--- /dev/null
+++ b/src/gpu/d3d/GrD3DGpu.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/d3d/GrD3DCaps.h"
+#include "src/gpu/d3d/GrD3DGpu.h"
+
+sk_sp<GrGpu> GrD3DGpu::Make(const GrD3DBackendContext& backendContext,
+                            const GrContextOptions& contextOptions, GrContext* context) {
+    return sk_sp<GrGpu>(new GrD3DGpu(context, contextOptions, backendContext));
+}
+
+GrD3DGpu::GrD3DGpu(GrContext* context, const GrContextOptions& contextOptions,
+                   const GrD3DBackendContext& backendContext)
+        : INHERITED(context) {
+    fCaps.reset(new GrD3DCaps(contextOptions));
+}
+
+GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
+    GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+    const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
+    const GrOpsRenderPass::StencilLoadAndStoreInfo&,
+    const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
+    // TODO
+    return nullptr;
+}
+
+void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
+    // TODO: actually submit something here
+    delete renderPass;
+}
+
+void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
+    // TODO
+}
+
+sk_sp<GrTexture> GrD3DGpu::onCreateTexture(SkISize dimensions,
+                                           const GrBackendFormat& format,
+                                           GrRenderable renderable,
+                                           int renderTargetSampleCnt,
+                                           SkBudgeted budgeted,
+                                           GrProtected isProtected,
+                                           int mipLevelCount,
+                                           uint32_t levelClearMask) {
+    // TODO
+    return nullptr;
+}
+
+sk_sp<GrTexture> GrD3DGpu::onCreateCompressedTexture(SkISize dimensions,
+                                                     const GrBackendFormat& format,
+                                                     SkBudgeted budgeted,
+                                                     GrMipMapped mipMapped,
+                                                     GrProtected isProtected,
+                                                     const void* data, size_t dataSize) {
+    // TODO
+    return nullptr;
+}
+
+sk_sp<GrTexture> GrD3DGpu::onWrapBackendTexture(const GrBackendTexture& tex, GrColorType colorType,
+                                                GrWrapOwnership ownership,
+                                                GrWrapCacheable wrapType, GrIOType ioType) {
+    // TODO
+    return nullptr;
+}
+
+sk_sp<GrTexture> GrD3DGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
+                                                          GrWrapOwnership ownership,
+                                                          GrWrapCacheable wrapType) {
+    return nullptr;
+}
+
+sk_sp<GrTexture> GrD3DGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
+                                                          int sampleCnt,
+                                                          GrColorType colorType,
+                                                          GrWrapOwnership ownership,
+                                                          GrWrapCacheable cacheable) {
+    // TODO
+    return nullptr;
+}
+
+sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt,
+                                                          GrColorType colorType) {
+    // TODO
+    return nullptr;
+}
+
+sk_sp<GrRenderTarget> GrD3DGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
+                                                                    int sampleCnt,
+                                                                    GrColorType colorType) {
+    // TODO
+    return nullptr;
+}
+
+sk_sp<GrGpuBuffer> GrD3DGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
+                                             GrAccessPattern accessPattern, const void*) {
+    // TODO
+    return nullptr;
+}
+
+GrStencilAttachment* GrD3DGpu::createStencilAttachmentForRenderTarget(
+        const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
+    // TODO
+    return nullptr;
+}
+
+GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
+                                                   const GrBackendFormat& format,
+                                                   GrRenderable,
+                                                   GrMipMapped mipMapped,
+                                                   GrProtected,
+                                                   const BackendTextureData*) {
+    // TODO
+    return GrBackendTexture();
+}
+
+GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
+                                                             const GrBackendFormat& format,
+                                                             GrMipMapped mipMapped,
+                                                             GrProtected,
+                                                             const BackendTextureData*) {
+    // TODO
+    return GrBackendTexture();
+}
+
+void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
+    // TODO
+}
+
+#if GR_TEST_UTILS
+bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
+    // TODO
+    return false;
+}
+
+GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
+                                                                      GrColorType colorType) {
+    // TODO
+    return GrBackendRenderTarget();
+}
+
+void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
+#endif
diff --git a/src/gpu/d3d/GrD3DGpu.h b/src/gpu/d3d/GrD3DGpu.h
new file mode 100644
index 0000000..b30d28e
--- /dev/null
+++ b/src/gpu/d3d/GrD3DGpu.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrD3DGpu_DEFINED
+#define GrD3DGpu_DEFINED
+
+#include "include/gpu/d3d/GrD3DBackendContext.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrRenderTarget.h"
+#include "src/gpu/GrSemaphore.h"
+#include "src/gpu/d3d/GrD3DCaps.h"
+
+class GrD3DOpsRenderPass;
+struct GrD3DOptions;
+class GrPipeline;
+
+class GrD3DGpu : public GrGpu {
+public:
+    static sk_sp<GrGpu> Make(const GrD3DBackendContext& backendContext, const GrContextOptions&,
+                             GrContext*);
+
+    ~GrD3DGpu() override {}
+
+    GrOpsRenderPass* getOpsRenderPass(
+            GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+            const GrOpsRenderPass::LoadAndStoreInfo&,
+            const GrOpsRenderPass::StencilLoadAndStoreInfo&,
+            const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
+
+    GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; }
+    bool waitFence(GrFence, uint64_t) override { return true; }
+    void deleteFence(GrFence) const override {}
+
+    std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
+        return nullptr;
+    }
+    std::unique_ptr<GrSemaphore> wrapBackendSemaphore(
+            const GrBackendSemaphore& semaphore,
+            GrResourceProvider::SemaphoreWrapType wrapType,
+            GrWrapOwnership ownership) override {
+        return nullptr;
+    }
+    void insertSemaphore(GrSemaphore* semaphore) override {}
+    void waitSemaphore(GrSemaphore* semaphore) override {}
+    std::unique_ptr<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override {
+        return nullptr;
+    }
+
+    void submit(GrOpsRenderPass* renderPass) override;
+
+    void checkFinishProcs() override {}
+
+private:
+    GrD3DGpu(GrContext* context, const GrContextOptions&, const GrD3DBackendContext&);
+
+    void onResetContext(uint32_t resetBits) override {}
+
+    void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>* sampleLocations) override;
+
+    void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
+
+    sk_sp<GrTexture> onCreateTexture(SkISize,
+                                     const GrBackendFormat&,
+                                     GrRenderable,
+                                     int renderTargetSampleCnt,
+                                     SkBudgeted,
+                                     GrProtected,
+                                     int mipLevelCount,
+                                     uint32_t levelClearMask) override;
+
+    sk_sp<GrTexture> onCreateCompressedTexture(SkISize dimensions,
+                                               const GrBackendFormat&,
+                                               SkBudgeted,
+                                               GrMipMapped,
+                                               GrProtected,
+                                               const void* data, size_t dataSize) override;
+
+    sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrColorType, GrWrapOwnership,
+                                          GrWrapCacheable, GrIOType) override;
+    sk_sp<GrTexture> onWrapCompressedBackendTexture(const GrBackendTexture&, GrWrapOwnership,
+                                                    GrWrapCacheable) override;
+
+    sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
+                                                    int sampleCnt,
+                                                    GrColorType,
+                                                    GrWrapOwnership,
+                                                    GrWrapCacheable) override;
+
+    sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&,
+                                                    GrColorType) override;
+
+    sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
+                                                             int sampleCnt, GrColorType) override;
+
+    sk_sp<GrGpuBuffer> onCreateBuffer(size_t sizeInBytes, GrGpuBufferType, GrAccessPattern,
+                                      const void*) override;
+
+    bool onReadPixels(GrSurface* surface, int left, int top, int width, int height,
+                      GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
+                      size_t rowBytes) override {
+        return true;
+    }
+
+    bool onWritePixels(GrSurface* surface, int left, int top, int width, int height,
+                       GrColorType surfaceColorType, GrColorType srcColorType,
+                       const GrMipLevel texels[], int mipLevelCount,
+                       bool prepForTexSampling) override {
+        return true;
+    }
+
+    bool onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
+                            GrColorType surfaceColorType, GrColorType bufferColorType,
+                            GrGpuBuffer* transferBuffer, size_t offset, size_t rowBytes) override {
+        return true;
+    }
+    bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
+                              GrColorType surfaceColorType, GrColorType bufferColorType,
+                              GrGpuBuffer* transferBuffer, size_t offset) override {
+        return true;
+    }
+    bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
+                       const SkIPoint& dstPoint) override {
+        return true;
+    }
+
+    bool onRegenerateMipMapLevels(GrTexture*) override { return true; }
+
+    void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, ForExternalIO) override {}
+
+    bool onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
+                       const GrFlushInfo& info, const GrPrepareForExternalIORequests&) override {
+        if (info.fFinishedProc) {
+            info.fFinishedProc(info.fFinishedContext);
+        }
+        return true;
+    }
+
+    GrStencilAttachment* createStencilAttachmentForRenderTarget(
+            const GrRenderTarget*, int width, int height, int numStencilSamples) override;
+    GrBackendTexture onCreateBackendTexture(SkISize dimensions,
+                                            const GrBackendFormat&,
+                                            GrRenderable,
+                                            GrMipMapped,
+                                            GrProtected,
+                                            const BackendTextureData*) override;
+    GrBackendTexture onCreateCompressedBackendTexture(SkISize dimensions,
+                                                      const GrBackendFormat&,
+                                                      GrMipMapped,
+                                                      GrProtected,
+                                                      const BackendTextureData*) override;
+    void deleteBackendTexture(const GrBackendTexture&) override;
+
+#if GR_TEST_UTILS
+    bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
+
+    GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
+    void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
+
+    void testingOnly_flushGpuAndSync() override {}
+#endif
+
+    typedef GrGpu INHERITED;
+};
+
+#endif
diff --git a/tools/flags/CommonFlagsConfig.cpp b/tools/flags/CommonFlagsConfig.cpp
index 1e8b790..2d80f3c 100644
--- a/tools/flags/CommonFlagsConfig.cpp
+++ b/tools/flags/CommonFlagsConfig.cpp
@@ -108,6 +108,9 @@
     { "mtlmsaa4",              "gpu", "api=metal,samples=4" },
     { "mtlmsaa8",              "gpu", "api=metal,samples=8" },
 #endif
+#ifdef SK_DIRECT3D
+    { "d3d",                   "gpu", "api=direct3d" },
+#endif
 };
 // clang-format on
 
@@ -273,6 +276,12 @@
         return true;
     }
 #endif
+#ifdef SK_DIRECT3D
+    if (value.equals("direct3d")) {
+        *outContextType = GrContextFactory::kDirect3D_ContextType;
+        return true;
+    }
+#endif
 #ifdef SK_DAWN
     if (value.equals("dawn")) {
         *outContextType = GrContextFactory::kDawn_ContextType;