// // 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(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 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(GetAs(mState.source)); buffer = gl_egl::GLObjectHandleToEGLClientBuffer(textureGL->getTextureID()); mNativeInternalFormat = textureGL->getNativeInternalFormat(mState.imageIndex); } else if (egl::IsRenderbufferTarget(mTarget)) { const RenderbufferGL *renderbufferGL = GetImplAs(GetAs(mState.source)); buffer = gl_egl::GLObjectHandleToEGLClientBuffer(renderbufferGL->getRenderbufferID()); mNativeInternalFormat = renderbufferGL->getNativeInternalFormat(); } else if (egl::IsExternalImageTarget(mTarget)) { const ExternalImageSiblingEGL *externalImageSibling = GetImplAs(GetAs(mState.source)); buffer = externalImageSibling->getBuffer(); mNativeInternalFormat = externalImageSibling->getFormat().info->sizedInternalFormat; // Add any additional attributes this type of image sibline requires externalImageSibling->getImageCreationAttributes(&attributes); } 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