Recycle stencil buffers across render targets.

Review URL: https://codereview.chromium.org/939093002
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 64cd327..d9e4c18 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -63,6 +63,73 @@
     context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
 }
 
+static void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* context) {
+    GrSurfaceDesc smallDesc;
+    smallDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+    smallDesc.fConfig = kSkia8888_GrPixelConfig;
+    smallDesc.fWidth = 4;
+    smallDesc.fHeight = 4;
+    smallDesc.fSampleCnt = 0;
+
+    // Test that two budgeted RTs with the same desc share a stencil buffer.
+    SkAutoTUnref<GrTexture> smallRT0(context->createTexture(smallDesc, true));
+    SkAutoTUnref<GrTexture> smallRT1(context->createTexture(smallDesc, true));
+    REPORTER_ASSERT(reporter, smallRT0 && smallRT1 &&
+                              smallRT0->asRenderTarget() && smallRT1->asRenderTarget() &&
+                              smallRT0->asRenderTarget()->getStencilBuffer() ==
+                              smallRT1->asRenderTarget()->getStencilBuffer());
+
+    // An unbudgeted RT with the same desc should also share.
+    SkAutoTUnref<GrTexture> smallRT2(context->createTexture(smallDesc, false));
+    REPORTER_ASSERT(reporter, smallRT0 && smallRT2 &&
+                              smallRT0->asRenderTarget() && smallRT2->asRenderTarget() &&
+                              smallRT0->asRenderTarget()->getStencilBuffer() ==
+                              smallRT2->asRenderTarget()->getStencilBuffer());
+
+    // An RT with a much larger size should not share.
+    GrSurfaceDesc bigDesc;
+    bigDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+    bigDesc.fConfig = kSkia8888_GrPixelConfig;
+    bigDesc.fWidth = 400;
+    bigDesc.fHeight = 200;
+    bigDesc.fSampleCnt = 0;
+    SkAutoTUnref<GrTexture> bigRT(context->createTexture(bigDesc, false));
+    REPORTER_ASSERT(reporter, smallRT0 && bigRT &&
+                              smallRT0->asRenderTarget() && bigRT->asRenderTarget() &&
+                              smallRT0->asRenderTarget()->getStencilBuffer() !=
+                              bigRT->asRenderTarget()->getStencilBuffer());
+
+    if (context->getMaxSampleCount() >= 4) {
+        // An RT with a different sample count should not share. 
+        GrSurfaceDesc smallMSAADesc = smallDesc;
+        smallMSAADesc.fSampleCnt = 4;
+        SkAutoTUnref<GrTexture> smallMSAART0(context->createTexture(smallMSAADesc, false));
+        REPORTER_ASSERT(reporter, smallRT0 && smallMSAART0 &&
+                                  smallRT0->asRenderTarget() && smallMSAART0->asRenderTarget() &&
+                                  smallRT0->asRenderTarget()->getStencilBuffer() !=
+                                  smallMSAART0->asRenderTarget()->getStencilBuffer());
+        // A second MSAA RT should share with the first MSAA RT.
+        SkAutoTUnref<GrTexture> smallMSAART1(context->createTexture(smallMSAADesc, false));
+        REPORTER_ASSERT(reporter, smallMSAART0 && smallMSAART1 &&
+                                  smallMSAART0->asRenderTarget() &&
+                                  smallMSAART1->asRenderTarget() &&
+                                  smallMSAART0->asRenderTarget()->getStencilBuffer() ==
+                                  smallMSAART1->asRenderTarget()->getStencilBuffer());
+        // But not one with a larger sample count should not. (Also check that the request for 4
+        // samples didn't get rounded up to >= 8 or else they could share.).
+        if (context->getMaxSampleCount() >= 8 && smallMSAART0 && smallMSAART0->asRenderTarget() &&
+            smallMSAART0->asRenderTarget()->numSamples() < 8) {
+            smallMSAADesc.fSampleCnt = 8;
+            smallMSAART1.reset(context->createTexture(smallMSAADesc, false));
+            REPORTER_ASSERT(reporter, smallMSAART0 && smallMSAART1 &&
+                                      smallMSAART0->asRenderTarget() &&
+                                      smallMSAART1->asRenderTarget() &&
+                                      smallMSAART0->asRenderTarget()->getStencilBuffer() !=
+                                      smallMSAART1->asRenderTarget()->getStencilBuffer());
+        }
+    }
+}
+
 class TestResource : public GrGpuResource {
     static const size_t kDefaultSize = 100;
     enum ScratchConstructor { kScratchConstructor };
@@ -936,6 +1003,7 @@
         SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context,
                                                                    SkSurface::kNo_Budgeted, info));
         test_cache(reporter, context, surface->getCanvas());
+        test_stencil_buffers(reporter, context);
     }
 
     // The below tests create their own mock contexts.