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