MSAA improvements for Direct3D.

* Fixes quality value
* Enables grabbing sample positions
* Enables centering samples for non-hardware AA

Change-Id: I5cabc0804b4a57347b7072b100c17310155c0ebc
Bug: skia:10476
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/308798
Reviewed-by: Brian Salomon <bsalomon@google.com>
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 1f91bf9..558412e 100644
--- a/src/gpu/d3d/GrD3DGpu.cpp
+++ b/src/gpu/d3d/GrD3DGpu.cpp
@@ -216,8 +216,59 @@
     fCurrentDirectCommandList->addFinishedCallback(std::move(finishedCallback));
 }
 
-void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
-    // TODO
+void GrD3DGpu::querySampleLocations(GrRenderTarget* renderTarget,
+                                    SkTArray<SkPoint>* sampleLocations) {
+    // By default, the Direct3D backend uses the standard sample locations defined by the docs.
+    // These are transformed from D3D's integer coordinate system with origin at the center,
+    // to our normalized coordinate system with origin at the upper left.
+    // This ends up corresponding with Vulkan's sample locations.
+    SkASSERT(this->caps()->sampleLocationsSupport());
+    static constexpr SkPoint kStandardSampleLocations_1[1] = {
+        {0.5f, 0.5f} };
+    static constexpr SkPoint kStandardSampleLocations_2[2] = {
+        {0.75f, 0.75f}, {0.25f, 0.25f} };
+    static constexpr SkPoint kStandardSampleLocations_4[4] = {
+        {0.375f, 0.125f}, {0.875f, 0.375f}, {0.125f, 0.625f}, {0.625f, 0.875f} };
+    static constexpr SkPoint kStandardSampleLocations_8[8] = {
+        {0.5625f, 0.3125f}, {0.4375f, 0.6875f}, {0.8125f, 0.5625f}, {0.3125f, 0.1875f},
+        {0.1875f, 0.8125f}, {0.0625f, 0.4375f}, {0.6875f, 0.9375f}, {0.9375f, 0.0625f} };
+    static constexpr SkPoint kStandardSampleLocations_16[16] = {
+        {0.5625f, 0.5625f}, {0.4375f, 0.3125f}, {0.3125f, 0.625f}, {0.75f, 0.4375f},
+        {0.1875f, 0.375f}, {0.625f, 0.8125f}, {0.8125f, 0.6875f}, {0.6875f, 0.1875f},
+        {0.375f, 0.875f}, {0.5f, 0.0625f}, {0.25f, 0.125f}, {0.125f, 0.75f},
+        {0.0f, 0.5f}, {0.9375f, 0.25f}, {0.875f, 0.9375f}, {0.0625f, 0.0f} };
+
+    int numSamples = renderTarget->numSamples();
+    // TODO: support mixed samples?
+    SkASSERT(numSamples > 1);
+    SkASSERT(!renderTarget->getStencilAttachment() ||
+             numSamples == renderTarget->getStencilAttachment()->numSamples());
+
+    GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(renderTarget);
+    unsigned int pattern = d3dRT->msaaTextureResource()->sampleQualityPattern();
+    if (pattern == DXGI_CENTER_MULTISAMPLE_QUALITY_PATTERN) {
+        sampleLocations->push_back_n(numSamples, kStandardSampleLocations_1[0]);
+        return;
+    }
+    SkASSERT(pattern == DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN);
+
+    switch (numSamples) {
+    case 2:
+        sampleLocations->push_back_n(2, kStandardSampleLocations_2);
+        break;
+    case 4:
+        sampleLocations->push_back_n(4, kStandardSampleLocations_4);
+        break;
+    case 8:
+        sampleLocations->push_back_n(8, kStandardSampleLocations_8);
+        break;
+    case 16:
+        sampleLocations->push_back_n(16, kStandardSampleLocations_16);
+        break;
+    default:
+        SK_ABORT("Invalid sample count.");
+        break;
+    }
 }
 
 sk_sp<GrD3DTexture> GrD3DGpu::createD3DTexture(SkISize dimensions,
@@ -248,8 +299,7 @@
     resourceDesc.MipLevels = mipLevelCount;
     resourceDesc.Format = dxgiFormat;
     resourceDesc.SampleDesc.Count = 1;
-    // quality levels are only supported for tiled resources so ignore for now
-    resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
+    resourceDesc.SampleDesc.Quality = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
     resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;  // use driver-selected swizzle
     resourceDesc.Flags = usageFlags;
 
@@ -955,8 +1005,7 @@
     resourceDesc.MipLevels = numMipLevels;
     resourceDesc.Format = dxgiFormat;
     resourceDesc.SampleDesc.Count = 1;
-    // quality levels are only supported for tiled resources so ignore for now
-    resourceDesc.SampleDesc.Quality = GrD3DTextureResource::kDefaultQualityLevel;
+    resourceDesc.SampleDesc.Quality = DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
     resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;  // use driver-selected swizzle
     resourceDesc.Flags = usageFlags;