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