More fixes to get D3D tests running.

* Set up D3D backend texture creation
* Fix GrD3DBackendSurfaceInfo initialization
* Minor fix to get wrapped RTs into the cache

Bug: skia:9935
Change-Id: Ic5319a7d059c4d969894529a326a91de0192f9eb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/282679
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/include/private/GrD3DTypesPriv.h b/include/private/GrD3DTypesPriv.h
index 884a24e..fa42afa 100644
--- a/include/private/GrD3DTypesPriv.h
+++ b/include/private/GrD3DTypesPriv.h
@@ -42,7 +42,7 @@
 #endif
 
 private:
-    std::unique_ptr<GrD3DTextureResourceInfo> fTextureResourceInfo;
+    GrD3DTextureResourceInfo* fTextureResourceInfo;
     GrD3DResourceState* fResourceState;
 };
 
diff --git a/src/gpu/d3d/GrD3DGpu.cpp b/src/gpu/d3d/GrD3DGpu.cpp
index b8b85fe..3e3951a 100644
--- a/src/gpu/d3d/GrD3DGpu.cpp
+++ b/src/gpu/d3d/GrD3DGpu.cpp
@@ -7,7 +7,9 @@
 
 #include "src/gpu/d3d/GrD3DGpu.h"
 
+#include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/d3d/GrD3DBackendContext.h"
+#include "src/core/SkMipMap.h"
 #include "src/gpu/d3d/GrD3DBuffer.h"
 #include "src/gpu/d3d/GrD3DCaps.h"
 #include "src/gpu/d3d/GrD3DOpsRenderPass.h"
@@ -183,7 +185,7 @@
     resourceDesc.SampleDesc.Count = 1;
     resourceDesc.SampleDesc.Quality = 0; // quality levels are only supported for tiled resources
                                          // so ignore for now
-    resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;  // use driver-selected swizzle for now
+    resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;  // use driver-selected swizzle
     resourceDesc.Flags = usageFlags;
 
     GrMipMapsStatus mipMapsStatus =
@@ -420,27 +422,140 @@
     return nullptr;
 }
 
+bool GrD3DGpu::createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
+                                                      SkISize dimensions,
+                                                      GrTexturable texturable,
+                                                      GrRenderable renderable,
+                                                      GrMipMapped mipMapped,
+                                                      GrD3DTextureResourceInfo* info,
+                                                      GrProtected isProtected,
+                                                      const BackendTextureData* data) {
+    SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
+    if (texturable == GrTexturable::kNo) {
+        SkASSERT(!data && mipMapped == GrMipMapped::kNo);
+    }
+
+    if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
+        return false;
+    }
+
+    if (texturable == GrTexturable::kYes && !this->d3dCaps().isFormatTexturable(dxgiFormat)) {
+        return false;
+    }
+
+    if (renderable == GrRenderable::kYes && !this->d3dCaps().isFormatRenderable(dxgiFormat, 1)) {
+        return false;
+    }
+
+    int numMipLevels = 1;
+    if (mipMapped == GrMipMapped::kYes) {
+        numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
+    }
+
+    // create the texture
+    D3D12_RESOURCE_FLAGS usageFlags = D3D12_RESOURCE_FLAG_NONE;
+    if (renderable == GrRenderable::kYes) {
+        usageFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+    }
+
+    D3D12_RESOURCE_DESC resourceDesc;
+    resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+    resourceDesc.Alignment = 0; // use default alignment
+    resourceDesc.Width = dimensions.fWidth;
+    resourceDesc.Height = dimensions.fHeight;
+    resourceDesc.DepthOrArraySize = 1;
+    resourceDesc.MipLevels = numMipLevels;
+    resourceDesc.Format = dxgiFormat;
+    resourceDesc.SampleDesc.Count = 1;
+    resourceDesc.SampleDesc.Quality = 0; // quality levels are only supported for tiled resources
+                                         // so ignore for now
+    resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // use driver-selected swizzle
+    resourceDesc.Flags = usageFlags;
+
+    if (!GrD3DTextureResource::InitTextureResourceInfo(this, resourceDesc, isProtected, info)) {
+        SkDebugf("Failed to init texture resource info\n");
+        return false;
+    }
+
+    if (!data) {
+        return true;
+    }
+
+    // TODO: upload the data
+
+    return true;
+}
+
 GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
                                                   const GrBackendFormat& format,
