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 else
83 {
84 UNREACHABLE();
85 }
86
87 attributes.push_back(EGL_IMAGE_PRESERVED);
88 attributes.push_back(mPreserveImage ? EGL_TRUE : EGL_FALSE);
89
90 attributes.push_back(EGL_NONE);
91
92 mImage = mEGL->createImageKHR(mContext, mTarget, buffer, attributes.data());
93 if (mImage == EGL_NO_IMAGE)
94 {
95 return egl::EglBadAlloc() << "eglCreateImage failed with " << egl::Error(mEGL->getError());
96 }
97
98 return egl::NoError();
99 }
100
orphan(const gl::Context * context,egl::ImageSibling * sibling)101 angle::Result ImageEGL::orphan(const gl::Context *context, egl::ImageSibling *sibling)
102 {
103 // Nothing to do, the native EGLImage will orphan automatically.
104 return angle::Result::Continue;
105 }
106
setTexture2D(const gl::Context * context,gl::TextureType type,TextureGL * texture,GLenum * outInternalFormat)107 angle::Result ImageEGL::setTexture2D(const gl::Context *context,
108 gl::TextureType type,
109 TextureGL *texture,
110 GLenum *outInternalFormat)
111 {
112 const FunctionsGL *functionsGL = GetFunctionsGL(context);
113 StateManagerGL *stateManager = GetStateManagerGL(context);
114
115 // Make sure this texture is bound
116 stateManager->bindTexture(type, texture->getTextureID());
117
118 // Bind the image to the texture
119 functionsGL->eGLImageTargetTexture2DOES(ToGLenum(type), mImage);
120 *outInternalFormat = mNativeInternalFormat;
121
122 return angle::Result::Continue;
123 }
124
setRenderbufferStorage(const gl::Context * context,RenderbufferGL * renderbuffer,GLenum * outInternalFormat)125 angle::Result ImageEGL::setRenderbufferStorage(const gl::Context *context,
126 RenderbufferGL *renderbuffer,
127 GLenum *outInternalFormat)
128 {
129 const FunctionsGL *functionsGL = GetFunctionsGL(context);
130 StateManagerGL *stateManager = GetStateManagerGL(context);
131
132 // Make sure this renderbuffer is bound
133 stateManager->bindRenderbuffer(GL_RENDERBUFFER, renderbuffer->getRenderbufferID());
134
135 // Bind the image to the renderbuffer
136 functionsGL->eGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage);
137 *outInternalFormat = mNativeInternalFormat;
138
139 return angle::Result::Continue;
140 }
141
142 } // namespace rx
143