diff options
author | Greg Daniel <egdaniel@google.com> | 2017-08-04 09:34:44 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-04 19:53:55 +0000 |
commit | 4a081e2475fa69dd55fcace9f8e6d3166ea25ad1 (patch) | |
tree | a42a3b82ab0697237fe66e7dda836d07af8e443d | |
parent | 21c3fb94deac8527719be74deff9e8fb8a490e23 (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.gni | 2 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlGpu.h | 8 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlGpu.mm | 41 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlTexture.h | 68 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlTexture.mm | 78 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlUtil.h | 5 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlUtil.mm | 20 |
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); +} + |