Index: [thread] [date] [subject] [author]
  From: Andrew Apted <ajapted@netspace.net.au>
  To  : ggi-develop@eskimo.com
  Date: Wed, 5 Aug 1998 14:39:26 +1000

Re: ggiGetPixelFormat and proposed new DirectBuffer scheme

Marcus writes:

>  I've been hacking some headers and here's what I propose:
>  
>  /* Pixelformat for ggiGet/Put buffers etc. */
>  typedef struct {
>  	int		bits;		/* Number of significant bits */
>  	int		size;		/* Physical size in bits */
>  
>  	ggi_pixel	red_mask;	/* Bitmask of red bits */
>  	ggi_pixel	green_mask;	/* Bitmask of green bits */
>  	ggi_pixel	blue_mask;	/* Bitmask of blue bits */
>  	ggi_pixel	alpha_mask;	/* Bitmask of alphachannel bits */
>  
>  	ggi_pixel	clut_mask;	/* Bitmask of bits for the clut */
>  	ggi_pixel	fg_mask;	/* Bitmask of foreground color */
>  	ggi_pixel	bg_mask;	/* Bitmask of background color */
>  	ggi_pixel	texture_mask;	/* Bitmask of the texture (for
>  					   textmodes - the actual character) */
>  	uint32		flags;		/* Pixelformat flags */
>  } ggi_pixelformat;
>
>  /* Pixelformat flags */
>  #define GGI_PF_REVERSE_ENDIAN	0x01
>  #define GGI_PF_HIGHBIT_LEFT	0x02
>  #define GGI_PF_HIGHBIT_RIGHT	0x04

Nice.

First question, how does GGI_PF_REVERSE_ENDIAN relate to the masks ?
Does it mean that masks don't change (e.g. r5g5b5), and the program has
to byte swap *after* encoding a pixel using the masks ?

Second question, what about 1..7 bit modes ?  For example, on a 1 bit
mode the above should have clut_mask == 0x01.  I think that's OK, but it
does imply that ggiGetXXX/ggiPutXXX don't take packed data (e.g. 8
pixels packed in each byte) but *unpacked* data (one pixel per byte).

I prefer the unpacked case, it is so much easier to program for, since
you don't have to worry about packing the data (with LSBit vs MSBit).
The disadvantage is ggiPutXXX can't resort to memcpy _when the data is
aligned_.  I'm not worried about this, applications can always access
the framebuffer directly to get a speed boost.  

(I guess that 1 bit modes under X would be slower too -- but IMHO the
nicer interface for all depths < 8 is more important than the speed of
1 bit modes).

Also, I've got a bad feeling that 2 cases (MSBit vs LSBit) won't be
enough to cover all the 1/2/4 bit modes.  There is probably hardware
with crap like "75316420" arrangements (Atari ? EGA ? C64 ? :)

>  The ggi_info struct and ggiGetInfo() will be removed completely.
>  The information in it is now supplied by the old functions:
>  ggiDBGetBuffer(), ggiGetMode() and ggiGetFlags()
>  and the new functions:
>  const ggi_pixelformat *ggiGetPixelFormat(ggi_visual_t vis);
>  int                    ggiGetSelectFD(ggi_visual_t vis);

Good.

>  /***************************************************************
>   * DirectBuffer
>   ***************************************************************/
>  
>  typedef enum {
>  	blPixelLinearBuffer,
>  	blExtended,
>  
>  	blLastBufferLayout
>  } ggi_bufferlayout;

We're going to need blBitPlanarBuffer and blInterleavedPlanarBuffer soon
(when running LibGGI on linux/m68k).  Just something to keep in mind.

>  typedef struct {
>  	int		stride;		/* bytes per row		*/
>  	ggi_pixelformat *pixelformat;	/* format of the pixels		*/
>  } ggi_pixellinearbuffer;
>
>  /* Buffer types */
>  #define GGI_DB_NORMAL		0x01
>  #define GGI_DB_EXTENDED		0x02
>  #define GGI_DB_MULTI_LEFT	0x04
>  #define GGI_DB_MULTI_RIGHT	0x08

Something else is needed here:

   #define GGI_DB_PRIVATE       0x10

This is for direct buffers that remain internal to LibGGI, such as the
emulation targets (trueemu, tile, ...) where the buffers are not
"Direct" and shouldn't be given to applications.  ggiGetNumBuffers()
should not count these, and ggiGetDBGetBuffer() should skip over them.

>  typedef struct {
>  	int		frame;		/* framenumber */
>  	uint32		type;		/* buffer type */
>   
>  	/*	access info	*/
>  	void		*read;		/* buffer address for reads	*/
>  	void		*write;		/* buffer address for writes	*/
>  	unsigned int	access;		/* supported access widths	*/
>  	unsigned int	align;		/* alignment requirements	*/
>  	unsigned int	page_size;	/* zero for true linear buffers	*/
>  
>  	ggi_bufferlayout	layout;
>  
>  	/* The actual buffer info. Depends on layout. */
>  	union {
>  		ggi_pixellinearbuffer plb;
>  		void *extended;
>  	} buffer;
>  } ggi_directbuffer;

Possible addition:

        int       non_standard;       /* non standard framebuffer types */

which would normally be 0, but would take on special values if the
framebuffer was partically strange, e.g. :

    #define GGI_DB_NONSTD_VGA_MODEX
    #define GGI_DB_NONSTD_VGA_MODEY
    #define GGI_DB_NONSTD_HAM6
    #define GGI_DB_NONSTD_HAM8

(though maybe this could be handled by the extension mechanism)

>  The frame entry is the framenumber (when double/tripplebuffering)
>  The type entry contains one or more GGI_DB_* flags.
>  This allows for things like doublebuffering on a pair of
>  VR-goggles (in which case ggiDBGetNumBuffers() would return 4
>  and we'd have two GGI_DB_MULTI_LEFT and two GGI_DB_MULTI_RIGHT
>  buffers)

Right.

>  ggiDBGetSimplePLB() will return a buffer with the following
>  properties:
>  frame=1
>  type=GGI_DB_NORMAL
>  read=write
>  access=all widths supported by the host CPU
>  align=any supported by the host CPU
>  layout=blPixelLinearBuffer

This one I'm not sure about -- how does it relate to the frames ?  
It looks like you don't get it whenever frames > 1.

I would suggest just having an extra flag in the DB types :

    #define GGI_DB_SIMPLE   0x20

which means exactly what you said, read=write, access=all, align=any,
layout=plb.  This would save us the extra function call and the extra
structure.

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

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