• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/gpu/graphite/mtl/MtlTexture.h"
9
10#include "include/gpu/MutableTextureState.h"
11#include "include/gpu/graphite/TextureInfo.h"
12#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h"
13#include "src/core/SkMipmap.h"
14#include "src/gpu/graphite/mtl/MtlCaps.h"
15#include "src/gpu/graphite/mtl/MtlGraphiteUtils.h"
16#include "src/gpu/graphite/mtl/MtlSharedContext.h"
17#include "src/gpu/mtl/MtlUtilsPriv.h"
18
19namespace skgpu::graphite {
20
21sk_cfp<id<MTLTexture>> MtlTexture::MakeMtlTexture(const MtlSharedContext* sharedContext,
22                                                  SkISize dimensions,
23                                                  const TextureInfo& info) {
24    const Caps* caps = sharedContext->caps();
25    if (dimensions.width() > caps->maxTextureSize() ||
26        dimensions.height() > caps->maxTextureSize()) {
27        return nullptr;
28    }
29
30    const auto& mtlInfo = TextureInfoPriv::Get<MtlTextureInfo>(info);
31    SkASSERT(!mtlInfo.fFramebufferOnly);
32
33    if (mtlInfo.fUsage & MTLTextureUsageShaderRead && !caps->isTexturable(info)) {
34        return nullptr;
35    }
36
37    if (mtlInfo.fUsage & MTLTextureUsageRenderTarget &&
38        !(caps->isRenderable(info) || MtlFormatIsDepthOrStencil(mtlInfo.fFormat))) {
39        return nullptr;
40    }
41
42    if (mtlInfo.fUsage & MTLTextureUsageShaderWrite && !caps->isStorage(info)) {
43        return nullptr;
44    }
45
46    int numMipLevels = 1;
47    if (info.mipmapped() == Mipmapped::kYes) {
48        numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
49    }
50
51    sk_cfp<MTLTextureDescriptor*> desc([[MTLTextureDescriptor alloc] init]);
52    (*desc).textureType = (info.numSamples() > 1) ? MTLTextureType2DMultisample : MTLTextureType2D;
53    (*desc).pixelFormat = mtlInfo.fFormat;
54    (*desc).width = dimensions.width();
55    (*desc).height = dimensions.height();
56    (*desc).depth = 1;
57    (*desc).mipmapLevelCount = numMipLevels;
58    (*desc).sampleCount = info.numSamples();
59    (*desc).arrayLength = 1;
60    (*desc).usage = mtlInfo.fUsage;
61    (*desc).storageMode = mtlInfo.fStorageMode;
62
63    sk_cfp<id<MTLTexture>> texture([sharedContext->device() newTextureWithDescriptor:desc.get()]);
64    return texture;
65}
66
67static bool has_transient_usage(const TextureInfo& info) {
68    if (@available(macOS 11.0, iOS 10.0, tvOS 10.0, *)) {
69        const auto& mtlInfo = TextureInfoPriv::Get<MtlTextureInfo>(info);
70        return mtlInfo.fStorageMode == MTLStorageModeMemoryless;
71    }
72    return false;
73}
74
75MtlTexture::MtlTexture(const MtlSharedContext* sharedContext,
76                       SkISize dimensions,
77                       const TextureInfo& info,
78                       sk_cfp<id<MTLTexture>> texture,
79                       Ownership ownership)
80        : Texture(sharedContext,
81                  dimensions,
82                  info,
83                  has_transient_usage(info),
84                  /*mutableState=*/nullptr,
85                  ownership)
86        , fTexture(std::move(texture)) {}
87
88sk_sp<Texture> MtlTexture::Make(const MtlSharedContext* sharedContext,
89                                SkISize dimensions,
90                                const TextureInfo& info) {
91    sk_cfp<id<MTLTexture>> texture = MakeMtlTexture(sharedContext, dimensions, info);
92    if (!texture) {
93        return nullptr;
94    }
95    return sk_sp<Texture>(new MtlTexture(sharedContext,
96                                         dimensions,
97                                         info,
98                                         std::move(texture),
99                                         Ownership::kOwned));
100}
101
102sk_sp<Texture> MtlTexture::MakeWrapped(const MtlSharedContext* sharedContext,
103                                       SkISize dimensions,
104                                       const TextureInfo& info,
105                                       sk_cfp<id<MTLTexture>> texture) {
106    return sk_sp<Texture>(new MtlTexture(sharedContext,
107                                         dimensions,
108                                         info,
109                                         std::move(texture),
110                                         Ownership::kWrapped));
111}
112
113void MtlTexture::freeGpuData() {
114    fTexture.reset();
115}
116
117
118void MtlTexture::setBackendLabel(char const* label) {
119    SkASSERT(label);
120#ifdef SK_ENABLE_MTL_DEBUG_INFO
121    NSString* labelStr = @(label);
122    this->mtlTexture().label = labelStr;
123#endif
124}
125
126} // namespace skgpu::graphite
127