Shared texture between JAVA openGL ES and OpenCL C++

Hi,

I spend 1 month trying to anderstand how a could use Image texture in my OpenCL C++ progran.

i use kirin 970 whut ARM G72 on huawei honor play phonne from paris.

I am working with JAVA openGL ES 3.2 and i used JNI call to process data using OpenCL in C++ and Multithread work on CPU .

When i trie to get the current context from C++ using eglGetCurrentContext() or eglGetCurrentContext() i got no context or display in return.

the problem is that i need both to use :

            CL_GL_CONTEXT_KHR,    (cl_context_properties)context,
            CL_EGL_DISPLAY_KHR,   (cl_context_properties)display,

I found that the SurfaceTexture class can acces to the Context to create EGLImageKHR which can be used with openCL.

Is there a way to share Image texture or data between JAVA OpenGL ES and C++.

And if it is possible. How ti implement it. I would like to retreive texture from FrameBuffer and then acces it by OpenCL.

In fact the pupose is to do somme work in OpenCL then display it and procees it by shader then send it back to OpenCL an bach again to Java OpenGL. I know i coul use Compute shader but i really need to do some work in multithread C++ and openCL (it is a lot lot faster) for real time.

Thank for the answer and may be another idea to get it work.

regards

Hi,

I am sorry to insist on the possibility to get EGL context set by Java Renderer.Thread.

I just need to know if it is possible or not. And if it is possible the way to get it. I for OpenCL openGL interop. So i could manage my double or triple buffering myself with EGLImageKHR.

I asked the question on other forum and No body answer. It is easy to said yes or not.

And i do not anderstand why the EGL context is TABOU. Nobody can explain clearly what is it use for. and the reason why it is related to a thread in JAVA openGL ES.

I think it is important to anderstand things that we are working with.

Regards.

Well, it’s possible to do that between Cuda and OpenGL, and it’s somewhat straightforward (just need some OpenGL object registration on Cuda’s side). So my belief is that it must be possible to do so between OpenCL and OpenGL. You may want to have a deep look at the OpenGL standard.

Well, a EGLContext can be current on at most 1 thread at a time. So, if you call eglGetCurrentContext on a thread where you never called eglMakeCurrent it is expected that EGL_NO_CONTEXT is returned, because there is no current context.
Likewise it is an error to attempt to make an EGLContext current on more than 1 thread at the same time, that will return error EGL_BAD_ACCESS from the eglMakeCurrent call. So, to “transfer” a context from being current on thread A to being current on thread B, you must first call eglMakeCurrent with EGL_NO_CONTEXT on thread A, before calling eglMakeCurrent with the context argument on thread B.

And i do not anderstand why the EGL context is TABOU. Nobody can explain clearly what is it use for. and the reason why it is related to a thread in JAVA openGL ES.

It is not specified what a EGLContext “looks” like, because it is essentially a data structure that is maintained and defined by the graphics driver. You can think of it as your connection to OpenGL. The reason it is a thread local object is because otherwise (almost) every OpenGL command would require the context object as an argument. When OpenGL was originally designed (at a time when multi threading was far less common) that was considered an annoyance and so the context was attached to the current thread where each OpenGL command could retrieve it internally without the caller having to provide it all the time. For a different approach compare how (almost) every Vulkan command takes a VkDevice, VkCommandBuffer, VkInstance, or other dispatchable object handle as its first argument - these allow the graphics driver to locate its internal data structures similarly to how OpenGL commands use the context.

Thanks for the answers.

So if i anderstoud. EGL can only be used by one thread a the time.
When i use SurfaceTexture class in java. Java call native library to execute the cpp code. And they do not need to call makecurrent they just acces the context using eglgetcurrentContext.
Why i caanot do it with my own library.
It is possible to do something so my librery could be accessing the EGL context.
I find out thet the EGL context is Private inside GLSurfaceViex.rendrer.thread. But android native can acces it, isn it. So i should also be able to acces it inside my app or it is not possible.

I’m afraid I don’t know, but it appears your library does something different here.

EGLContext is a typedef for void * (see egl.h) and on Android I suppose you get the pointer value from EGLContext.getNativeHandle, inherited from EGLObjectHandle. You could pass that to your native code and cast it back to the right type.

Whether you use egl, wgl, glx, qt… the context logic is the same. Each context can be current by a single thread at a time, and each thread can make a single context current at a time. Here you have the relation you was looking for between the context and you thread.
Once a context is made current on a thread, it will remain current until it is explicitly made not-current, another context is made current, or the context is destroyed.
Your library is most probably managing all of this internally to ease common GL development. If you can create threads, windows and egl contexts (and make them current, even implicitly), you have everything to do OpenGL in a multithreading environment.

Hi,

@carsten_neumann

i tried already to send eglGetCurrentContext().getNativeHandle() trough JNI as Jobject but it did not work. May be the cast ? How would you do the cast from Jobject to EGLContext ;))

@Silence

So in multithreading each thread need to create is onw context (i can do that). But i will not be able to share Object with other context. Context is usefull for example if you are displaying many 3D object inside the same HTLM page for example. Each ThreJ or openGL will work with is own shader and texture.

In My case it is more shared context. Using the same context with Java OpenGL and C++ OpenCL. I am a little bit confised with this EGL Context :)).

