xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/RenderBufferMtl.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1//
2// Copyright 2019 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// RenderBufferMtl.mm:
7//    Implements the class methods for RenderBufferMtl.
8//
9
10#include "libANGLE/renderer/metal/RenderBufferMtl.h"
11
12#include "libANGLE/renderer/metal/ContextMtl.h"
13#include "libANGLE/renderer/metal/ImageMtl.h"
14#include "libANGLE/renderer/metal/mtl_format_utils.h"
15#include "libANGLE/renderer/metal/mtl_utils.h"
16
17namespace rx
18{
19
20RenderbufferMtl::RenderbufferMtl(const gl::RenderbufferState &state) : RenderbufferImpl(state) {}
21
22RenderbufferMtl::~RenderbufferMtl() {}
23
24void RenderbufferMtl::onDestroy(const gl::Context *context)
25{
26    releaseTexture();
27}
28
29void RenderbufferMtl::releaseTexture()
30{
31    mTexture           = nullptr;
32    mImplicitMSTexture = nullptr;
33}
34
35angle::Result RenderbufferMtl::setStorageImpl(const gl::Context *context,
36                                              GLsizei samples,
37                                              GLenum internalformat,
38                                              GLsizei width,
39                                              GLsizei height,
40                                              gl::MultisamplingMode mode)
41{
42    ContextMtl *contextMtl = mtl::GetImpl(context);
43
44    if (mTexture != nullptr && mTexture->valid())
45    {
46        // Check against the state if we need to recreate the storage.
47        if (internalformat != mState.getFormat().info->internalFormat ||
48            width != mState.getWidth() || height != mState.getHeight() ||
49            samples != mState.getSamples())
50        {
51            releaseTexture();
52        }
53    }
54
55    const gl::InternalFormat &internalFormat = gl::GetSizedInternalFormatInfo(internalformat);
56    angle::FormatID angleFormatId =
57        angle::Format::InternalFormatToID(internalFormat.sizedInternalFormat);
58    mFormat = contextMtl->getPixelFormat(angleFormatId);
59
60    uint32_t actualSamples;
61    if (samples == 0)
62    {
63        actualSamples = 1;
64    }
65    else
66    {
67        // We always start at at least 2 samples
68        actualSamples = static_cast<uint32_t>(std::max<size_t>(2, samples));
69
70        const gl::TextureCaps &textureCaps =
71            contextMtl->getTextureCaps().get(mFormat.intendedFormatId);
72        actualSamples = textureCaps.getNearestSamples(actualSamples);
73        ANGLE_MTL_CHECK(contextMtl, actualSamples != 0, GL_INVALID_VALUE);
74    }
75
76    if ((mTexture == nullptr || !mTexture->valid()) && (width != 0 && height != 0))
77    {
78        if (actualSamples == 1 || mode == gl::MultisamplingMode::MultisampledRenderToTexture)
79        {
80            ANGLE_TRY(mtl::Texture::Make2DTexture(
81                contextMtl, mFormat, static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1,
82                /* renderTargetOnly */ false,
83                /* allowFormatView */ mFormat.hasDepthAndStencilBits(), &mTexture));
84
85            if (mode == gl::MultisamplingMode::MultisampledRenderToTexture)
86            {
87                // This format must supports implicit resolve
88                ASSERT(mFormat.getCaps().resolve);
89
90                ANGLE_TRY(mtl::Texture::MakeMemoryLess2DMSTexture(
91                    contextMtl, mFormat, static_cast<uint32_t>(width),
92                    static_cast<uint32_t>(height), actualSamples, &mImplicitMSTexture));
93            }
94        }
95        else
96        {
97            ANGLE_TRY(mtl::Texture::Make2DMSTexture(
98                contextMtl, mFormat, static_cast<uint32_t>(width), static_cast<uint32_t>(height),
99                actualSamples,
100                /* renderTargetOnly */ false,
101                /* allowFormatView */ mFormat.hasDepthAndStencilBits(), &mTexture));
102        }
103
104        mRenderTarget.setWithImplicitMSTexture(mTexture, mImplicitMSTexture,
105                                               mtl::kZeroNativeMipLevel, 0, mFormat);
106
107        // For emulated channels that GL texture intends to not have,
108        // we need to initialize their content.
109        bool emulatedChannels = mtl::IsFormatEmulated(mFormat);
110        if (emulatedChannels)
111        {
112            gl::ImageIndex index;
113
114            if (mTexture->samples() > 1)
115            {
116                index = gl::ImageIndex::Make2DMultisample();
117            }
118            else
119            {
120                index = gl::ImageIndex::Make2D(0);
121            }
122
123            ANGLE_TRY(mtl::InitializeTextureContents(context, mTexture, mFormat,
124                                                     mtl::ImageNativeIndex(index, 0)));
125        }  // if (emulatedChannels)
126        bool isDepthStencil = mFormat.hasDepthOrStencilBits();
127        if (isDepthStencil)
128        {
129            gl::ImageIndex index;
130            if (mTexture->samples() > 1)
131            {
132                index = gl::ImageIndex::Make2DMultisample();
133            }
134            else
135            {
136                index = gl::ImageIndex::Make2D(0);
137            }
138            ANGLE_TRY(mtl::InitializeDepthStencilTextureContentsGPU(
139                context, mTexture, mFormat, mtl::ImageNativeIndex(index, 0)));
140        }
141    }
142
143    return angle::Result::Continue;
144}
145
146angle::Result RenderbufferMtl::setStorage(const gl::Context *context,
147                                          GLenum internalformat,
148                                          GLsizei width,
149                                          GLsizei height)
150{
151    return setStorageImpl(context, 0, internalformat, width, height,
152                          gl::MultisamplingMode::Regular);
153}
154
155angle::Result RenderbufferMtl::setStorageMultisample(const gl::Context *context,
156                                                     GLsizei samples,
157                                                     GLenum internalformat,
158                                                     GLsizei width,
159                                                     GLsizei height,
160                                                     gl::MultisamplingMode mode)
161{
162    return setStorageImpl(context, samples, internalformat, width, height, mode);
163}
164
165angle::Result RenderbufferMtl::setStorageEGLImageTarget(const gl::Context *context,
166                                                        egl::Image *image)
167{
168    releaseTexture();
169
170    ContextMtl *contextMtl = mtl::GetImpl(context);
171
172    ImageMtl *imageMtl = mtl::GetImpl(image);
173    mTexture           = imageMtl->getTexture();
174
175    const angle::FormatID angleFormatId =
176        angle::Format::InternalFormatToID(image->getFormat().info->sizedInternalFormat);
177    mFormat = contextMtl->getPixelFormat(angleFormatId);
178
179    mRenderTarget.set(mTexture, mtl::kZeroNativeMipLevel, 0, mFormat);
180
181    return angle::Result::Continue;
182}
183
184angle::Result RenderbufferMtl::getAttachmentRenderTarget(const gl::Context *context,
185                                                         GLenum binding,
186                                                         const gl::ImageIndex &imageIndex,
187                                                         GLsizei samples,
188                                                         FramebufferAttachmentRenderTarget **rtOut)
189{
190    ASSERT(mTexture && mTexture->valid());
191    *rtOut = &mRenderTarget;
192    return angle::Result::Continue;
193}
194
195angle::Result RenderbufferMtl::initializeContents(const gl::Context *context,
196                                                  GLenum binding,
197                                                  const gl::ImageIndex &imageIndex)
198{
199    if (imageIndex.valid())
200        return mtl::InitializeTextureContents(
201            context, mTexture, mFormat, mtl::ImageNativeIndex::FromBaseZeroGLIndex(imageIndex));
202    else
203        return mtl::InitializeTextureContents(
204            context, mTexture, mFormat,
205            mtl::ImageNativeIndex::FromBaseZeroGLIndex(gl::ImageIndex::Make2D(0)));
206}
207}  // namespace rx
208