1// 2// Copyright 2021 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// ImageMtl.cpp: 7// Implements the class methods for ImageMtl. 8// 9 10#include "libANGLE/renderer/metal/ImageMtl.h" 11 12#include "common/debug.h" 13#include "libANGLE/Context.h" 14#include "libANGLE/Display.h" 15#include "libANGLE/renderer/metal/ContextMtl.h" 16#include "libANGLE/renderer/metal/DisplayMtl.h" 17#include "libANGLE/renderer/metal/RenderBufferMtl.h" 18#include "libANGLE/renderer/metal/TextureMtl.h" 19 20namespace rx 21{ 22 23// TextureImageSiblingMtl implementation 24TextureImageSiblingMtl::TextureImageSiblingMtl(EGLClientBuffer buffer) 25 : mBuffer(buffer), mGLFormat(GL_NONE) 26{} 27 28TextureImageSiblingMtl::~TextureImageSiblingMtl() {} 29 30// Static 31bool TextureImageSiblingMtl::ValidateClientBuffer(const DisplayMtl *display, EGLClientBuffer buffer) 32{ 33 id<MTLTexture> texture = (__bridge id<MTLTexture>)(buffer); 34 if (!texture || texture.device != display->getMetalDevice()) 35 { 36 return false; 37 } 38 39 if (texture.textureType != MTLTextureType2D && texture.textureType != MTLTextureTypeCube) 40 { 41 return false; 42 } 43 44 angle::FormatID angleFormatId = mtl::Format::MetalToAngleFormatID(texture.pixelFormat); 45 const mtl::Format &format = display->getPixelFormat(angleFormatId); 46 if (!format.valid()) 47 { 48 ERR() << "Unrecognized format"; 49 // Not supported 50 return false; 51 } 52 53 return true; 54} 55 56egl::Error TextureImageSiblingMtl::initialize(const egl::Display *display) 57{ 58 DisplayMtl *displayMtl = mtl::GetImpl(display); 59 if (initImpl(displayMtl) != angle::Result::Continue) 60 { 61 return egl::EglBadParameter(); 62 } 63 64 return egl::NoError(); 65} 66 67angle::Result TextureImageSiblingMtl::initImpl(DisplayMtl *displayMtl) 68{ 69 mNativeTexture = mtl::Texture::MakeFromMetal((__bridge id<MTLTexture>)(mBuffer)); 70 71 angle::FormatID angleFormatId = 72 mtl::Format::MetalToAngleFormatID(mNativeTexture->pixelFormat()); 73 mFormat = displayMtl->getPixelFormat(angleFormatId); 74 75 if (mNativeTexture) 76 { 77 size_t resourceSize = EstimateTextureSizeInBytes( 78 mFormat, mNativeTexture->widthAt0(), mNativeTexture->heightAt0(), 79 mNativeTexture->depthAt0(), mNativeTexture->samples(), mNativeTexture->mipmapLevels()); 80 mNativeTexture->setEstimatedByteSize(resourceSize); 81 } 82 83 mGLFormat = gl::Format(mFormat.intendedAngleFormat().glInternalFormat); 84 85 mRenderable = mFormat.getCaps().depthRenderable || mFormat.getCaps().colorRenderable; 86 87 mTextureable = mFormat.getCaps().filterable || mFormat.hasDepthOrStencilBits(); 88 89 return angle::Result::Continue; 90} 91 92void TextureImageSiblingMtl::onDestroy(const egl::Display *display) 93{ 94 mNativeTexture = nullptr; 95} 96 97gl::Format TextureImageSiblingMtl::getFormat() const 98{ 99 return mGLFormat; 100} 101 102bool TextureImageSiblingMtl::isRenderable(const gl::Context *context) const 103{ 104 return mRenderable; 105} 106 107bool TextureImageSiblingMtl::isTexturable(const gl::Context *context) const 108{ 109 return mTextureable; 110} 111 112gl::Extents TextureImageSiblingMtl::getSize() const 113{ 114 return mNativeTexture ? mNativeTexture->sizeAt0() : gl::Extents(0, 0, 0); 115} 116 117size_t TextureImageSiblingMtl::getSamples() const 118{ 119 uint32_t samples = mNativeTexture ? mNativeTexture->samples() : 0; 120 return samples > 1 ? samples : 0; 121} 122 123bool TextureImageSiblingMtl::isYUV() const 124{ 125 // NOTE(hqle): not supporting YUV image yet. 126 return false; 127} 128 129bool TextureImageSiblingMtl::hasProtectedContent() const 130{ 131 return false; 132} 133 134// ImageMtl implementation 135ImageMtl::ImageMtl(const egl::ImageState &state, const gl::Context *context) : ImageImpl(state) {} 136 137ImageMtl::~ImageMtl() {} 138 139void ImageMtl::onDestroy(const egl::Display *display) 140{ 141 mNativeTexture = nullptr; 142} 143 144egl::Error ImageMtl::initialize(const egl::Display *display) 145{ 146 if (mState.target == EGL_METAL_TEXTURE_ANGLE) 147 { 148 const TextureImageSiblingMtl *externalImageSibling = 149 GetImplAs<TextureImageSiblingMtl>(GetAs<egl::ExternalImageSibling>(mState.source)); 150 151 mNativeTexture = externalImageSibling->getTexture(); 152 153 switch (mNativeTexture->textureType()) 154 { 155 case MTLTextureType2D: 156 mImageTextureType = gl::TextureType::_2D; 157 break; 158 case MTLTextureTypeCube: 159 mImageTextureType = gl::TextureType::CubeMap; 160 break; 161 default: 162 UNREACHABLE(); 163 } 164 165 mImageLevel = 0; 166 mImageLayer = 0; 167 } 168 else 169 { 170 UNREACHABLE(); 171 return egl::EglBadAccess(); 172 } 173 174 return egl::NoError(); 175} 176 177angle::Result ImageMtl::orphan(const gl::Context *context, egl::ImageSibling *sibling) 178{ 179 if (sibling == mState.source) 180 { 181 mNativeTexture = nullptr; 182 } 183 184 return angle::Result::Continue; 185} 186 187} // namespace rx 188