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