0

This is what I'm doing:

  • In native code, I'm creating an EGL texture from AHardwareBuffer and pass ID of the EGL texture back to Java
  • In java I create SurfaceTexture from that texture ID and Surface from that SurfaceTexture
  • Pass Surface to native code and get ANativeWindow* from it using ANativeWindow_fromSurface
  • In java, on the same thread I call UpdateTexImage on the SurfaceTexture in a loop
  • C++, in a new thread I feed the ANativeWindow* to a decoder that starts writing frames to it.

UpdateTexImage fails with the following: bindTextureImage: clearing GL error: 0x502 bindTextureImage: error binding external image: 0x502

If I don't start the decoder, updateTexImage doesn't fail If I use a normal texture and not a AHardwareBuffer backed texture, updateTexImage and decoder don't fail

The reason I'm using AHardwareBuffer backed texture is because that makes it easy(ish) to do InterOp with Vulkan, and I will need that later. Relevant code stripped of error checking is below.

Grateful for advice.


This is how I create AHardwareBuffer

m_pAndroidHardwareBuffer = nullptr;
    AHardwareBuffer_Desc desc = {};
    desc.width = w;
    desc.height = h;
    desc.layers = 1;
    desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
    desc.format = AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 ;//AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
    int aRes = AHardwareBuffer_allocate(&desc, &m_pAndroidHardwareBuffer);

This is how I create EGL texture from the hardware buffer

    // Create EGLClientBuffer from AHardwareBuffer
    EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(m_pAndroidHardwareBuffer);
    const EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};

    // Create the EGLImage from EGLClientBuffer
    EGLImageKHR eglImage = eglCreateImageKHR(m_eglDisplay, m_OutputContext, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, eglImageAttributes);

    // generate EGL texture from EGLImage
    GLuint texture = 0;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    // Use the EGLImage as the texture's data source
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES) eglImage);
    // Set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D, 0);

This is how I create SurfaceTexture and Surface in Java: (textureID is GLuint texture from above)

mDecodeTargetTexture = new SurfaceTexture(textureID, false);
mDecodeTargetTexture.setOnFrameAvailableListener(null);
mDecodeTargetSurface = new Surface(mDecodeTargetTexture);

I've been reading the implementation of UpdateTexImage here https://android.googlesource.com/platform/frameworks/native/+/marshmallow-mr2-release/libs/gui/GLConsumer.cpp And I'm starting to suspect that what I want to do is impossible.

I've also looked into other ways to do EGL-Vulkan Interop but this seems the most straight forward

0 Answers0