xref: /aosp_15_r20/external/skia/src/gpu/graphite/mtl/MtlTexture.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/MtlGraphiteTypesPriv.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 MtlTextureSpec mtlSpec = TextureInfos::GetMtlTextureSpec(info);
31    SkASSERT(!mtlSpec.fFramebufferOnly);
32
33    if (mtlSpec.fUsage & MTLTextureUsageShaderRead && !caps->isTexturable(info)) {
34        return nullptr;
35    }
36
37    if (mtlSpec.fUsage & MTLTextureUsageRenderTarget &&
38        !(caps->isRenderable(info) || MtlFormatIsDepthOrStencil(mtlSpec.fFormat))) {
39        return nullptr;
40    }
41
42    if (mtlSpec.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 = mtlSpec.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 = mtlSpec.fUsage;
61    (*desc).storageMode = mtlSpec.fStorageMode;
62
63    sk_cfp<id<MTLTexture>> texture([sharedContext->device() newTextureWithDescriptor:desc.get()]);
64    return texture;
65}
66
67MtlTexture::MtlTexture(const MtlSharedContext* sharedContext,
68                       SkISize dimensions,
69                       const TextureInfo& info,
70                       sk_cfp<id<MTLTexture>> texture,
71                       Ownership ownership,
72                       skgpu::Budgeted budgeted)
73        : Texture(sharedContext,
74                  dimensions,
75                  info,
76                  /*mutableState=*/nullptr,
77                  ownership,
78                  budgeted)
79        , fTexture(std::move(texture)) {}
80
81sk_sp<Texture> MtlTexture::Make(const MtlSharedContext* sharedContext,
82                                SkISize dimensions,
83                                const TextureInfo& info,
84                                skgpu::Budgeted budgeted) {
85    sk_cfp<id<MTLTexture>> texture = MakeMtlTexture(sharedContext, dimensions, info);
86    if (!texture) {
87        return nullptr;
88    }
89    return sk_sp<Texture>(new MtlTexture(sharedContext,
90                                         dimensions,
91                                         info,
92                                         std::move(texture),
93                                         Ownership::kOwned,
94                                         budgeted));
95}
96
97sk_sp<Texture> MtlTexture::MakeWrapped(const MtlSharedContext* sharedContext,
98                                       SkISize dimensions,
99                                       const TextureInfo& info,
100                                       sk_cfp<id<MTLTexture>> texture) {
101    return sk_sp<Texture>(new MtlTexture(sharedContext,
102                                         dimensions,
103                                         info,
104                                         std::move(texture),
105                                         Ownership::kWrapped,
106                                         skgpu::Budgeted::kNo));
107}
108
109void MtlTexture::freeGpuData() {
110    fTexture.reset();
111}
112
113
114void MtlTexture::setBackendLabel(char const* label) {
115    SkASSERT(label);
116#ifdef SK_ENABLE_MTL_DEBUG_INFO
117    NSString* labelStr = @(label);
118    this->mtlTexture().label = labelStr;
119#endif
120}
121
122} // namespace skgpu::graphite
123
124