A context, by it’s very nature, is either Open VG, Open GL ES [or most recently Open GL], but not a combination of them.
A context is, if you will pardon OOP lingo, an instance of a single rendering API.
That said, it’s perfectly valid to create multiple contexts - one for each API you wish to render with, and simply use eglMakeCurrent() to switch between them (re-using the same drawing surface). This will get you the effect you seem to be looking for.
The only public implementation I am aware of that implements both OpenVG and OpenGL ES is hybrid’s old Rasteroid implementation (if you fail to find that [the hybrid.fi has been down for a long time now], see if the Mesa implementation supports both at the same time - don’t know if it does).
My application would require OpenVG content to be displayed on top of the OpenGL content. Would this be possible via switching contexts using eglMakeCurrent()?
If you have EGL and want to render to a VG texture - sure.
Use eglCreatePbufferFromClientBuffer() to create your surface.
If intending to draw to a GL texture, you could try eglBindTexImage() and see if it works [I have not used it]
Word of warning: these functions are often not implemented in many EGL implementations.
If they are not implemented, try looking for one OpenVG/OpenGL ES extensions that do something similar. I could have sworn I’ve seen something on the topic while browsing the extension registry.
If all else fails, you’re stuck with vgReadPixels() from a regular pbuffer [but you’ll have to suffer performance penalty of reading and writing textures from main memory to GPU memory of course].
Thanks jpilon, I went over the documentation on those extensions, and they seem like they’re just what I was looking for. Unfortunately, I’m pretty sure our device doesn’t have support for these extensions. Do you think there exist ways to convert the OpenVG context/surface into a Texture2D using just standard EGL methods?
At this time I’d also like to discuss another possibility: overlaying the OpenVG & OpenGL surfaces onto the same display. Here’s the pseudo-code:
(DO NOT clear screen, screen is left dirty intentionally)
render ogl stuff
swap buffer (display, ogl)
Would this work to render OpenVG & OpenGL onto the same display? The only red-flag I see here is if swapbuffer actually replaces the entire display with the surface. If that’s the case, we’d probably only see the OpenGL content… which is not the desired result.
I was under the impression the surfaces couldn’t be ‘shared’ by both ogl & ovg? Are they actually share-able assuming they have the same config attributes? This would be great!
Ivo, could you explain further what you meant by this:
makecurrent the ogl context with the same surface (you may need to makecurrent() with NULL parameters first, depending on implementation)
What’s the reason for using eglMakeCurrent() with the NULL parameters first?
No - surfaces are sharable (think of them as just a handle to a framebuffer). When you create them, you need to make sure the config supports both ovg and ogl rendering, but I don’t see that as much of a problem for any driver which supports both ovg and ogl rendering - chances are high that all valid configs will (but it never hurts to check).
The reason for the NULL makecurrent is that some egl implementations might return errors if the surface you are making current is the same surface that’s bound to the context that you are replacing (giving some surface in use error or something). It shouldn’t happen IMHO, but I think I have run into a bug like that once in some driver or other at some point.
I think the EGL specification enforces this behavior, so it would be a bug if you didn’t get an error when trying to make current a surface that’s already bound to another context. So if you want to write portable EGL code, it’s probably safer to make current with NULL, however it’s possible doing this could have a negative impact on perforce as it could trigger some expensive state updates. So, I would say the decision depends if you’re focused on a particular platform or not.
create ovg image object, load with image data and bind ovg image to pbuffer using eglCreatePbufferFromClientBuffer
pbuffer = eglCreatePbufferFromClientBuffer(dsp, EGL_OPENVG_IMAGE,
(EGLClientBuffer)ovgimage, config, attrib_list);
create shared context
bind ogles
make shared context current to the thread
Bind ovg texture (pbuffer) to ogl primitives using eglBindTexImage
glBindTexture(GL_TEXTURE_2D, pbuffer);
eglBindTexImage(dsplay, pbuffer, EGL_BACK_BUFFER);
In the above implementation eglBindTexImage returns EGL_BAD_MATCH. surface, display are shared and created only once.
If in 4) and you’re creating a context, the bound api is still openvg - you’ll be creating an openVG context.
Thus your make current will bind a openvg context.
Other than that, as I said in some other post, I have not used eglBindTextImage(), so I’m afraid the EGL spec can help you more than I can there. Did you set/leave the EGL_TEXTURE_FORMAT surface attribute to EGL_NO_TEXTURE?
No you can’t share a context across different APIs. Internally, what a context is an instance of the current API state (everything from what paints are created and bound, to attributes like VG_LINE_WIDTH, to internal state you never see). Contexts by their very nature are API specific (GL state is very different from VG state afterall). So sharing a VG context with an OpenGL ES context is a mistake.
To render to a texture, you should be trying to transform a VGImage (OpenVG) into pbuffer (EGL), after you do this, the pbuffer should still be valid (because it’s EGL) even after the OpenVG context is made not current (and you wont be able to use the VGImage again until the pbuffer is destroyed). You should then be able to use the pbuffer as a normal rendering surface for any API (if your implementation crashes doing this, it’s a bug).