Fun with Procedural Images: Mouse Support part 1

In the last update, I fixed up the input support, so now I can read the mouse location within a window.  Here are the results.

Cursor location in window: 38 pixels right, 46 down.

Cursor location in window: 38 pixels right, 46 down.

Of course, that doesn’t mean everything’s golden.

Reported cursor location: 79x59.  Actual cursor location: 341x215

Reported cursor location: 79×59. Actual cursor location: 341×215

SDL can only report mouse locations inside of its own context.  If, say, I initialized the window to 80 pixels by 60 pixels so I could test things quickly and in an area small enough that you don’t have to click on the images to see what’s going on, and then resize the window so it’s bigger, then everything outside that 80×60 box in the upper left corner is outside the SDL context, and I get bad information.  Obviously, what I need to do is resize the SDL context.

This presents its own problems.

Most boring game ever!

Most boring game ever!

What happened here!?

Well, as Shamus Young explained quite thoroughly on his own blog, when the SDL context is rebuilt, it flushes EVERYTHING else from video memory.  Suddenly there aren’t any polygons to draw anymore.

Fortunately, the way to fix this is to inform OpenGL that I have a bunch of new vertexes for it.  This actually happens a lot during normal program operation, so all I have to do is tell the program that ALL of the vertexes need updating.

Well, it's something.

Well, it’s something.

As you probably just guessed, resetting the SDL context kills all of the textures, too.  This is not as easy a problem to fix as vertexes, because textures don’t get updated the same way that vertexes do.  For one thing, they’re typically a lot bigger than a set of vertexes.  Most of my test textures are 128×128 pixels.  That’s at least 64 kilobytes for each texture.  By comparison, the ENTIRE map takes about 32 kilobytes, if that, and even that is rarely updated.

I’ve got two options here.  Option number one: when a resize is triggered, I can tell the texture library to go through each texture and read the file back off the disk.  This has its limits.  For one, it ONLY works with image textures.  Procedural textures take longer to load than images do, and there are several avenues for them to get created, meaning there isn’t always a file I can load them back up from.

This leaves option number two: read all of the textures out of the video card into local memory, reinitialize the SDL context, and then pump them back in.  This might actually be even slower than option one, because now I’m doubling the amount of data sent back or forth between system memory and the video card, but it means that it doesn’t matter what changes have been made to textures since they were loaded, I’m guaranteed to get back what I put into it.

So I do that.

Something's off...

Something’s off…

Here’s a hint: this is what the window looked like immediately before resize:

I don't remember where I got the character sprites from, but thank-you, whoever created them.  They've been immensely helpful for testing.

I don’t remember where I got the character sprites from, but thank-you, whoever created them. They’ve been immensely helpful for testing.

Something is overwriting my textures, seemingly at random.  It seems to come and go depending on which textures I load up, and while it seems random which textures are corrupted and which ones are left alone, it’s also consistent.

I did some digging around in the backup and restore functions, and finally hit on the idea of printing out a list of the texture names with their corresponding indexes(a number which OpenGL uses to refer to them in-system) before and after a reload, to see how they’re behaving.

Left: before, Right: after

Left: before, Right: after

Orange highlighting means the line has changed in some way, while white means that they’re the same.  In this case, I expect the lines to change.  The texture is getting assigned to a new index, after all.  The old one was blown away in the reset.

See the 4th entry?  tilegrid-test-0.png is the name of the file used to hold the textures for all of the map objects.  You’ll note in the above pictures that it didn’t get corrupted.  Why is that?

Well, what’s happening is that it just happens to be the first texture loaded into the system, giving it an index of 1.  After the reset, all of these indexes are now invalid, but the Texture Library still remembers them.  It goes through and starts re-loading textures, only this time(because of how the textures are stored), it starts with clouds_32, which now gets an index of 1.  sprites2 had an index that was different from the one clouds_32 got assigned, so it got overwritten.  Same for sprites6.  Then we get back to tilegrid-test-0.png, and… hey, it has index #1.

The first thing done when reinitializing these textures is that the old texture is cleared, freeing up the index.  Yep, the new clouds_32 got blown away while trying to put tilegrid-test-0.png back together.

I fix this by skipping the step in the reload where the old texture is cleared out, and now the printout looks like this:

Note that everything has changed.

Note that everything has changed.

And now I’m not getting any texture corruption.  Yay!

Next time, I’ll go over how I actually read mouse inputs with respect to locations in-program.



Leave a Reply. Wheaton's Rule in full effect.

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s