Using Bitmap.draw in a thread

Hi.

So, I have the habit to draw my tilesheets are runtime, to make them perfect for the resolution available.
It can be tricky at some times, but I am always satisfied by the pixel perfect result.

And it’s okay when you only have to run it once, store the texture on the device, and move along.
But with multi windows systems on Android and iOS becoming a thins, and the porting of android apps to Chrome and other devices, the size of the app can change, sometimes while playing.

So rather than blocking the thread for 2/3 seconds, I would rather do it on a secondary thread.

And it works fine, as long as you only work with bitmaps, you can pass them without any issue frome the main thread to another.
But trying to use Bitmap.draw, with a vectorial shape as the item to draw, fails.
I tried creating a sprite or passing is as parameter, and it fails both times.
The sprite to draw and the bitmapData both just fill in black.

Here is the test class file I used:
http://pastebin.com/zAGC6pyr

I simply call it like that from the main class constructor:

var stamp:Sprite;
stamp = new Sprite();
stamp.x = 20;
stamp.y = 20;
addChild( stamp );

var sprite:Sprite;
sprite = new Sprite();
sprite.x = 40;
sprite.y = 20;
addChild( sprite );

var cacher:Cacher = new Cacher( sprite.graphics, stamp, 256, 256, 10 );

And as I said, if I choose ( at line 138 ) to just draw in the bitmapData using fill rect, I see that everything works fine.
I can draw to a sprite added to the main view, it will display fine, and when I get the shared bitmapData back, it displays fine.

But if I choose to draw the sprite to the bitmap, both become black:

What is weird is that the sprite becomes black even before BitmapData.draw is called ( I checked by putting a 2 seconds sleep on the thread ).

So, I have no clue what more I can try.
Ok, I know. This is a specific usecase.
Definitely not a priority.
But is there a way to make it work, by initializing something in the new thread or something, that would be great.

Using bitmapData.draw might use the OpenGL renderer, which will not work in a thread, since (unless I’m mistaken) OpenGL is single-threaded

However, a software-based bitmapData.draw, depending on design, might work? It’s unsafe depending on whether you manipulate the objects that are drawing from the main thread, but there’s a chance it could work. I need to implement Cairo bitmapData.draw support, I wonder if that would work threaded

Well, I tried using a sprite on the main thread because using a sprite in the new thread doesn’t work either.
But of course that would raise some issues.
I am more looking to setup a proper environment for drawing everything in the second thread.

If it is a new thread, is it not possible to setup a whole new OpenGl context rather than depending on the main one?
Have I any chance to make things work if I try to reproduce what is in ApplicationMain.create() ?

Actually, take a look at this:

This would not work with legacy, but theoretically, things could progress down this road of being able to boot up a Stage from scratch. There probably are static variables that might not jive right now with two stages, but in principle, I want to see things moving in this direction where we can boot up / shutdown things at will

Well, I surely wish for it.
But that’s over my head to get it to work myself.
I guess I’ll check back in a few months, and meanwhile work on my own rendered ( the vector shapes I want to draw on the bitmap are rather simple ).

“OpenGL is single-threaded” is not accurate explanation.
You just cannot make the same context current at the same time from multiple threads.

Instead of using the same OpenGL context from multiple threads, you can create context for each thread and share its resources. On SDL, you can do that with SDL_GL_SHARE_WITH_CURRENT_CONTEXT.

Hey, a bit of feedback on that.
Yes, it is now possible to draw on a second thread using the drawing API.
In my project, I open a thread, and build some pixel perfect tilesheets using some assets I load and the drawing API.

It works while targeting Windows and Neko, ( using respectivly neko.vm.thread and cpp.vm.thread ).
This should work with Android too but I haven’t had time to try.

I might try to add threading with Flash using workers, and also maybe Html5. But I mostly needed it for mobile, were less power is available.
Plus those two targets are more complicated ( you need to run separate swf and js files ).

maybe 1 Worker-Thread that manage queued Jobs for sequentially openGl-drawing…
but most time-consuming is in filling gpu-ram
(if many threads using same gl-context, may they are waiting for each other ;)?)