aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Greg Daniel <egdaniel@google.com>2017-08-04 09:34:44 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-04 19:53:55 +0000
commit4a081e2475fa69dd55fcace9f8e6d3166ea25ad1 (patch)
treea42a3b82ab0697237fe66e7dda836d07af8e443d
parent21c3fb94deac8527719be74deff9e8fb8a490e23 (diff)
Add GrMtlTexture classes
Adds support for basic Texture creation. Bug: skia: Change-Id: I9a3f15bef1c88054c19e952e231cad94ad69f296 Reviewed-on: https://skia-review.googlesource.com/30781 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Greg Daniel <egdaniel@google.com>
-rw-r--r--gn/gpu.gni2
-rw-r--r--src/gpu/mtl/GrMtlGpu.h8
-rw-r--r--src/gpu/mtl/GrMtlGpu.mm41
-rw-r--r--src/gpu/mtl/GrMtlTexture.h68
-rw-r--r--src/gpu/mtl/GrMtlTexture.mm78
-rw-r--r--src/gpu/mtl/GrMtlUtil.h5
-rw-r--r--src/gpu/mtl/GrMtlUtil.mm20
7 files changed, 218 insertions, 4 deletions
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 9bd28e19f1..e9b33ed58c 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -585,6 +585,8 @@ skia_metal_sources = [
"$_src/gpu/mtl/GrMtlCaps.mm",
"$_src/gpu/mtl/GrMtlGpu.h",
"$_src/gpu/mtl/GrMtlGpu.mm",
+ "$_src/gpu/mtl/GrMtlTexture.mm",
+ "$_src/gpu/mtl/GrMtlTexture.h",
"$_src/gpu/mtl/GrMtlTrampoline.h",
"$_src/gpu/mtl/GrMtlTrampoline.mm",
"$_src/gpu/mtl/GrMtlUtil.h",
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index c812843950..06c2b2fc5e 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -26,9 +26,11 @@ public:
id<MTLDevice> device, id<MTLCommandQueue> queue);
~GrMtlGpu() override {}
-
+
const GrMtlCaps& mtlCaps() const { return *fMtlCaps.get(); }
+ id<MTLDevice> device() const { return fDevice; }
+
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
GrPixelConfig readConfig, DrawPreference*,
ReadPixelTempDrawInfo*) override { return false; }
@@ -72,9 +74,7 @@ private:
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
- const GrMipLevel texels[], int mipLevelCount) override {
- return nullptr;
- }
+ const GrMipLevel texels[], int mipLevelCount) override;
sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
GrSurfaceOrigin,
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 7a9a673d69..a830959bdd 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -7,6 +7,8 @@
#include "GrMtlGpu.h"
+#include "GrMtlTexture.h"
+
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
@@ -103,3 +105,42 @@ GrMtlGpu::GrMtlGpu(GrContext* context, const GrContextOptions& options,
// Unused queue warning fix
SkDebugf("ptr to queue: %p\n", fQueue);
}
+
+sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
+ const GrMipLevel texels[], int mipLevelCount) {
+ int mipLevels = !mipLevelCount ? 1 : mipLevelCount;
+
+ if (!fMtlCaps->isConfigTexturable(desc.fConfig)) {
+ return nullptr;
+ }
+
+ bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
+ if (renderTarget) {
+ // Current we don't have render target support
+ return nullptr;
+ }
+
+ sk_sp<GrMtlTexture> tex;
+ if (renderTarget) {
+ // Enable once we have render target support
+#if 0
+ tex = GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted,
+ desc, mipLevels);
+#endif
+ } else {
+ tex = GrMtlTexture::CreateNewTexture(this, budgeted, desc, mipLevels);
+ }
+
+ if (!tex) {
+ return nullptr;
+ }
+
+ if (mipLevelCount) {
+ // Perform initial data upload here
+ }
+
+ if (desc.fFlags & kPerformInitialClear_GrSurfaceFlag) {
+ // Do initial clear of the texture
+ }
+ return tex;
+}
diff --git a/src/gpu/mtl/GrMtlTexture.h b/src/gpu/mtl/GrMtlTexture.h
new file mode 100644
index 0000000000..2d3580ef71
--- /dev/null
+++ b/src/gpu/mtl/GrMtlTexture.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrMtlTexture_DEFINED
+#define GrMtlTexture_DEFINED
+
+#include "GrTexture.h"
+
+#import <Metal/Metal.h>
+
+class GrMtlGpu;
+
+class GrMtlTexture : public GrTexture {
+public:
+ static sk_sp<GrMtlTexture> CreateNewTexture(GrMtlGpu*, SkBudgeted budgeted,
+ const GrSurfaceDesc&, int mipLevels);
+
+ static sk_sp<GrMtlTexture> MakeWrappedTexture(GrMtlGpu*, const GrSurfaceDesc&,
+ GrWrapOwnership);
+
+ ~GrMtlTexture() override;
+
+ id<MTLTexture> mtlTexture() const { return fTexture; }
+
+ GrBackendObject getTextureHandle() const override;
+
+ void textureParamsModified() override {}
+
+ bool reallocForMipmap(GrMtlGpu* gpu, uint32_t mipLevels);
+
+ void setRelease(GrTexture::ReleaseProc proc, GrTexture::ReleaseCtx ctx) override {
+ // Since all MTLResources are inherently ref counted, we can call the Release proc when we
+ // delete the GrMtlTexture without worry of the MTLTexture getting deleted before it is done
+ // on the GPU.
+ fReleaseProc = proc;
+ fReleaseCtx = ctx;
+ }
+
+protected:
+ GrMtlTexture(GrMtlGpu*, const GrSurfaceDesc&);
+
+ GrMtlGpu* getMtlGpu() const;
+
+ void onAbandon() override {
+ fTexture = nil;
+ }
+ void onRelease() override {
+ fTexture = nil;
+ }
+
+private:
+ enum Wrapped { kWrapped };
+ GrMtlTexture(GrMtlGpu*, SkBudgeted, const GrSurfaceDesc&, id<MTLTexture>, bool isMipMapped);
+ // GrMtlTexture(GrMtlGpu*, Wrapped, const GrSurfaceDesc&, GrMtlImage::Wrapped wrapped);
+
+ id<MTLTexture> fTexture;
+
+ ReleaseProc fReleaseProc = nullptr;
+ ReleaseCtx fReleaseCtx = nullptr;
+
+ typedef GrTexture INHERITED;
+};
+
+#endif
diff --git a/src/gpu/mtl/GrMtlTexture.mm b/src/gpu/mtl/GrMtlTexture.mm
new file mode 100644
index 0000000000..ec7f3b1750
--- /dev/null
+++ b/src/gpu/mtl/GrMtlTexture.mm
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrMtlTexture.h"
+
+#include "GrMtlGpu.h"
+#include "GrMtlUtil.h"
+#include "GrTexturePriv.h"
+
+sk_sp<GrMtlTexture> GrMtlTexture::CreateNewTexture(GrMtlGpu* gpu, SkBudgeted budgeted,
+ const GrSurfaceDesc& desc, int mipLevels) {
+ MTLPixelFormat format;
+ if (!GrPixelConfigToMTLFormat(desc.fConfig, &format)) {
+ return nullptr;
+ }
+
+ MTLTextureDescriptor* descriptor = [[MTLTextureDescriptor alloc] init];
+ descriptor.textureType = MTLTextureType2D;
+ descriptor.pixelFormat = format;
+ descriptor.width = desc.fWidth;
+ descriptor.height = desc.fHeight;
+ descriptor.depth = 1;
+ descriptor.mipmapLevelCount = mipLevels;
+ descriptor.sampleCount = 1;
+ descriptor.arrayLength = 1;
+ // descriptor.resourceOptions This looks to be set by setting cpuCacheMode and storageModes
+ descriptor.cpuCacheMode = MTLCPUCacheModeWriteCombined;
+ // Shared is not available on MacOS. Is there a reason to want managed to allow mapping?
+ descriptor.storageMode = MTLStorageModePrivate;
+
+ MTLTextureUsage texUsage = MTLTextureUsageShaderRead;
+ if (GrMTLFormatIsSRGB(format, nullptr)) {
+ texUsage |= MTLTextureUsagePixelFormatView;
+ }
+ descriptor.usage = texUsage;
+
+ id<MTLTexture> texture = [gpu->device() newTextureWithDescriptor:descriptor];
+
+ return sk_sp<GrMtlTexture>(new GrMtlTexture(gpu, budgeted, desc, texture, mipLevels > 1));
+}
+
+// This method parallels GrTextureProxy::highestFilterMode
+static inline GrSamplerParams::FilterMode highest_filter_mode(GrPixelConfig config) {
+ if (GrPixelConfigIsSint(config)) {
+ // We only ever want to nearest-neighbor sample signed int textures.
+ return GrSamplerParams::kNone_FilterMode;
+ }
+ return GrSamplerParams::kMipMap_FilterMode;
+}
+
+GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu,
+ SkBudgeted budgeted,
+ const GrSurfaceDesc& desc,
+ id<MTLTexture> texture,
+ bool isMipMapped)
+ : GrSurface(gpu, desc)
+ , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
+ isMipMapped)
+ , fTexture(texture) {
+}
+
+GrMtlTexture::~GrMtlTexture() {
+ SkASSERT(nil == fTexture);
+}
+
+GrMtlGpu* GrMtlTexture::getMtlGpu() const {
+ SkASSERT(!this->wasDestroyed());
+ return static_cast<GrMtlGpu*>(this->getGpu());
+}
+
+GrBackendObject GrMtlTexture::getTextureHandle() const {
+ void* voidTex = (__bridge_retained void*)fTexture;
+ return (GrBackendObject)voidTex;
+}
diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h
index 78af7bf89f..a84a636511 100644
--- a/src/gpu/mtl/GrMtlUtil.h
+++ b/src/gpu/mtl/GrMtlUtil.h
@@ -22,5 +22,10 @@ bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format);
*/
GrPixelConfig GrMTLFormatToPixelConfig(MTLPixelFormat format);
+/**
+ * Returns true if the given vulkan texture format is sRGB encoded.
+ * Also provides the non-sRGB version, if there is one.
+ */
+bool GrMTLFormatIsSRGB(MTLPixelFormat format, MTLPixelFormat* linearFormat);
#endif
diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm
index 9c6e3f0eca..d1bbf6e6bc 100644
--- a/src/gpu/mtl/GrMtlUtil.mm
+++ b/src/gpu/mtl/GrMtlUtil.mm
@@ -101,3 +101,23 @@ GrPixelConfig GrMTLFormatToPixelConfig(MTLPixelFormat format) {
return kUnknown_GrPixelConfig;
}
}
+
+bool GrMTLFormatIsSRGB(MTLPixelFormat format, MTLPixelFormat* linearFormat) {
+ MTLPixelFormat linearFmt = format;
+ switch (format) {
+ case MTLPixelFormatRGBA8Unorm_sRGB:
+ linearFmt = MTLPixelFormatRGBA8Unorm;
+ break;
+ case MTLPixelFormatBGRA8Unorm_sRGB:
+ linearFmt = MTLPixelFormatBGRA8Unorm;
+ break;
+ default:
+ break;
+ }
+
+ if (linearFormat) {
+ *linearFormat = linearFmt;
+ }
+ return (linearFmt != format);
+}
+