Optimized drawing of background picture


#1

Current application is working so well i decided to start profiling it. It turns out i spend over 50% of the total CPU time redrawing the background image of my GUI. The background image is redrawed often, i guess, because of child components changing. This doesn't really seem ideal, so i would like to optimize it. 

I've tried implementing the background image as a child component of the main gui (DrawableImage), as an image and drawing it in maingui::paint(), but nothing really changes. Here's a view of Instruments profiling it:

It seems to spend almost all of the time 'acquireing' the image, so i made sure the image doesn't share it's data (using duplicateIfShared) - it didn't help though. As we can see, the actual rendering takes litterally no time.

Is there any way to cache the rendering of the image and quickly copy it in a paint() call, instead of redrawing and rendering it constantly?

 


#2

Okay the 'acquire' part has nothing to do with locking semantics, theres a world below that function call!

 

So basically, it seems all the cpu time is spent encoding + decoding + transforming the image each rendering. That doesn't seem clever, any way to prevent this? Has this got something to do with the type of images i load?


#3

I'm no expert, but have you tried turning on JUCE_ENABLE_REPAINT_DEBUGGING in AppConfig.h? It will tell you more about what is being painted and when. I had a painting problem recently that I was able to sort by only repainting the part of my component that needed repainting using Component::repaint (int x, int y, int width, int height). It dramatically reduced the CPU strain.  


#4

Hey, that's a neat feature.

It seems to work as expected, it only redraws the parts it should. It doesn't repaint the whole background picture when the childs change, that's good. But still, having no background image as opposed to having one increases cpu load extremely. 


#5

Why don't you draw directly onto your main component in its paint routine rather than drawing onto a DrawableImage which you then place on to your main component? You can draw the image directly without using a drawable image? I normally do this with an Image and Graphics::drawImage(). Never had any CPU issues. 


#6

As said in the topic:

I've tried implementing the background image as a child component of the main gui (DrawableImage), as an image and drawing it in maingui::paint(), but nothing really changes.

It makes no difference. I also tried using SoftwareImageType, changes nothing. I tried generating an image in memory, changes nothing.


#7

GL images will render extremely fast if you're redrawing the same one repeatedly.

For CoreGraphics, it's anybody's guess what the OS does internally when you draw one of those images!


#8

That sounds good! I made a naive try using it but i get an assertion failure creating the image in my editor constructor at juce_openglimage.cpp 189:

    OpenGLContext* currentContext = OpenGLContext::getCurrentContext();

    jassert (currentContext != nullptr); // an OpenGL image can only be created when a valid context is active!

Looking around it seems you can only using opengl in the 'render' thread, ie. in paint() function? So i have to create the image there, or what?


#9

No, just use a normal image, but use the GL rendering engine. You can see this in the juce demo if you turn on the GL engine and try the rendering demo page.


#10

Well, that was a dramatic help. Levels are now acceptable :) Thanks.