ofxCairo [Performance issues]

I just started working on a simple add-on for toggling an ofCairoRenderer on/off and drawing the results to screen. (In my case to get access to the improved line-rendering features of cairo over openGL).

Github repo here: https://github.com/bgstaal/ofxCairo

When I started working on an example I quickly realized that the performance drop when using cairo for rendering was pretty severe. (Check out the example project in the GitHub repo.) On my prev gen MacBook Pro the cpu usage for the app goes up to nearly 100% after running the cairo renderer for about 10 seconds while it’s at about 5% when using the openGL renderer. The fps also drops to about 10 while the openGL renderer is at a steady 90-100 fps. I even tried commenting out the code that uploads and draws the texture but the results are pretty much the same.

Is cairo really that slow at rendering or is it the ofCairoRenderer implementation that is the issue?

Is it silly to think that one can use cairo for real time rendering? If so, are there any better alternatives for rendering smooth lines with precise control over line-capping/joining?

afaik, cairo (which runs on the cpu) is just really slow compared to gpu-accelerated opengl :frowning: i don’t think it has anything to do with OF…

Correct me if I am wrong…

ofLine / ofPolyline are always going to quite limited in terms of line capping / joining. They draw using GL_LINES / GL_LINE_STRIP which itself has no line capping or no joining implementation. These draw modes are, while super convenient, surprisingly inefficient.

Possible options are probably to roll your own procedures for drawing:

  1. Meshes: creating a mesh along for each line, putting a circle (or other shape) at each end and joint.

  2. Mesh: create a single mesh from ofPolyline, doing the above but optimising so the output is one mesh.

  3. Texture: if you only need 2d, perhaps use a texture and manipulate the pixels directly. 1st make a function that draws a circle on to the texture at an xy coordinate. Get your polyline at resample it (.getResampledBySpacing()) by one pixel. Iterate through the line drawing you circle at each point. If your line is not changing each frame (say in a drawing app) this should be fast enough. If you want more features, instead of having a function that draws a circle on a texture, have a function that copies one texture into another. Then you can manipulate the source texture (radius for width, transparency from centre for smoothness).

I was rolling with this 3rd technique for a drawing app prototype and it was working quite well. We’ve since switch to doing it in JavaScript so the code was left a bit scrappy.

@kylemcdonald I’t seems that you are right. I have done a similar test using CoreGraphics to see if there are any performance-advancements. Without doing exact benchmarks it still seems that a cpu based renderer will have a tough time re-rendering even less then 100 line segments every frame. Looking at other platforms like Html canvas & Flash it seems that it is possible to draw a lot more complex graphics, a lot faster though (I had a look at the source code for WebKit and it looks like they are using CG/QT as rendering backend for 2d canvas contexts). I guess they have implemented a clever system for redrawing only the dirty regions at any time?

@Rc1 You are right about how ofLines/Polylines are drawn in the default renderer. When switching to a rendering backend like cairo or CoreGraphics they are drawn differently though. Take a look at screenshots from the example app in the github repo:

Built in openGL renderer:

Cairo renderer:

As you can see, the results from using cairo for rendering is a lot better. The only issues I’m having is with performance.

About your suggestion of implementing my own rasterizer: I really doubt that I can do a better job than the people working on an professional grade graphics library, both in regards to quality and performance. But hey, that might just be my limitations :smiley:

I’ve used Cairo for some quite heavy rendering in Cinder and it’s been reasonably performant there but I wasn’t drawing every frame. I also threaded the rendering and did the drawing to an FBO.

Drawing circles or textures along a line in a shader is a good technique, you could do this like you do a point sprite. Otherwise you’re looking at tessellating a line into quads or triangles (there’s a Processing implementation here: http://wiki.processing.org/w/Stroke-attributes-in-OpenGL, but you can see how gnarly it is).

@joshua that approach sounds like a great way to render complex vector graphics that never change, like svg assets. In my case I need the ability to do dynamic graphics in real time.

Anyways, I found another solution that seems to cover my needs.

Thread here: http://forum.openframeworks.cc/t/ofxshivavg-smooth-2d-graphics-in-of/12574/0

Code here:

(In the repo I try to separate the oF-specific part of the code from the more general rendering code so that it can be re-purposed as a cinder-block as well)