| // |
| // Copyright 2018 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // ImageEGL.cpp: Implements the rx::ImageEGL class. |
| |
| #include "libANGLE/renderer/gl/egl/ImageEGL.h" |
| |
| #include "common/utilities.h" |
| #include "libANGLE/Context.h" |
| #include "libANGLE/renderer/gl/FunctionsGL.h" |
| #include "libANGLE/renderer/gl/RenderbufferGL.h" |
| #include "libANGLE/renderer/gl/StateManagerGL.h" |
| #include "libANGLE/renderer/gl/TextureGL.h" |
| #include "libANGLE/renderer/gl/egl/ContextEGL.h" |
| #include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h" |
| #include "libANGLE/renderer/gl/egl/FunctionsEGL.h" |
| |
| namespace rx |
| { |
| |
| ImageEGL::ImageEGL(const egl::ImageState &state, |
| const gl::Context *context, |
| EGLenum target, |
| const egl::AttributeMap &attribs, |
| const FunctionsEGL *egl) |
| : ImageGL(state), |
| mEGL(egl), |
| mContext(EGL_NO_CONTEXT), |
| mTarget(target), |
| mPreserveImage(false), |
| mImage(EGL_NO_IMAGE) |
| { |
| if (context) |
| { |
| mContext = GetImplAs<ContextEGL>(context)->getContext(); |
| } |
| mPreserveImage = attribs.get(EGL_IMAGE_PRESERVED, EGL_FALSE) == EGL_TRUE; |
| } |
| |
| ImageEGL::~ImageEGL() |
| { |
| mEGL->destroyImageKHR(mImage); |
| } |
| |
| egl::Error ImageEGL::initialize(const egl::Display *display) |
| { |
| EGLClientBuffer buffer = nullptr; |
| std::vector<EGLint> attributes; |
| |
| if (egl::IsTextureTarget(mTarget)) |
| { |
| attributes.push_back(EGL_GL_TEXTURE_LEVEL); |
| attributes.push_back(mState.imageIndex.getLevelIndex()); |
| |
| if (mState.imageIndex.has3DLayer()) |
| { |
| attributes.push_back(EGL_GL_TEXTURE_ZOFFSET); |
| attributes.push_back(mState.imageIndex.getLayerIndex()); |
| } |
| |
| const TextureGL *textureGL = GetImplAs<TextureGL>(GetAs<gl::Texture>(mState.source)); |
| buffer = gl_egl::GLObjectHandleToEGLClientBuffer(textureGL->getTextureID()); |
| mNativeInternalFormat = textureGL->getNativeInternalFormat(mState.imageIndex); |
| } |
| else if (egl::IsRenderbufferTarget(mTarget)) |
| { |
| const RenderbufferGL *renderbufferGL = |
| GetImplAs<RenderbufferGL>(GetAs<gl::Renderbuffer>(mState.source)); |
| buffer = gl_egl::GLObjectHandleToEGLClientBuffer(renderbufferGL->getRenderbufferID()); |
| mNativeInternalFormat = renderbufferGL->getNativeInternalFormat(); |
| } |
| else if (egl::IsExternalImageTarget(mTarget)) |
| { |
| const ExternalImageSiblingEGL *externalImageSibling = |
| GetImplAs<ExternalImageSiblingEGL>(GetAs<egl::ExternalImageSibling>(mState.source)); |
| buffer = externalImageSibling->getBuffer(); |
| mNativeInternalFormat = externalImageSibling->getFormat().info->sizedInternalFormat; |
| } |
| else |
| { |
| UNREACHABLE(); |
| } |
| |
| attributes.push_back(EGL_IMAGE_PRESERVED); |
| attributes.push_back(mPreserveImage ? EGL_TRUE : EGL_FALSE); |
| |
| attributes.push_back(EGL_NONE); |
| |
| mImage = mEGL->createImageKHR(mContext, mTarget, buffer, attributes.data()); |
| if (mImage == EGL_NO_IMAGE) |
| { |
| return egl::EglBadAlloc() << "eglCreateImage failed with " << egl::Error(mEGL->getError()); |
| } |
| |
| return egl::NoError(); |
| } |
| |
| angle::Result ImageEGL::orphan(const gl::Context *context, egl::ImageSibling *sibling) |
| { |
| // Nothing to do, the native EGLImage will orphan automatically. |
| return angle::Result::Continue; |
| } |
| |
| angle::Result ImageEGL::setTexture2D(const gl::Context *context, |
| gl::TextureType type, |
| TextureGL *texture, |
| GLenum *outInternalFormat) |
| { |
| const FunctionsGL *functionsGL = GetFunctionsGL(context); |
| StateManagerGL *stateManager = GetStateManagerGL(context); |
| |
| // Make sure this texture is bound |
| stateManager->bindTexture(type, texture->getTextureID()); |
| |
| // Bind the image to the texture |
| functionsGL->eGLImageTargetTexture2DOES(ToGLenum(type), mImage); |
| *outInternalFormat = mNativeInternalFormat; |
| |
| return angle::Result::Continue; |
| } |
| |
| angle::Result ImageEGL::setRenderbufferStorage(const gl::Context *context, |
| RenderbufferGL *renderbuffer, |
| GLenum *outInternalFormat) |
| { |
| const FunctionsGL *functionsGL = GetFunctionsGL(context); |
| StateManagerGL *stateManager = GetStateManagerGL(context); |
| |
| // Make sure this renderbuffer is bound |
| stateManager->bindRenderbuffer(GL_RENDERBUFFER, renderbuffer->getRenderbufferID()); |
| |
| // Bind the image to the renderbuffer |
| functionsGL->eGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mImage); |
| *outInternalFormat = mNativeInternalFormat; |
| |
| return angle::Result::Continue; |
| } |
| |
| } // namespace rx |