www.delorie.com/archives/browse.cgi   search  
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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019