2

I'm trying to speedup the rendering (both latency and throughput wise) in the Inkscape vector image editor so that it can be more artist friendly.

I'm trying to decide whether to draw directly to the window or draw to an intermediate offscreen surface and then copy it to the window.

If the whole canvas had to be redrawn every time, then drawing directly to the window will clearly be faster by conserving memory bandwidth. But unfortunately, Inkscape doesn't do GPU rendering so it can't afford to redraw the whole window, only the rectangles that were invalidated.

Let's say i have 2 rectangles that need to be redrawn. enter image description here

The 1st method is to get acquire a sub surface for each rectangle using gdk_window_begin_draw_frame(rect), draw, and send it to the screen. But the disadvantage is you can't draw the 2 in parallel because GTK only allows 1 rectangle to be locked at a time.

The 2nd method I thought of is to ask the windowing system (GTK) for the bounding box of the 2 rectangles. Then draw the 2 in parallel, and send the results to the screen. But here the problem is GTK doesn't preserve the old contents of the window - it clears the entire update region, creating blank areas in the gap between the 2 rectangles.

So for the 2nd method to work, I could either ask the GUI toolkit to preserve the contents of the window or render to an intermediate buffer that preserves the whole window. But that would require extra copying. I want to know is it customary to discard the previous contents when drawing? I'm aware that discarding has the performance advantage of not having to wait for previous rendering to complete and not having to read back from GPU memory to CPU memory. That advice is given for OpenGL's glMapBuffer() and DirectX surfaces' LockRect(). But glMapBuffer() does have an option to return the old contents. So should GTK have such an option too? Or is that too much to ask?

It seems a lot of the problems I face are artificial due to the GUI toolkit limitations. For example, if the GUI toolkit lets you update multiple regions in parallel, then the 1st method would work and be easier. OpenGL lets you do that with glMapBufferRange().

I would like a good solution for GTK, but at the same time I would like to know if you had very direct access to the GPU hardware, how would you implement the partial drawing I described most efficiently?

Yale Zhang
  • 1,447
  • 12
  • 30
  • If OpenGl does what you want, why don't you use OpenGl within Gtk (or similar)? – theGtknerd Jan 19 '18 at 11:50
  • Why don't you just call `gtk_widget_queue_draw_area` or `gtk_widget_queue_draw_region`? – liberforce Jan 19 '18 at 14:41
  • @theGtknerd - it would be great to port to OpenGL but implementing curved path rendering with so many different fill modes (solid, linear gradient, mesh gradient, ...) would be a huge task. Cairo has an OpenGL backend but it's not complete exactly because of those complexities. NVIDIA has path rendering extensions for OpenGL but those don't support all SVG rendering modes either. Adobe uses it in Illustrator so they must've extended it. My focus now is just on transfering the final software rendered image to the windowing system efficiently. – Yale Zhang Jan 21 '18 at 04:27
  • @liberforce - I would like to avoid gtk_widget_queue_draw_area() because those functions schedule a redraw (expose) in the future instead of drawing now for minimum latency. And it won't allow you to process the redraw (expose) events in parallel since the event processing is inherently serial. I don't know how frequently multiple rectangles get invalidated at the same time (when you shrink a rectangle I suppose), so I might be over emphasizing the importance of redrawing multiple rectangles in ||. – Yale Zhang Jan 21 '18 at 04:40
  • I think you don't care if the redraw is in the future as long as you're redrawing at a high-enough frequency. You're bound to your screen latency anyway. Drawing at 60fps is just at worse 16.7ms latency. Calling `gtk_widget_queue_draw_region` give in one single call all the areas you need to redraw and generates the appropriate events to process the redraws. Making sure these areas are minimal is what can speedup, as it will be used as a clipping mask in draw operations by cairo. – liberforce Jan 22 '18 at 11:35
  • Anyway, as that's a pretty advanced topic, make sure you ask about it to the GTK+ developers on their IRC channel. – liberforce Jan 22 '18 at 11:37

0 Answers0