-                                                  GrRenderable,
+                                                  GrRenderable renderable,
                                                   GrMipMapped mipMapped,
-                                                  GrProtected,
-                                                  const BackendTextureData*) {
-    // TODO
-    return GrBackendTexture();
+                                                  GrProtected isProtected,
+                                                  const BackendTextureData* data) {
+    this->handleDirtyContext();
+
+    const GrD3DCaps& caps = this->d3dCaps();
+
+    if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
+        return {};
+    }
+
+    DXGI_FORMAT dxgiFormat;
+    if (!format.asDxgiFormat(&dxgiFormat)) {
+        return {};
+    }
+
+    // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
+    if (!caps.isFormatTexturable(dxgiFormat)) {
+        return {};
+    }
+
+    GrD3DTextureResourceInfo info;
+    if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
+                                                      renderable, mipMapped,
+                                                      &info, isProtected, data)) {
+        return {};
+    }
+
+    return GrBackendTexture(dimensions.width(), dimensions.height(), info);
 }
 
 GrBackendTexture GrD3DGpu::onCreateCompressedBackendTexture(SkISize dimensions,
                                                             const GrBackendFormat& format,
                                                             GrMipMapped mipMapped,
-                                                            GrProtected,
-                                                            const BackendTextureData*) {
-    // TODO
-    return GrBackendTexture();
+                                                            GrProtected isProtected,
+                                                            const BackendTextureData* data) {
+    this->handleDirtyContext();
+
+    const GrD3DCaps& caps = this->d3dCaps();
+
+    if (this->protectedContext() != (isProtected == GrProtected::kYes)) {
+        return {};
+    }
+
+    DXGI_FORMAT dxgiFormat;
+    if (!format.asDxgiFormat(&dxgiFormat)) {
+        return {};
+    }
+
+    // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
+    if (!caps.isFormatTexturable(dxgiFormat)) {
+        return {};
+    }
+
+    GrD3DTextureResourceInfo info;
+    if (!this->createTextureResourceForBackendSurface(dxgiFormat, dimensions, GrTexturable::kYes,
+                                                      GrRenderable::kNo, mipMapped,
+                                                      &info, isProtected, data)) {
+        return {};
+    }
+
+    return GrBackendTexture(dimensions.width(), dimensions.height(), info);
 }
 
 void GrD3DGpu::deleteBackendTexture(const GrBackendTexture& tex) {
-    // TODO
+    SkASSERT(GrBackendApi::kDirect3D == tex.fBackend);
+    // Nothing to do here, will get cleaned up when the GrBackendTexture object goes away
 }
 
 bool GrD3DGpu::compile(const GrProgramDesc&, const GrProgramInfo&) {
@@ -449,15 +564,51 @@
 
 #if GR_TEST_UTILS
 bool GrD3DGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
-    // TODO
-    return false;
+    SkASSERT(GrBackendApi::kDirect3D == tex.backend());
+
+    GrD3DTextureResourceInfo info;
+    if (!tex.getD3DTextureResourceInfo(&info)) {
+        return false;
+    }
+    ID3D12Resource* textureResource = info.fResource.get();
+    if (!textureResource) {
+        return false;
+    }
+    return !(textureResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
 }
 
 GrBackendRenderTarget GrD3DGpu::createTestingOnlyBackendRenderTarget(int w, int h,
                                                                      GrColorType colorType) {
-    // TODO
-    return GrBackendRenderTarget();
+    this->handleDirtyContext();
+
+    if (w > this->caps()->maxRenderTargetSize() || h > this->caps()->maxRenderTargetSize()) {
+        return GrBackendRenderTarget();
+    }
+
+    DXGI_FORMAT dxgiFormat = this->d3dCaps().getFormatFromColorType(colorType);
+
+    GrD3DTextureResourceInfo info;
+    if (!this->createTextureResourceForBackendSurface(dxgiFormat, { w, h }, GrTexturable::kNo,
+                                                      GrRenderable::kYes, GrMipMapped::kNo,
+                                                      &info, GrProtected::kNo, nullptr)) {
+        return {};
+    }
+
+    return GrBackendRenderTarget(w, h, 1, info);
 }
 
-void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
+void GrD3DGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
+    SkASSERT(GrBackendApi::kDirect3D == rt.backend());
+
+    GrD3DTextureResourceInfo info;
+    if (rt.getD3DTextureResourceInfo(&info)) {
+        this->testingOnly_flushGpuAndSync();
+        // Nothing else to do here, will get cleaned up when the GrBackendRenderTarget
+        // is deleted.
+    }
+}
+
+void GrD3DGpu::testingOnly_flushGpuAndSync() {
+    // TODO
+}
 #endif
