"Double Buffering" with BitmapData

There’s an interesting discussion going on on the OSFlash list about what was originally termed “double buffering”, but is more accurately “offscreen buffering”. This is when you create an instance of BitmapData, but don’t add it to the display list, and then do a whole bunch of drawing to it, and when you are done, drawing that bitmap onto another bitmap that IS on the display list. There was some discussion as to whether or not this would actually be quicker, so I did a quick test. I usually get into trouble when I do these timing tests, but I’m going to post it anyway.

Here we have three BitmapData instances. One is wrapped in a Bitmap object and put on the display list. The second is put in a Bitmap object, but not added to the display list. The third is just left alone. Then a million random pixels are drawn to each one. The results bear out not only that the off-display list version is quicker than the on-display list version, but it’s also slightly faster than the version that has the Bitmap object wrapping the Bitmap data, but not on the display list. I’m seeing on average about 13% difference between the high and low versions, which is a decent increase in speed.

[as]package {
import flash.display.Sprite;
import flash.utils.getTimer;
import flash.display.Bitmap;
import flash.display.BitmapData;

public class BlitTest extends Sprite
{
public function BlitTest()
{
var bmp1:BitmapData = new BitmapData(500, 500, true, 0);
var bmp2:BitmapData = new BitmapData(500, 500, true, 0);
var bmp3:BitmapData = new BitmapData(500, 500, true, 0);
var holder1:Bitmap = new Bitmap(bmp1);
addChild(holder1);
var holder2:Bitmap = new Bitmap(bmp2);

var start:int
var i:uint;

start = getTimer();
for(i = 0; i < 1000000; i++) { bmp1.setPixel(Math.random() * 500, Math.random() * 500, Math.random() * 0xffffff); } trace(getTimer() - start); start = getTimer(); for(i = 0; i < 1000000; i++) { bmp2.setPixel(Math.random() * 500, Math.random() * 500, Math.random() * 0xffffff); } trace(getTimer() - start); start = getTimer(); for(i = 0; i < 1000000; i++) { bmp3.setPixel(Math.random() * 500, Math.random() * 500, Math.random() * 0xffffff); } trace(getTimer() - start); } } } [/as]

This entry was posted in Flash. Bookmark the permalink.

6 Responses to "Double Buffering" with BitmapData

  1. This makes me wonder if there’s still any savings if you remove a bitmap from the display list, draw millions of pixels, and then add it again. Guess I better read that thread. (-;

  2. Guy Watson says:

    You can close that gap considerably and reduce the need to have a seperate bitmap by hiding the holder bitmap and locking the bitmapData object while you call setPixel:

    start=getTimer()
    bmp1.lock()
    holder1.visible=false
    for(i=0;i

  3. kp says:

    thanks guy. that rocks.

  4. Dru says:

    Hey, Guy, could you possibly repost that comment? The “<” in the for must have gotten interpreted as an HTML tag and truncated the code listing.

  5. kp says:

    Code got cut off in the database too. But I think you just need lock the bitmap and set it invisible before drawing, and unlock and set it visible afterwards.

  6. kp says:

    I did some more tests, covering just about all bases. I don’t really see that the visible makes much of a difference at all. But lock/unlock brings all tests down to the same level.

    initial tests
    ————-
    in bitmap on display list:
    812
    in bitmap, not on display list:
    809
    not in bitmap:
    684

    round 2, using lock and unlock
    in bitmap on display list:
    680
    in bitmap, not on display list:
    687
    not in bitmap:
    684

    round 3, using lock and unlock, setting visible true/false where appropriate
    in bitmap on display list, bitmap invisible:
    683
    in bitmap, not on display list, bitmap invisible:
    684

    Of course, figures varied slightly in each run, but were all generally within these ranges. Since things varied by 10-15 milliseconds in each test, a difference in any two times that is less than that can be considered roughly “the same”.

    So essentially, using lock and unlock brings it all down to the same speed as using an offscreen buffer!

Leave a Reply