xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/ImageMtl.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker//
2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2021 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker//
6*8975f5c5SAndroid Build Coastguard Worker// ImageMtl.cpp:
7*8975f5c5SAndroid Build Coastguard Worker//    Implements the class methods for ImageMtl.
8*8975f5c5SAndroid Build Coastguard Worker//
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ImageMtl.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker#include "common/debug.h"
13*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Context.h"
14*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Display.h"
15*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ContextMtl.h"
16*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/DisplayMtl.h"
17*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/RenderBufferMtl.h"
18*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/TextureMtl.h"
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Workernamespace rx
21*8975f5c5SAndroid Build Coastguard Worker{
22*8975f5c5SAndroid Build Coastguard Worker
23*8975f5c5SAndroid Build Coastguard Workernamespace
24*8975f5c5SAndroid Build Coastguard Worker{
25*8975f5c5SAndroid Build Coastguard Workerangle::FormatID intendedFormatForMTLTexture(id<MTLTexture> texture,
26*8975f5c5SAndroid Build Coastguard Worker                                            const egl::AttributeMap &attribs)
27*8975f5c5SAndroid Build Coastguard Worker{
28*8975f5c5SAndroid Build Coastguard Worker    angle::FormatID angleFormatId = mtl::Format::MetalToAngleFormatID(texture.pixelFormat);
29*8975f5c5SAndroid Build Coastguard Worker    if (angleFormatId == angle::FormatID::NONE)
30*8975f5c5SAndroid Build Coastguard Worker    {
31*8975f5c5SAndroid Build Coastguard Worker        return angle::FormatID::NONE;
32*8975f5c5SAndroid Build Coastguard Worker    }
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker    const angle::Format *textureAngleFormat = &angle::Format::Get(angleFormatId);
35*8975f5c5SAndroid Build Coastguard Worker    ASSERT(textureAngleFormat);
36*8975f5c5SAndroid Build Coastguard Worker
37*8975f5c5SAndroid Build Coastguard Worker    GLenum sizedInternalFormat = textureAngleFormat->glInternalFormat;
38*8975f5c5SAndroid Build Coastguard Worker
39*8975f5c5SAndroid Build Coastguard Worker    if (attribs.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE))
40*8975f5c5SAndroid Build Coastguard Worker    {
41*8975f5c5SAndroid Build Coastguard Worker        const GLenum internalFormat =
42*8975f5c5SAndroid Build Coastguard Worker            static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
43*8975f5c5SAndroid Build Coastguard Worker        GLenum type       = gl::GetSizedInternalFormatInfo(sizedInternalFormat).type;
44*8975f5c5SAndroid Build Coastguard Worker        const auto format = gl::Format(internalFormat, type);
45*8975f5c5SAndroid Build Coastguard Worker        if (!format.valid())
46*8975f5c5SAndroid Build Coastguard Worker        {
47*8975f5c5SAndroid Build Coastguard Worker            return angle::FormatID::NONE;
48*8975f5c5SAndroid Build Coastguard Worker        }
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Worker        sizedInternalFormat = format.info->sizedInternalFormat;
51*8975f5c5SAndroid Build Coastguard Worker    }
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker    return angle::Format::InternalFormatToID(sizedInternalFormat);
54*8975f5c5SAndroid Build Coastguard Worker}
55*8975f5c5SAndroid Build Coastguard Worker}  // anonymous namespace
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker// TextureImageSiblingMtl implementation
58*8975f5c5SAndroid Build Coastguard WorkerTextureImageSiblingMtl::TextureImageSiblingMtl(EGLClientBuffer buffer,
59*8975f5c5SAndroid Build Coastguard Worker                                               const egl::AttributeMap &attribs)
60*8975f5c5SAndroid Build Coastguard Worker    : mBuffer(buffer), mAttribs(attribs), mGLFormat(GL_NONE)
61*8975f5c5SAndroid Build Coastguard Worker{}
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard WorkerTextureImageSiblingMtl::~TextureImageSiblingMtl() {}
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker// Static
66*8975f5c5SAndroid Build Coastguard Workeregl::Error TextureImageSiblingMtl::ValidateClientBuffer(const DisplayMtl *display,
67*8975f5c5SAndroid Build Coastguard Worker                                                        EGLClientBuffer buffer,
68*8975f5c5SAndroid Build Coastguard Worker                                                        const egl::AttributeMap &attribs)
69*8975f5c5SAndroid Build Coastguard Worker{
70*8975f5c5SAndroid Build Coastguard Worker    id<MTLTexture> texture = (__bridge id<MTLTexture>)(buffer);
71*8975f5c5SAndroid Build Coastguard Worker    if (!texture || texture.device != display->getMetalDevice())
72*8975f5c5SAndroid Build Coastguard Worker    {
73*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAttribute();
74*8975f5c5SAndroid Build Coastguard Worker    }
75*8975f5c5SAndroid Build Coastguard Worker
76*8975f5c5SAndroid Build Coastguard Worker    if (texture.textureType != MTLTextureType2D && texture.textureType != MTLTextureTypeCube &&
77*8975f5c5SAndroid Build Coastguard Worker        texture.textureType != MTLTextureType2DArray)
78*8975f5c5SAndroid Build Coastguard Worker    {
79*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAttribute();
80*8975f5c5SAndroid Build Coastguard Worker    }
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Worker    angle::FormatID angleFormatId = intendedFormatForMTLTexture(texture, attribs);
83*8975f5c5SAndroid Build Coastguard Worker    const mtl::Format &format     = display->getPixelFormat(angleFormatId);
84*8975f5c5SAndroid Build Coastguard Worker    if (!format.valid())
85*8975f5c5SAndroid Build Coastguard Worker    {
86*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAttribute() << "Unrecognized format";
87*8975f5c5SAndroid Build Coastguard Worker    }
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker    if (format.metalFormat != texture.pixelFormat)
90*8975f5c5SAndroid Build Coastguard Worker    {
91*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAttribute() << "Incompatible format";
92*8975f5c5SAndroid Build Coastguard Worker    }
93*8975f5c5SAndroid Build Coastguard Worker
94*8975f5c5SAndroid Build Coastguard Worker    unsigned textureArraySlice =
95*8975f5c5SAndroid Build Coastguard Worker        static_cast<unsigned>(attribs.getAsInt(EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, 0));
96*8975f5c5SAndroid Build Coastguard Worker    if (texture.textureType != MTLTextureType2DArray && textureArraySlice > 0)
97*8975f5c5SAndroid Build Coastguard Worker    {
98*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAttribute() << "Invalid texture type for non-zero texture array slice";
99*8975f5c5SAndroid Build Coastguard Worker    }
100*8975f5c5SAndroid Build Coastguard Worker    if (textureArraySlice >= texture.arrayLength)
101*8975f5c5SAndroid Build Coastguard Worker    {
102*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAttribute() << "Invalid texture array slice: " << textureArraySlice;
103*8975f5c5SAndroid Build Coastguard Worker    }
104*8975f5c5SAndroid Build Coastguard Worker
105*8975f5c5SAndroid Build Coastguard Worker    return egl::NoError();
106*8975f5c5SAndroid Build Coastguard Worker}
107*8975f5c5SAndroid Build Coastguard Worker
108*8975f5c5SAndroid Build Coastguard Workeregl::Error TextureImageSiblingMtl::initialize(const egl::Display *display)
109*8975f5c5SAndroid Build Coastguard Worker{
110*8975f5c5SAndroid Build Coastguard Worker    DisplayMtl *displayMtl = mtl::GetImpl(display);
111*8975f5c5SAndroid Build Coastguard Worker    if (initImpl(displayMtl) != angle::Result::Continue)
112*8975f5c5SAndroid Build Coastguard Worker    {
113*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadParameter();
114*8975f5c5SAndroid Build Coastguard Worker    }
115*8975f5c5SAndroid Build Coastguard Worker
116*8975f5c5SAndroid Build Coastguard Worker    return egl::NoError();
117*8975f5c5SAndroid Build Coastguard Worker}
118*8975f5c5SAndroid Build Coastguard Worker
119*8975f5c5SAndroid Build Coastguard Workerangle::Result TextureImageSiblingMtl::initImpl(DisplayMtl *displayMtl)
120*8975f5c5SAndroid Build Coastguard Worker{
121*8975f5c5SAndroid Build Coastguard Worker    mNativeTexture = mtl::Texture::MakeFromMetal((__bridge id<MTLTexture>)(mBuffer));
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker    if (mNativeTexture->textureType() == MTLTextureType2DArray)
124*8975f5c5SAndroid Build Coastguard Worker    {
125*8975f5c5SAndroid Build Coastguard Worker        mtl::TextureRef baseTexture = std::move(mNativeTexture);
126*8975f5c5SAndroid Build Coastguard Worker        unsigned textureArraySlice =
127*8975f5c5SAndroid Build Coastguard Worker            static_cast<unsigned>(mAttribs.getAsInt(EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, 0));
128*8975f5c5SAndroid Build Coastguard Worker        mNativeTexture =
129*8975f5c5SAndroid Build Coastguard Worker            baseTexture->createSliceMipView(textureArraySlice, mtl::kZeroNativeMipLevel);
130*8975f5c5SAndroid Build Coastguard Worker    }
131*8975f5c5SAndroid Build Coastguard Worker
132*8975f5c5SAndroid Build Coastguard Worker    angle::FormatID angleFormatId = intendedFormatForMTLTexture(mNativeTexture->get(), mAttribs);
133*8975f5c5SAndroid Build Coastguard Worker    mFormat                       = displayMtl->getPixelFormat(angleFormatId);
134*8975f5c5SAndroid Build Coastguard Worker
135*8975f5c5SAndroid Build Coastguard Worker    if (mNativeTexture)
136*8975f5c5SAndroid Build Coastguard Worker    {
137*8975f5c5SAndroid Build Coastguard Worker        size_t resourceSize = EstimateTextureSizeInBytes(
138*8975f5c5SAndroid Build Coastguard Worker            mFormat, mNativeTexture->widthAt0(), mNativeTexture->heightAt0(),
139*8975f5c5SAndroid Build Coastguard Worker            mNativeTexture->depthAt0(), mNativeTexture->samples(), mNativeTexture->mipmapLevels());
140*8975f5c5SAndroid Build Coastguard Worker        mNativeTexture->setEstimatedByteSize(resourceSize);
141*8975f5c5SAndroid Build Coastguard Worker    }
142*8975f5c5SAndroid Build Coastguard Worker
143*8975f5c5SAndroid Build Coastguard Worker    mGLFormat = gl::Format(mFormat.intendedAngleFormat().glInternalFormat);
144*8975f5c5SAndroid Build Coastguard Worker
145*8975f5c5SAndroid Build Coastguard Worker    mRenderable = mFormat.getCaps().depthRenderable || mFormat.getCaps().colorRenderable;
146*8975f5c5SAndroid Build Coastguard Worker
147*8975f5c5SAndroid Build Coastguard Worker    // Some formats are not filterable but renderable such as integer formats. In this case, treat
148*8975f5c5SAndroid Build Coastguard Worker    // them as texturable as well.
149*8975f5c5SAndroid Build Coastguard Worker    mTextureable = mFormat.getCaps().filterable || mRenderable;
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
152*8975f5c5SAndroid Build Coastguard Worker}
153*8975f5c5SAndroid Build Coastguard Worker
154*8975f5c5SAndroid Build Coastguard Workervoid TextureImageSiblingMtl::onDestroy(const egl::Display *display)
155*8975f5c5SAndroid Build Coastguard Worker{
156*8975f5c5SAndroid Build Coastguard Worker    mNativeTexture = nullptr;
157*8975f5c5SAndroid Build Coastguard Worker}
158*8975f5c5SAndroid Build Coastguard Worker
159*8975f5c5SAndroid Build Coastguard Workergl::Format TextureImageSiblingMtl::getFormat() const
160*8975f5c5SAndroid Build Coastguard Worker{
161*8975f5c5SAndroid Build Coastguard Worker    return mGLFormat;
162*8975f5c5SAndroid Build Coastguard Worker}
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Workerbool TextureImageSiblingMtl::isRenderable(const gl::Context *context) const
165*8975f5c5SAndroid Build Coastguard Worker{
166*8975f5c5SAndroid Build Coastguard Worker    return mRenderable;
167*8975f5c5SAndroid Build Coastguard Worker}
168*8975f5c5SAndroid Build Coastguard Worker
169*8975f5c5SAndroid Build Coastguard Workerbool TextureImageSiblingMtl::isTexturable(const gl::Context *context) const
170*8975f5c5SAndroid Build Coastguard Worker{
171*8975f5c5SAndroid Build Coastguard Worker    return mTextureable;
172*8975f5c5SAndroid Build Coastguard Worker}
173*8975f5c5SAndroid Build Coastguard Worker
174*8975f5c5SAndroid Build Coastguard Workergl::Extents TextureImageSiblingMtl::getSize() const
175*8975f5c5SAndroid Build Coastguard Worker{
176*8975f5c5SAndroid Build Coastguard Worker    return mNativeTexture ? mNativeTexture->sizeAt0() : gl::Extents(0, 0, 0);
177*8975f5c5SAndroid Build Coastguard Worker}
178*8975f5c5SAndroid Build Coastguard Worker
179*8975f5c5SAndroid Build Coastguard Workersize_t TextureImageSiblingMtl::getSamples() const
180*8975f5c5SAndroid Build Coastguard Worker{
181*8975f5c5SAndroid Build Coastguard Worker    uint32_t samples = mNativeTexture ? mNativeTexture->samples() : 0;
182*8975f5c5SAndroid Build Coastguard Worker    return samples > 1 ? samples : 0;
183*8975f5c5SAndroid Build Coastguard Worker}
184*8975f5c5SAndroid Build Coastguard Worker
185*8975f5c5SAndroid Build Coastguard Workerbool TextureImageSiblingMtl::isYUV() const
186*8975f5c5SAndroid Build Coastguard Worker{
187*8975f5c5SAndroid Build Coastguard Worker    // NOTE(hqle): not supporting YUV image yet.
188*8975f5c5SAndroid Build Coastguard Worker    return false;
189*8975f5c5SAndroid Build Coastguard Worker}
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Workerbool TextureImageSiblingMtl::hasProtectedContent() const
192*8975f5c5SAndroid Build Coastguard Worker{
193*8975f5c5SAndroid Build Coastguard Worker    return false;
194*8975f5c5SAndroid Build Coastguard Worker}
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker// ImageMtl implementation
197*8975f5c5SAndroid Build Coastguard WorkerImageMtl::ImageMtl(const egl::ImageState &state, const gl::Context *context) : ImageImpl(state) {}
198*8975f5c5SAndroid Build Coastguard Worker
199*8975f5c5SAndroid Build Coastguard WorkerImageMtl::~ImageMtl() {}
200*8975f5c5SAndroid Build Coastguard Worker
201*8975f5c5SAndroid Build Coastguard Workervoid ImageMtl::onDestroy(const egl::Display *display)
202*8975f5c5SAndroid Build Coastguard Worker{
203*8975f5c5SAndroid Build Coastguard Worker    mNativeTexture = nullptr;
204*8975f5c5SAndroid Build Coastguard Worker}
205*8975f5c5SAndroid Build Coastguard Worker
206*8975f5c5SAndroid Build Coastguard Workeregl::Error ImageMtl::initialize(const egl::Display *display)
207*8975f5c5SAndroid Build Coastguard Worker{
208*8975f5c5SAndroid Build Coastguard Worker    if (mState.target == EGL_METAL_TEXTURE_ANGLE)
209*8975f5c5SAndroid Build Coastguard Worker    {
210*8975f5c5SAndroid Build Coastguard Worker        const TextureImageSiblingMtl *externalImageSibling =
211*8975f5c5SAndroid Build Coastguard Worker            GetImplAs<TextureImageSiblingMtl>(GetAs<egl::ExternalImageSibling>(mState.source));
212*8975f5c5SAndroid Build Coastguard Worker
213*8975f5c5SAndroid Build Coastguard Worker        mNativeTexture = externalImageSibling->getTexture();
214*8975f5c5SAndroid Build Coastguard Worker
215*8975f5c5SAndroid Build Coastguard Worker        switch (mNativeTexture->textureType())
216*8975f5c5SAndroid Build Coastguard Worker        {
217*8975f5c5SAndroid Build Coastguard Worker            case MTLTextureType2D:
218*8975f5c5SAndroid Build Coastguard Worker            case MTLTextureType2DArray:
219*8975f5c5SAndroid Build Coastguard Worker                mImageTextureType = gl::TextureType::_2D;
220*8975f5c5SAndroid Build Coastguard Worker                break;
221*8975f5c5SAndroid Build Coastguard Worker            case MTLTextureTypeCube:
222*8975f5c5SAndroid Build Coastguard Worker                mImageTextureType = gl::TextureType::CubeMap;
223*8975f5c5SAndroid Build Coastguard Worker                break;
224*8975f5c5SAndroid Build Coastguard Worker            default:
225*8975f5c5SAndroid Build Coastguard Worker                UNREACHABLE();
226*8975f5c5SAndroid Build Coastguard Worker        }
227*8975f5c5SAndroid Build Coastguard Worker
228*8975f5c5SAndroid Build Coastguard Worker        mImageLevel = 0;
229*8975f5c5SAndroid Build Coastguard Worker        mImageLayer = 0;
230*8975f5c5SAndroid Build Coastguard Worker    }
231*8975f5c5SAndroid Build Coastguard Worker    else
232*8975f5c5SAndroid Build Coastguard Worker    {
233*8975f5c5SAndroid Build Coastguard Worker        UNREACHABLE();
234*8975f5c5SAndroid Build Coastguard Worker        return egl::EglBadAccess();
235*8975f5c5SAndroid Build Coastguard Worker    }
236*8975f5c5SAndroid Build Coastguard Worker
237*8975f5c5SAndroid Build Coastguard Worker    return egl::NoError();
238*8975f5c5SAndroid Build Coastguard Worker}
239*8975f5c5SAndroid Build Coastguard Worker
240*8975f5c5SAndroid Build Coastguard Workerangle::Result ImageMtl::orphan(const gl::Context *context, egl::ImageSibling *sibling)
241*8975f5c5SAndroid Build Coastguard Worker{
242*8975f5c5SAndroid Build Coastguard Worker    if (sibling == mState.source)
243*8975f5c5SAndroid Build Coastguard Worker    {
244*8975f5c5SAndroid Build Coastguard Worker        mNativeTexture = nullptr;
245*8975f5c5SAndroid Build Coastguard Worker    }
246*8975f5c5SAndroid Build Coastguard Worker
247*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
248*8975f5c5SAndroid Build Coastguard Worker}
249*8975f5c5SAndroid Build Coastguard Worker
250*8975f5c5SAndroid Build Coastguard Worker}  // namespace rx
251