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>
This commit is contained in:
parent
21c3fb94de
commit
4a081e2475
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
68
src/gpu/mtl/GrMtlTexture.h
Normal file
68
src/gpu/mtl/GrMtlTexture.h
Normal file
@ -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
|
78
src/gpu/mtl/GrMtlTexture.mm
Normal file
78
src/gpu/mtl/GrMtlTexture.mm
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user