In the case of SurfeceView.cpp used by Java OpenGL. When i use the update méthod in java, i am not in the Renderer.thread. But the native can acces the current EGL context easely. But when i use my library fonction i can get the EGL context. So the EGL context i shared with Opengl Native Library but not with other library. There is may something to add in my library to be able to acces the EGL Context.

I did not anderstand the last part with multithreading environment. Do you meens that we can have One context per Thread using the same dislplay.

I see EGL Context like a box how got it’s own object to manage that those object cannot be used by another context.

I am quite confused with this EGL Context notion. I read about it but it look like i have misanderstoud something. I am french so my english is not so good. I may confuse term some time. That why i am a little insisting. Because i feel that there is something how escape my comprhéension. ;))

It is not a kind of stupidity, it is just that it is already not easy and not in my mother linguage. So fell lost about the use of this EGL context :)) ;))

Anyway thanks for you help and patience ;))

I don’t know enough about JAVA or JNI to explain the details, but you get a long from getNativeHandle(), which is probably just the pointer value stored as an integer value. If you can pass an integer (of sufficient bit size) through JNI you can cast the integer value back to the pointer.

If you want to share OpenGL objects (textures, buffers, etc) between multiple contexts you must put them into a “share group”. This is achieved by passing an existing context to the share_context argument of eglCreateContext. If the existing context is already part of a “share group” (i.e. already shares objects with other contexts) the new context becomes a member of that share group, otherwise the two contexts are the only members of the share group.

No, as long as the same context is not made current by several threads at the same time.

No either. The OpenCL context is not the same thing as the OpenGL context. The OpenGL Context will give you a mean to do OpenGL with the window you provided to, whereas the OpenCL context will give you a mean to do GPGPU on a device. They could both work on the same graphic card, but they don’t work together for the same thing.

What you want is to find how OpenCL can feed OpenGL buffers and texture storages. Unfortunately I don’t have this answer. But as I said in a previous post, this is straightforward with Cuda, so my supposition is that it should be as easy with OpenCL. You might try the OpenCL forum, read deeply the OpenGL specs, or try some researches on Google.

Thanks two both of you.

@carsten_neumann
I tried this morning casting long to pointer but it does not work. I suppose that the problem is from ARM. Because if i create an EGL context in c++. I got no problem to use it fir KHR. I just cannot get the current context (if java make it current ?) from C++.

@Silence
Thanks for the explication. I at least learned something about EGL ;))

So at the end. As i find a way to use buffer between C++ OpenCL and Java OpenGL.
I think i will give up the isea of testing KHR_Image even if i think taht could be faster.

I do still not anderstand the use of EGL context by thread. By application yes for sure. By by thread i do not anderstand. By defualt every develloper know that it is not a good idéa to acces any data at the same by two process. And even more for feeding a driver. I will tried to look for shared context gruop to see. But i am feed up with this nearly intutile concept of context/thread specially on mobile where there is only one apk running at the time. It is only usefull for Web when loading 3D threej, openGL.

For for the rest ? OpenGL just need to know the program how will run the shader and the ressource how are available and this related to a surface.

Aniway using buffer is very faster, consume less energy(no need of transfer). You just need to managed it correctly ;)) Specially with shared memory and mobile. I think that shared memory could even be ported to desktop in the futur. AI will be asking for. I think that IOS as already used this option in some version.

So gye bye EGL and happy buffer pointer ;))

I GIVE UP EGL it is just a new X11 or Xwindow ameliorated. But we only need context for different running procces not thread.

Thanks again for the answer and good work ;))

The usual distinction between process and thread is that threads within a single process share the same address space, while each process has its own distinct address space. In other words you can pass a pointer to an object between the threads of a process and it still points to the object. If you do the same thing between processes it is unlikely to point to anything useful let alone the same object.

Now, within a single process you may have multiple threads that each want to perform some OpenGL calls, e.g. maybe you have a helper thread that loads image data from disk and places it into texture objects and a main thread that renders. In order to do that it is common create an OpenGL context (EGLContext) for each thread and set the contexts up to share objects. If you were to use only a single context you’d have to make it not-current on the main thread (and not make any OpenGL calls until the context is current on the main thread again!), make it current on the helper thread, perform OpenGL calls on the helper thread, make the context not-current on the helper thread, finally make it current on the main thread again and continue rendering on the main thread. Which is painful and probably not very fast either because eglMakeCurrent is often an expensive operation.

thanks for the final explanation cersten_newman :wink:

You can comunication between process using IPC and global memory, i use to be not bad at this long time ago ;))

But you are rigth ! using MakeCurrent for every frame is not a really good idéa. And i must admit that is time i did not find the issue with EGL. (i call it EGL nightmare now ;)))

I will stand with buffer for the communication C++ -> JAVA and framebuffer/PBO/readpixel/glMapBufferRange from Java -> C++. It seems to be very fast on ARM G72. I am sur they use pointer on the Buffer. But i think it would be a bad idea to change the readpixel size to get it so fast. I got 120 frame per seconde on readpixel this way. So why to try with EGL and interop KHR_Image.

I just wanted to anderstant and try for my personnal knowledge. I spend already to much time on it. And more i anderstand it more i feel like it is an old way to bring external image to openGL external extension. With Metal and vulkan and AI, things will change ;)) Specially on mobile ;))

Sorry for insisting but i think it is clear for me with EGL context nigthmare ;)) ;))