Index: [thread] [date] [subject] [author]
  From: Andrew Apted <ajapted@netspace.net.au>
  To  : ggi-develop@eskimo.com
  Date: Mon, 10 Aug 1998 15:22:37 +1000

Re: LibGGI & 24/32 bit modes

Marcus writes:

>  > 1) 32 bit modes -- the set of masks describe the layout perfectly,
>  >    without any funniness like you get with reverse-endian 16 bit modes,
>  >    so shouldn't we avoid using the GGI_PF_REVERSE_ENDIAN flag here ?
>  
>  Sure, every mode should be described in the most simple way that still
>  is correct.

Yep.

>  > 2) 24 bit modes have to be read / written 1 byte at a time, but in
>  >    what order ?  There are two possibilities:
>  > 
>  >       buf[0] = (ggi_pixel & 0xff0000) >> 16;
>  >       buf[1] = (ggi_pixel & 0xff00) >> 8;
>  >       buf[2] = (ggi_pixel & 0xff)
>  > 
>  >       versus
>  > 
>  >       buf[0] = (ggi_pixel & 0xff)
>  >       buf[1] = (ggi_pixel & 0xff00) >> 8;
>  >       buf[2] = (ggi_pixel & 0xff0000) >> 16;
>  >
>  >    We should pick one and stick to it.  I think the second version looks
>  >    easier to optimize (e.g. *buf++ = (uint8) pix; pix >>= 8).
>  
>  Well, that will depend on the endianness.
>  When reading/writing multiple pixels at a time we should put 4 bytes
>  at a time (8 an 64-bit machines), and the order we put the bytes in
>  when writing a single pixel must be the same as it is when putting
>  multiple ones.

No, writing multible pixels at a time is CPU-endianness dependent.  For
example when writing 16 bit pixels to a put-buffer, they still have to
end up in 0,1,2,3 order, so if the app wants to write 4 of these at once
then that is an optimization which has nothing to do with the
pixel-endianness.

Now, a single 24 bit pixel is something that cannot be read/written at
once as a whole (unlike 8/16/32 bit pixels), so it must be read/written
as three bytes.  These three bytes have an order in the put-buffer, and
the burning question remains: how do these three bytes correspond to a
ggi_pixel value ?

For example, here is a piece of code I wrote which converts a line of 8
bit pixels to arbitrary sized pixels (where lookup[] contains the results 
of ggiMapColor) :

    ggi_pixel lookup[256];
    
    uint8 trans_buffer[8192];
    
    void win_translate_hline(int x, int y, int w, uchar *data)
    {
        int ww = w;
    
        uint8  *buf1 = (uint8  *) trans_buffer;
        uint16 *buf2 = (uint16 *) trans_buffer;
        uint32 *buf4 = (uint32 *) trans_buffer;
    
        switch ((graphtype & GT_ACCESS_MASK) >> GT_ACCESS_SHIFT)
    
        case 8:
            for (; ww > 0; ww--) {
                *buf1++ = lookup[*data++];
            }
            break;
    
        case 16:
            for (; ww > 0; ww--) {
                *buf2++ = lookup[*data++];
            }
            break;
    
-->     case 24:
-->         for (; ww > 0; ww--) {
-->             ggi_pixel pix = lookup[*data++];
--> 
-->             *buf1++ = pix; pix >>= 8;
-->             *buf1++ = pix; pix >>= 8;
-->             *buf1++ = pix;
-->         }
-->         break;
    
        case 32:
            for (; ww > 0; ww--) {
                *buf4++ = lookup[*data++];
            }
            break;
        }
        
        ggiPutHLine(vis, x, y, w, trans_buffer);
    }

That assumes that for 24 bit modes, the LSB of a ggi_pixel value is
stored as the first byte of each group of three.  Should we make this
the official behaviour ?

Cheers,
_____________________________________________  ____
                                               \  /
  Andrew Apted   <andrew@ggi-project.org>       \/
  

Index: [thread] [date] [subject] [author]