Blit

From StoneHome

This document explains the development of a simple blit routine, also called a blitter. More complex systems such as pattern blitters and alpha blitters are documented elsewhere, but rely on an understanding of the material presented here first. Blit is one of the important simple behaviors in game development and many graphics-oriented applications, such as web browsers, GUI and primitive toolkits, graphics applications, and so forth.

What's a Blitter?

Contents

Blitters are actually relatively simple tools, though their implementation often confounds novices. The definition of blitters varies a bit based on context. Originally, blitting was just a way to describe copying a bulk of data from point A to point B. However, over the years the word has tended to be used in the more specific fashion of referring specifically to copying graphics data from point A to the screen, or perhaps to a back buffer. In general, one suggests that something has been blitted if it is used to draw onto another surface in the fashion of a stamp; blitting is a common mechanism to implement sprites and tiled backgrounds on platforms where these do not exist natively, as an example. Still, because of special concerns with graphics, a blitter tends to do a bit more than just copying one stretch of data.

Okay, so what's a blitter?

Well, at its heart, a blitter is still a point to point copy. However, there are some general assumptions implied when describing a blitter.

To begin with, a blitter needs to implement spanwise copying. Blitters implement a two-dimensional copy, not a one-dimensional copy - they're not putting a stripe into a sequence, but instead a box onto another box. As a result, you can't just give a blitter a source, target and copy length, like you can with a normal copy routine. Consider a screen which is ten pixels by ten pixels, onto which you want to blit a four by four square, in the center. The source is a four by four bitmap, so it's a different size than the target. The interior square's upper left hand corner would be at (3,3), which as a 1d sequence is cell 33 (yay for examples whose size matches your counting radix.) However, that row ends at 36; you don't want to paint (3,7), so you have to leave 37 alone, and clearly a 4x4 square is more than 4 pixels long. You need to start the next row at 43 and run it to 46; then, 53..56 and 63..66. This is spanwise copying: you paint a row at a time instead of the whole thing at once, so that you can account for the empty space on either side of the blit. As such, instead of just a source, destination and length, you need to give the blitter a source, target, copy length, copy width and source width. If you want to support copying blitting just part of the source, you also need to pass the total width of the source, so you can do spanwise reading alongside spanwise copying.

Secondarily, many blitters want an implementation of transparency in some form (especially for blitters to support sprites.) This makes the copy routine itself a bit more complex; you have to make some test, generally based on the color to be painted (though there are alternate approaches,) to determine whether or not to paint each pixel. Some blitters are more complex; they allow things like alpha copying, pattern copying, masked copying, and so forth. We'll detail those elsewhere, in alpha blitter, mask blitter, pattern blitter, and so forth; this introductory example will only support boolean transparency - that is, either this pixel exists or it doesn't - and the first version won't even do that much.

Show me a blitter!

Okay, okay, settle down. Easily enough done. I'll write this example for the screen metrics of the Nintendo DS, so that it's useful for some of my other tutorials too. The DS screens are 256x192 pixels, and we'll write this tutorial for a 15-bit-color mode which is simply addressed linearly. We'll also assume an 8-bit byte, and that the 15-bit colors are stored in 16-bit space (which is typical,) meaning each pixel is two bytes storage space. Therefore, the screen's buffer is 256*192*2 bytes or 96K.

Example Situation

Retrieved from "http://sc.tri-bit.com/Blit"