Render cairo surface directly to OpenGL texture - c++

I'm using cairo (http://cairographics.org) in combination with an OpenGL based 3D graphics library.
I'm currently using the 3D library on Windows, but I'm hoping to receive an answer that is platform independent.
This is all done in c++.
I've got the straight forward approach working which is to use cairo_image_surface_create in combination with glTexImage2D to get an OpenGL texture.
However, from what I've been able to gather from the documentation cairo_image_surface_create uses a CPU-based renderer and writes the output to main memory.
I've come to understand cairo has a new OpenGL based renderer which renders its output directly on the GPU, but I'm unable to find concrete details on how to use it.
(I've found some details on the glitz-renderer, but it seems to be deprecated and removed).
I've checked the surface list at: http://www.cairographics.org/manual/cairo-surfaces.html, but I feel I'm missing the obvious.
My question is: How do I create a cairo surface that renders directly to an OpenGL texture?
Do note: I'll need to be able to use the texture directly (without copying) to display the cairo output on screen.

As of 2015, Cairo GL SDL2 is probably the best way to use Cairo GL
https://github.com/cubicool/cairo-gl-sdl2
If you are on an OS like Ubuntu where cairo is not compiled with GL you will need to compile your own copy and let cairo-gl-sdl2 know where it is.

The glitz renderer has been replaced by the experimental cairo-gl backend.
You'll find a mention of it in:
http://cairographics.org/OpenGL/
Can't say if it's stable enough to be used though.
Once you have a gl backend working, you can render into a Framebuffer Object to render directly in a given texture.

I did it using GL_BGRA.
int tex_w = cairo_image_surface_get_width(surface);
int tex_h = cairo_image_surface_get_height(surface);
unsigned char* data = cairo_image_surface_get_data(surface);
then do
glTexImage2D(GL_TEXTURE_2D, 0, 4, tex_w,tex_h, 0,GL_BGRA, GL_UNSIGNED_BYTE, data);
when you create the texture.
Use glTexSubImage2D(...) to update th texture when the image content changes. For speed
set the filters for the texture to GL_NEAREST

Related

How to Convert Existing OpenGL Texture to Metal Texture

I am working on developing some FxPlug plugins for Motion and FCP X. Ultimately, I'd like to have them render in Metal as Apple is deprecating OpenGL.
I'm currently using CoreImage, and while I've been able to use the CoreImage functionality to do Metal processing outside of the FxPlug SDK, FxPlug only provides me the frame as an OpenGL texture. I've tried just passing this into the CoreImage filter, but I end up getting this error:
Cannot render image (with an input GL texture) using a metal-DG context.
After a bit of research, I found that I can supposedly use CVPixelBuffers to share textures between the two, but after trying to write code utilizing this method for a while, I've come to the belief that this was intended as a way to WRITE (as in, create from scratch) to a shared buffer, but not convert between. While this may be incorrect, I cannot find a way to get the existing GL texture to exist in a CVPixelBuffer.
TL;DR: I've found ways to get a resulting Metal or OpenGL texture FROM a CVPixelBuffer, but I cannot find a way to create a CVPixelBuffer from an existing OpenGL texture. My heart is not set on this method, as my ultimate goal is to simply convert from OpenGL to Metal, then back to OpenGL (ideally in an efficient way).
Has anyone else found a way to work with FxPlug with Metal? Is there a good way to convert from an OpenGL texture to Metal/CVPixelBuffer?
I have written an FxPlug that uses both OpenGL textures and Metal textures. The thing you're looking for is an IOSurface. They are textures that can be used with either Metal or OpenGL, though they have some limitations. As such, if you already have a Metal or OpenGL texture, you must copy it into an IOSurface to use it with the other system.
To create an IOSurface you can either use CVPixelBuffers (by including the kCVPixelBufferIOSurfacePropertiesKey) or you can directly create one using the IOSurface class defined in <IOSurface/IOSurfaceObjC.h>.
Once you have an IOSurface, you can copy your OpenGL texture into it by getting an OpenGL texture from the IOSurface via CGLTexImageIOSurface2D() (defined in <OpenGL/CGLIOSurface.h>). You then take that texture and use it as the backing texture for an FBO. You can, for example, draw a textured quad into it using the input FxTexture as the texture. Be sure the call glFlush() when done!
Next take the IOSurface and create a MTLTexture from it via -[MTLDevice newTextureWithDescriptor:ioSurface:plane:] (described here). You'll want to create an output IOSurface to draw into and also create a MTLTexture from it. Do your Metal rendering into the output MTLTexture. Next, take the output IOSurface and create an OpenGL texture out of it via CGLTexImageIOSurface2D(). Now copy that OpenGL texture into the output FxTexture either by using it as the backing of a texture-backed FBO or whatever other method you prefer.
As you can see, the downside of this is that each render requires 2 copies - 1 of the input into an IOSurface and 1 of the output IOSurface into the output texture the app gives you. The other downside is that this is probably all moot, as with Apple having announced publicly that they're ending support for OpenGL, they're probably working on a Metal-based solution already. It may be extra work to do it all yourself. (Though the upside is that you can use that same code in other host applications that only support OpenGL.)

OpenGL blending not working with DIB section

I’m trying to render to a DIB section with blending using OpenGL on XP. I’m trying to multiply the source and destination colour components together, as in:
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
However, it fails to draw a blended image. By changing the type of blending I ask for, I can make it draw as if without blending, or not draw at all. But it refuses to blend.
Here are details about the OpenGL version I’m using:
Vendor: Microsoft Corporation
Renderer: GDI Generic
Version: 1.1.0
Extensions: GL_WIN_swap_hint GL_EXT_bgra GL_EXT_paletted_texture
I was aware that I’m limited to “generic” (software) rendering with DIB sections, but I did not expect blending to fail. I have searched for confirmation about whether blending is or is not supported in such cases, but to no avail.
glBlendFunc(GL_DST_COLOR, GL_ZERO);
^^^ oh?
Transparency, Translucency, and Blending:
15.060 I want to use blending but can’t get destination alpha to work. Can I blend or create a transparency effect without destination alpha?
Many OpenGL devices don't support destination alpha. In particular, the OpenGL 1.1 software rendering libraries from Microsoft don't support it. The OpenGL specification doesn't require it.
Also:
No Alpha in the Framebuffer:
If you are doing Blending and you need a destination alpha, you need to make sure that your render target has one. This is easy to ensure when rendering to a Framebuffer Object. But with a Default Framebuffer, it depends on how you created your OpenGL Context.
For example, if you are using GLUT, you need to make sure you pass GLUT_ALPHA to the glutInitDisplayMode function.
Ok I made a silly mistake: I misread my own script code and ended up applying the texture in the wrong rendering pass. OpenGL wasn’t to blame, and blending DOES work.

SDL and Dynamic Super Resolution?

Is there a way to do DSR with SDL and OpenGL? As far as I know this is an NVidia thing (I have an NVidia card), so would this be something done in a shader? I can't find anything in the SDL reference and some googling around doesn't reveal anything either.
On the top of my head, the best way to do that would be using framebuffers.
You do your rendering on a larger FBO (FBO Documentation) than your screen resolution, then you downsample your FBO to another framebuffer that fit the size of the screen using a pixel shader.
This is OpenGL-specific, so you should be able to do it on SDL.
The OpenGL wiki has some snippet of code to render to FBO, it should be useful to get you started. And since what you wanna do is basicly downsampling, you might be interested in this thread.

Render text to an opengl texture in a standalone program

I'm using opengl+glut and wondering if there is a library out there that can render text to a buffer in a format consistent with opengl textures.
Check out FTGL. It uses FreeType to render text to textures, and can also create polygons if you feel like it. The tutorial shows the basic usage nicely.

openGL into png

I'm trying to convert an openGL [edit: "card that I drew"(?):) thx unwind]containing a lot of textures (nothing moving) into one PNG file that I can use in another part of the framework I'm working with. Is there a C++ library that does that?
thanks!
If you simply mean "take a scene rendered by OpenGL and save it as an image," then it is fairly straightforward. You need to read the scene with glReadPixels(), and then convert that data to an image format such as PNG (http://www.opengl.org/resources/faq/technical/miscellaneous.htm).
There are also more efficient ways of achieving this, such as using FBOs. Instead of rendering the scene directly into the framebuffer, you can render it to a texture via an FBO, then render that texture as a full-screen quad. You can then take this texture and save it to a file (using glGetTexImage, for example).
What is an "OpenGL file"? OpenGL is a graphics API, it doesn't specify any file formats. Do you mean a DDS file, or something?
There are better ways to make a compose texture than drawing them with the graphics card. This is really something you would want to do before hand on the cpu, store and then use as and when you need it with opengl