Metal stencil support

Bug: skia:
Change-Id: I697a39bc756bb8f18ea2c6a1f8151dbc103bf9fe
Reviewed-on: https://skia-review.googlesource.com/c/157567
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/gpu/mtl/GrMtlStencilAttachment.mm b/src/gpu/mtl/GrMtlStencilAttachment.mm
new file mode 100644
index 0000000..b6fb18c
--- /dev/null
+++ b/src/gpu/mtl/GrMtlStencilAttachment.mm
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrMtlGpu.h"
+#include "GrMtlUtil.h"
+
+GrMtlStencilAttachment::GrMtlStencilAttachment(GrMtlGpu* gpu,
+                                               const Format& format,
+                                               const id<MTLTexture> stencilView)
+    : GrStencilAttachment(gpu, stencilView.width, stencilView.height, format.fStencilBits,
+                          stencilView.sampleCount)
+    , fFormat(format)
+    , fStencilView(stencilView) {
+    this->registerWithCache(SkBudgeted::kYes);
+}
+
+GrMtlStencilAttachment* GrMtlStencilAttachment::Create(GrMtlGpu* gpu,
+                                                       int width,
+                                                       int height,
+                                                       int sampleCnt,
+                                                       const Format& format) {
+    MTLTextureDescriptor* desc = [MTLTextureDescriptor
+                              texture2DDescriptorWithPixelFormat:MTLPixelFormatStencil8
+                              width:width
+                              height:height
+                              mipmapped:NO];
+    desc.resourceOptions = MTLResourceStorageModePrivate;
+    return new GrMtlStencilAttachment(gpu, format, [gpu->device() newTextureWithDescriptor:desc]);
+}
+
+GrMtlStencilAttachment::~GrMtlStencilAttachment() {
+    // should have been released or abandoned first
+    SkASSERT(!fStencilView);
+}
+
+size_t GrMtlStencilAttachment::onGpuMemorySize() const {
+    uint64_t size = this->width();
+    size *= this->height();
+    size *= fFormat.fTotalBits;
+    size *= this->numSamples();
+    return static_cast<size_t>(size / 8);
+}
+
+void GrMtlStencilAttachment::onRelease() {
+    fStencilView = nullptr;
+    GrStencilAttachment::onRelease();
+}
+
+void GrMtlStencilAttachment::onAbandon() {
+    fStencilView = nullptr;
+    GrStencilAttachment::onAbandon();
+}
+
+GrMtlGpu* GrMtlStencilAttachment::getMtlGpu() const {
+    SkASSERT(!this->wasDestroyed());
+    return static_cast<GrMtlGpu*>(this->getGpu());
+}