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/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