Index: [thread] [date] [subject] [author]
  From: Marcus Sundberg <e94_msu@e.kth.se>
  To  : ggi-develop@eskimo.com
  Date: Wed, 05 Aug 1998 12:02:36 +0200

Re: ggiGetPixelFormat and proposed new DirectBuffer scheme

Andrew Apted wrote:
> 
> 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 ?

Yes, I think this makes most sense.
Having masks like:
ggbbbbb0 rrrrrggg
would imply that gg in the left byte are the high-bits, which
is not correct. Thus we have:
rrrrrggg ggbbbbb0
and GGI_PF_REVERSE_ENDIAN tells us that we need to swap the
bytes.

Of course a smart application could spot this case and encode
the pixel directly so that no swapping is needed, but the most
common case will be that it encodes the pixel according to masks
and then does a swap.

Btw, doesn't many processors have an instruction to do byte
swapping? In that case I suggest we add some byte swapping
macros to the API, which will use inline-assembly on supported
platforms.

Also, I suggest we make GGI_PF_HIGHBIT_LEFT the default and
remove that flag. Agreed?

> 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).

3,5,6 and 7 bit modes should definitely be unpacked, because
I've never heard of any HW that supports such modes with a packed
chunky buffer. :)
For the other modes I suggest we have a GGI_PF_PACKED flag that
indicate that _aligned_ buffers uses packed format.
After all, <8 bit modes are almost only used on old hardware
where speed is always an issue.

> 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 "" arrangements (Atari ? EGA ? C64 ? :)

Well, we have 32 flags in there, so I suppose we can add
a GGI_PF_75316420 when there's actually support for any
such mode. ;)

> >  /***************************************************************
> >   * 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.

Yep. DirectBuffer should support planar modes out of the box.

For Get/Put buffers I think it makes most sense to use chunky
pixels even if the HW is planar, as it will allow applications
to run everywhere without needing to now anything about planar
modes. There should be a planar extension anyway supporting
things like Get/PutPlane, ScrollPlane and other things that
don't make sense on non-planar HW.

> >  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.

This was my originally planned changes to structs.h:

--- old/include/structs.h       Thu Jul 23 09:35:59 1998
+++ ./include/structs.h Tue Aug  4 16:40:14 1998
@@ -77,6 +77,14 @@
        void *private;
 } ggi_extlist;
 
+/* Direct Buffer stuff */
+typedef struct {
+       int                     numbufs;
+       ggi_directbuffer        **buffers;
+
+       void    *dummy[8];      /* for future expansion */
+} ggi_db_internal;
+
 /* Increment the version number every time you add 
  * new features.
  */
@@ -102,7 +110,12 @@
        struct ggi_visual_opgc      *opgc;  /* GC operations */
        void                        *opdummy[5];/* For future expansion */
 
-       struct ggi_info info;           /* Info on the mode */
+       ggi_pixelformat *pixfmt;        /* Format of the pixels */
+       ggi_db_internal *dblist;        /* List of DBs */
+       ggi_flags       flags;          /* Flags */
+       ggi_mode        *mode;          /* Current mode */
+       int             select_fd;
+
        int size;                       /* Size of all extensions */
        ggi_dlhandle_l  *extlib;        /* Dynamic libs from extensions */
 
I suggest we add:
       int                     numpriv;
       ggi_directbuffer        **privbufs;
to ggi_db_internal. That way application- and internal buffers are
completely separated.

> >  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)

Any reason why we shouldn't simply add the above four and
similiar modes to the ggi_bufferlayout enumeration ?

> >  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.

My idea was that it would return the first frame if there's more
than one. But your idea is even better, as i allows us to have
only simple buffers even when double/tripplebuffering.
 
//Marcus
-- 
-------------------------------+------------------------------------
        Marcus Sundberg        | http://www.stacken.kth.se/~mackan/
 Royal Institute of Technology |       Phone: +46 707 295404
       Stockholm, Sweden       |      E-Mail: e94_msu@e.kth.se

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