Mail Archives: djgpp/1998/03/10/04:38:18
Message-ID: | <D1FB30BBA491D1118E6D006097BCAE3913624A@Probe-nt-2a.Probe.co.uk>
|
From: | Shawn Hargreaves <ShawnH AT Probe DOT co DOT uk>
|
To: | djgpp AT delorie DOT com
|
Subject: | Re: Accessing BITMAPs Directly in Allegro
|
Date: | Tue, 10 Mar 1998 09:37:43 -0000
|
MIME-Version: | 1.0
|
Colin Walsh writes:
> I'm currently trying to eke out as much speed as possible from my 3D
> engine, and I figure that the _putpixel/_getpixel routines (even
> for asm) should be slower that directly accessing the bytes in the
> BITMAP.
If you look in allegro.h, you will see that the _putpixel() function
is implemented as:
void _putpixel(BITMAP *bmp, int x, int y, unsigned char color)
{
asm (
" movw %w0, %%fs ; "
" .byte 0x64 ; "
" movb %b3, (%1, %2) "
:
: "rm" (bmp->seg),
"r" (bmp_write_line(bmp, y)),
"r" (x),
"qi" (color)
);
}
This is essentially a _farpokeb() call where the destination address
is provided by the bmp_write_line() bank switch routine, and is just
about the most efficient generic way to do this, but there are a few
optimisations that may help in specific situations:
- don't bother reloading %fs for each pixel. If you know that you
will be drawing onto a memory bitmap you can leave it out altogether
and get rid of the ".byte 0x64" selector override, while if you are
drawing onto the screen you can just call _farsetsel() once at the
start of your drawing loop rather than once per pixel.
- if you know that you are drawing onto a memory bitmap or linear
framebuffer SVGA screen, get rid of the bmp_write_line() call and
lookup the value of bmp->line[y] directly instead. If you might
be drawing onto a banked SVGA screen, you can still improve things
by only calling the bank switcher once at the start of each scanline
rather than once per pixel.
> So I was wondering if there is a method of directly accessing the
> bitmap, and if so, how?
There are many possible ways, and the best one will depend on the
exact situation. See the "direct access to video memory" section of
the documentation.
Vic replied:
> You can say bitmap->line[y][x]=color; or color=bitmap->line[y][x]
where
> y is the Y and x is the X (yes they are reversed!). But this is just
> 8 bit modes. I'm afraid for highcolor you need the putpixel routine.
That isn't entirely true: you need some casts to convert your pointers
to the correct types, but you can still access the memory directly (see
allegro.txt somewhere around line 2488). For example the 16 bit version
would be:
((short *)bitmap->line[y])[x] = color;
For 32 bits:
((long *)bitmap->line[y])[x] = color;
For 24 bits (this one is nasty :-) you could either use:
bitmap->line[y][x*3] = color&0xFF;
bitmap->line[y][x*3+1] = (color>>8)&0xFF;
bitmap->line[y][x*3+2] = (color>>16)&0xFF;
or perhaps:
((short *)(bitmap->line[y]+x*3)) = color&0xFFFF;
bitmap->line[y][x*3+2] = (color>>16)&0xFF;
I hope I got those the right way around: be warned that this code is
untested :-)
Shawn Hargreaves.
- Raw text -