xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/egl/ImageEGL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2018 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 
7 // ImageEGL.cpp: Implements the rx::ImageEGL class.
8 
9 #include "libANGLE/renderer/gl/egl/ImageEGL.h"
10 
11 #include "common/utilities.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/renderer/gl/FunctionsGL.h"
15 #include "libANGLE/renderer/gl/RenderbufferGL.h"
16 #include "libANGLE/renderer/gl/StateManagerGL.h"
17 #include "libANGLE/renderer/gl/TextureGL.h"
18 #include "libANGLE/renderer/gl/egl/ContextEGL.h"
19 #include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h"
20 #include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
21 
22 namespace rx
23 {
24 
ImageEGL(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs,const FunctionsEGL * egl)25 ImageEGL::ImageEGL(const egl::ImageState &state,
26                    const gl::Context *context,
27                    EGLenum target,
28                    const egl::AttributeMap &attribs,
29                    const FunctionsEGL *egl)
30     : ImageGL(state),
31       mEGL(egl),
32       mContext(EGL_NO_CONTEXT),
33       mTarget(target),
34       mPreserveImage(false),
35       mImage(EGL_NO_IMAGE)
36 {
37     if (context)
38     {
39         mContext = GetImplAs<ContextEGL>(context)->getContext();
40     }
41     mPreserveImage = attribs.get(EGL_IMAGE_PRESERVED, EGL_FALSE) == EGL_TRUE;
42 }
43 
~ImageEGL()44 ImageEGL::~ImageEGL()
45 {
46     mEGL->destroyImageKHR(mImage);
47 }
48 
initialize(const egl::Display * display)49 egl::Error ImageEGL::initialize(const egl::Display *display)
50 {
51     EGLClientBuffer buffer = nullptr;
52     angle::FastVector<EGLint, 8> attributes;
53 
54     if (egl::IsTextureTarget(mTarget))
55     {
56         attributes.push_back(EGL_GL_TEXTURE_LEVEL);
57         attributes.push_back(mState.imageIndex.getLevelIndex());
58 
59         if (mState.imageIndex.has3DLayer())
60         {
61             attributes.push_back(EGL_GL_TEXTURE_ZOFFSET);
62             attributes.push_back(mState.imageIndex.getLayerIndex());
63         }
64 
65         const TextureGL *textureGL = GetImplAs<TextureGL>(GetAs<gl::Texture>(mState.source));
66         buffer                = gl_egl::GLObjectHandleToEGLClientBuffer(textureGL->getTextureID());
67         mNativeInternalFormat = textureGL->getNativeInternalFormat(mState.imageIndex);
68     }
69     else if (egl::IsRenderbufferTarget(mTarget))
70     {
71         const RenderbufferGL *renderbufferGL =
72             GetImplAs<RenderbufferGL>(GetAs<gl::Renderbuffer>(mState.source));
73         buffer = gl_egl::GLObjectHandleToEGLClientBuffer(renderbufferGL->getRenderbufferID());
74         mNativeInternalFormat = renderbufferGL->getNativeInternalFormat();
75     }
76     else if (egl::IsExternalImageTarget(mTarget))
77     {
78         const ExternalImageSiblingEGL *externalImageSibling =
79             GetImplAs<ExternalImageSiblingEGL>(GetAs<egl::ExternalImageSibling>(mState.source));
80         buffer                = externalImageSibling->getBuffer();
81         mNativeInternalFormat = externalImageSibling->getFormat().info->sizedInternalFormat;
82 
83         // Add any additional attributes this type of image sibline requires
84         std::vector<EGLint> tmp_attributes;
85         externalImageSibling->getImageCreationAttributes(&tmp_attributes);
86 
87         attributes.reserve(attributes.size() + tmp_attributes.size());
88         for (EGLint attribute : tmp_attributes)
89         {
90             attributes.push_back(attribute);
91         }
92     }
93     else
94     {
95         UNREACHABLE();
96     }
97 
98     attributes.push_back(EGL_IMAGE_PRESERVED);
99     attributes.push_back(mPreserveImage ? EGL_TRUE : EGL_FALSE);
100 
101     attributes.push_back(EGL_NONE);
102 
103     egl::Display::GetCurrentThreadUnlockedTailCall()->add([egl = mEGL, &image = mImage,
104                                                            context = mContext, target = mTarget,
105                                                            buffer, attributes](void *resultOut) {
106         image = egl->createImageKHR(context, target, buffer, attributes.data());
107 
108         // If image creation failed, force the return value of eglCreateImage to EGL_NO_IMAGE. This
109         // won't delete this image object but a driver error is unexpected at this point.
110         if (image == EGL_NO_IMAGE)
111         {
112             ERR() << "eglCreateImage failed with " << gl::FmtHex(egl->getError());
113             *static_cast<EGLImage *>(resultOut) = EGL_NO_IMAGE;
114         }
115     });
116 
117     return egl::NoError();
118 }
119 
orphan(const gl::Context * context,egl::ImageSibling * sibling)120 angle::Result ImageEGL::orphan(const gl::Context *context, egl::ImageSibling *sibling)
121 {
122     // Nothing to do, the native EGLImage will orphan automatically.
123     return angle::Result::Continue;
124 }
125 
setTexture2D(const gl::Context * context,gl::TextureType type,TextureGL * texture,GLenum * outInternalFormat)126 angle::Result ImageEGL::setTexture2D(const gl::Context *context,
127                                      gl::TextureType type,
128                                      TextureGL *texture,
129                                      GLenum *outInternalFormat)
130 {
131     const FunctionsGL *functionsGL = GetFunctionsGL(context);
132     StateManagerGL *stateManager   = GetStateManagerGL(context);
133 
134     // Make sure this texture is bound
135     stateManager->bindTexture(type, texture->getTextureID());
136 
137     // Bind the image to the texture
138     functionsGL->eGLImageTargetTexture2DOES(ToGLenum(type), mImage);
139     *outInternalFormat = mNativeInternalFormat;
140 
141     return angle::Result::Continue;
142 }
143 
setRenderbufferStorage(const gl::Context * context,RenderbufferGL * renderbuffer,GLenum * outInternalFormat)144 angle::Result ImageEGL::setRenderbufferStorage(const gl::Context *context,
145                                                RenderbufferGL *renderbuffer,
146                                                GLenum *outInternalFormat)
147 {
148     const FunctionsGL *functionsGL = GetFunctionsGL(context);
149     StateManagerGL *stateManager   = GetStateManagerGL(context);
150 
151     // Make sure this renderbuffer is bound
152     stateManager->bindRenderbuffer(GL_RENDERBUFFER, renderbuffer->getRenderbufferID());
153 
154     // Bind the image to the renderbuffer
155     functionsGL->eGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage);
156     *outInternalFormat = mNativeInternalFormat;
157 
158     return angle::Result::Continue;
159 }
160 
161 }  // namespace rx
162