Use a custom field in the SDL IO to avoid the global surface

This also introduced a change in io_free, so it first cleans up the
custom pointer. If you have to clean up anything in the custom pointer,
do that in io_teardown.