• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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