#include <ggi/ggi.h> typedef struct { uint32_t type; int frame; ggi_resource_t resource; void *read; void *write; unsigned int page_size; uint32_t noaccess; uint32_t align; ggi_bufferlayout layout; union { ggi_pixellinearbuffer plb; ggi_pixelplanarbuffer plan; ggi_samplelinearbuffer slb; ggi_sampleplanarbuffer splan; void *extended; } buffer; } ggi_directbuffer;
/* Buffer types */ #define GGI_DB_NORMAL 0x0001 /* "frame" is valid when set */ #define GGI_DB_EXTENDED 0x0002 #define GGI_DB_MULTI_LEFT 0x0004 #define GGI_DB_MULTI_RIGHT 0x0008 /* Flags that may be or'ed with the buffer type */ #define GGI_DB_SIMPLE_PLB 0x01000000 /* GGI_DB_SIMPLE_PLB means that the buffer has the following properties: type == GGI_DB_NORMAL read == write noaccess == 0 align == 0 layout == blPixelLinearBuffer */
You can determine whether the DirectBuffer needs to be acquired by using ggiResourceMustAcquire(3). An acquire is done by using ggiResourceAcquire(3) and it is released by calling ggiResourceRelease(3).
Be aware that these fields may be changed by an acquire, and that they may be NULL or invalid when the DirectBuffer is not acquired.
Successive access to addresses addr0 and addr1 of either read or write buffers with addr0/page_size != addr1/page_size may be very expensive compared to successive accesses with addr0/page_size == addr1/page_size.
On i386 the penalty will be about 1500 cycles plus 4 cycles per to be remapped. Because of this, block transfer operations might become very inefficient for paged buffers. If there are two different buffers provided for read and write operations, you should do successive reads from one and do successive writes to the other. If not, it is recommended to copy pagewise into a temporary buffer and then to copy this temporary buffer back to screen.
typedef struct { int stride; /* bytes per row */ ggi_pixelformat *pixelformat; /* format of the pixels */ } ggi_pixellinearbuffer;
A linear buffer is a region in the application's virtual memory address space. A pixel with the pixel coordinates (x, y) is assigned a pixel number according to the following formula:
pixel_number = (origin_y + y) * stride + origin_x + x;
In any case both x and y must not be negative, and less than the buffer's width and height respectively. For top-left-origin screen coordinates, stride and origin_y will both be positive. For bottom-left-origin screen coordinates, stride and origin_y will both be negative. This will result in the correct pixel number with the same formula in both cases. The pixel number will be used to address the pixel.
A certain number of bits is stored per pixel, and this is indicated in the ggi_pixelformat.access field. For some visuals, the buffer might not be in host CPU native format and swapping operations need to be performed before writes or after reads.
typedef struct { int next_line; /* bytes until next line */ int next_plane; /* bytes until next plane */ ggi_pixelformat *pixelformat; /* format of the pixels */ } ggi_pixelplanarbuffer;
typedef struct { int num_pixels; /* how many pixelformats */ int stride; /* bytes per row */ ggi_pixelformat *pixelformat[4];/* format of the pixels */ } ggi_samplelinearbuffer;
typedef struct { int next_line[3]; /* bytes until next line */ int next_plane[3]; /* bytes until next plane */ ggi_pixelformat *pixelformat[4];/* format of the pixels */ } ggi_sampleplanarbuffer;