what is the correct way to handle textures for V2

@Vortico : The porting instructions say not to hold onto any off-screen images between draw calls. But it’s often highly desirable.

There is a squinky labs module (Colors) that generates a monochrome texture of “noise” and uses it to animate the UI. I used to create this in the widget constructor and free it in the widget destructor. That crashes in V2, although @robert.kock has got it to not crash.

@synthi shared a method he found works.

But what it the “right” way to do something like this?

1 Like

You can actually store NanoVG image handles across frames, but you must destroy them in Widget::onContextDestroy() and recreate them in Widget::onContextCreate(). Between these events, the window, OpenGL, and NanoVG contexts do not exist, and they are different when recreated and cannot be used with image handles of the previous context.

2 Likes

oh, cool. Is that a typo? maybe you re-create them in onContextCreate?

Yes, typo fixed!

2 Likes

Came across this researching some question I had.

API doc for loadImage() says:

Do not store this reference across screen frames, as the Window may have changed, invalidating the Image.

Does this doc contradict what @Vortico writes above saying you can use it across frames? If this is different than crossing contexts (managed by on[Create|Destroy]Context), I don’t see Frame Start/End events needed to manage resources, or a way to determine what frame you’re in, so you know when you can’t hold onto that loadImage return value.

I suspect the doc is wrong and it should say context instead of frame, and point to the context events as the hooks needed for resource management. If the recommendation is that you call LoadImage every time you need it (like I remember for fonts), then that API doc should say so.

As it happens for one of my usages, I can’t use LoadImage because I need access to the image pixel data, and I don’t see an API to get that via an image handle, so I have use stb directly to load the image and do my own caching of the nvg image handle. Now that I just learned about the context events, I can throw away half of the cache management I just wrote because I didn’t find the context events when I was looking for them :-).

Ok, based on this thread telling me about these events, I tried implementing onContextDestroy and onContextCreate and immeditley discovered a Rack 2.3 bug where the NVGcontext in the event is uninitialized, so that you crash if you try to use it. Just emailed support about the bug (with the fix).

Fix seems to work well with a few minutes of casual testing. However I realized, these events aren’t sufficient to manage caching an image handle. You don’t get these events when your widget is destroyed, and I’m not sure there’s a good place to call nvgDeleteImage() when you have a valid NVGcontext to use when your widget is being destroyed, unless you’re keeping your own copy, which seems a little dangerous, but you can use the context destroy event to clear it after you’ve used it the one last time it’s possible to do so). A quick check shows we might get away with simply using APP->window->vg to destroy the image (checking for non-null window and vg, of course), but reaching into Window’s members doesn’t really seem right.

Which Andrew has either already fixed before I reported it, or fixed it on seeing the mail.

Thanks!

Now I need to figure out how to properly delete the cached image in all the scenarios that happen where onDestroyContext isn’t called.