diff --git a/src/gpu/d3d/GrD3DGpu.h b/src/gpu/d3d/GrD3DGpu.h
index 1d8e016..a8bb98b 100644
--- a/src/gpu/d3d/GrD3DGpu.h
+++ b/src/gpu/d3d/GrD3DGpu.h
@@ -49,7 +49,7 @@
     GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
     void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
 
-    void testingOnly_flushGpuAndSync() override {}
+    void testingOnly_flushGpuAndSync() override;
 #endif
 
     GrStencilAttachment* createStencilAttachmentForRenderTarget(
@@ -184,6 +184,15 @@
 
     void checkForFinishedCommandLists();
 
+    bool createTextureResourceForBackendSurface(DXGI_FORMAT dxgiFormat,
+                                                SkISize dimensions,
+                                                GrTexturable texturable,
+                                                GrRenderable renderable,
+                                                GrMipMapped mipMapped,
+                                                GrD3DTextureResourceInfo* info,
+                                                GrProtected isProtected,
+                                                const BackendTextureData* data);
+
     gr_cp<ID3D12Device> fDevice;
     gr_cp<ID3D12CommandQueue> fQueue;
 
diff --git a/src/gpu/d3d/GrD3DRenderTarget.cpp b/src/gpu/d3d/GrD3DRenderTarget.cpp
index c70ddfe..793c4b1 100644
--- a/src/gpu/d3d/GrD3DRenderTarget.cpp
+++ b/src/gpu/d3d/GrD3DRenderTarget.cpp
@@ -113,9 +113,9 @@
                                   static_cast<D3D12_RESOURCE_STATES>(msInfo.fResourceState)));
 
         d3dRT = new GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, std::move(state), msInfo,
-                                      std::move(msState));
+                                      std::move(msState), kWrapped);
     } else {
-        d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state));
+        d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), kWrapped);
     }
 
     return sk_sp<GrD3DRenderTarget>(d3dRT);
diff --git a/src/gpu/d3d/GrD3DRenderTarget.h b/src/gpu/d3d/GrD3DRenderTarget.h
index 8e69adb..220e944 100644
--- a/src/gpu/d3d/GrD3DRenderTarget.h
+++ b/src/gpu/d3d/GrD3DRenderTarget.h
@@ -39,7 +39,7 @@
     GrD3DTextureResource* msaaTextureResource() { return fMSAATextureResource.get(); }
 
     bool canAttemptStencilAttachment() const override {
-        return false; // For now
+        return true;
     }
 
     GrBackendRenderTarget getBackendRenderTarget() const override;
diff --git a/src/gpu/d3d/GrD3DTypesPriv.cpp b/src/gpu/d3d/GrD3DTypesPriv.cpp
index b50c503..a84ea7e 100644
--- a/src/gpu/d3d/GrD3DTypesPriv.cpp
+++ b/src/gpu/d3d/GrD3DTypesPriv.cpp
@@ -18,13 +18,17 @@
 void GrD3DBackendSurfaceInfo::cleanup() {
     SkSafeUnref(fResourceState);
     fResourceState = nullptr;
+    delete fTextureResourceInfo;
+    fTextureResourceInfo = nullptr;
 };
 
 void GrD3DBackendSurfaceInfo::assign(const GrD3DBackendSurfaceInfo& that, bool isThisValid) {
-    fTextureResourceInfo.reset(new GrD3DTextureResourceInfo(*that.fTextureResourceInfo));
+    GrD3DTextureResourceInfo* oldInfo = fTextureResourceInfo;
     GrD3DResourceState* oldLayout = fResourceState;
+    fTextureResourceInfo = new GrD3DTextureResourceInfo(*that.fTextureResourceInfo);
     fResourceState = SkSafeRef(that.fResourceState);
     if (isThisValid) {
+        delete oldInfo;
         SkSafeUnref(oldLayout);
     }
 }
@@ -44,6 +48,7 @@
 }
 
 bool GrD3DBackendSurfaceInfo::isProtected() const {
+    SkASSERT(fTextureResourceInfo);
     return fTextureResourceInfo->fProtected == GrProtected::kYes;
 }