Dependent on the visual and runtime environment found, applications may be granted direct access to hardware and/or library internal buffers. This may significantly enhance performance for certain pixel oriented applications or libraries.
The DirectBuffer is a mechanism in which a LibGGI program can use to determine all the characteristics of these buffers (typically the framebuffer), including the method of addressing, the stride, alignment requirements, and endianness.
However, use not conforming to this specification will have undefined effects and may cause data loss or corruption, program malfunction or abnormal program termination. So you don't really want to do this.
Only the framebuffer is defined currently.
A frame buffer may be organized as several distinct buffers. Each buffer may have a different layout. This means both the addressing scheme to be used as well as the addressing parameters may differ from buffer to buffer.
A framebuffer is denoted by ggi_directbuffer.type==GGI_DB_NORMAL. Each frame has its own buffer, and its number is indicated in ggi_directbuffer.frame.
LibGGI currently has support for pixel-linear buffers, bit-planar buffers, and interleaved planar buffers.
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, x must be less than size_x and y must be less than size_y. 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.
Please refer to ggi_directbuffer(9ggi) for the description of DirectBuffer structures.
Read and write access to the buffer is done using load and store instructions of the host CPU. The access and and align members of ggi_directbuffer structure specify additional restrictions.
Read operations should be performed using the read buffer and write operations should be performed using the write buffer. These might be the same, but need not. If they are, read/write may be done to either buffer. Please note, that either read or write may be NULL. These are write-only or read-only buffers, which might be caused by hardware limitations. Such buffers are not suited to do Read-Modify-Write operations, so take care.
More importantly, certain DirectBuffers need to be explicitly acquired (i.e. locked) before using them (i.e. accessing their pointers). Such a situation may arise if the underlying visual supports mixed acceleration and framebuffer access, but they cannot occur at the same time. In that case, LibGGI needs to be informed when the application is using the framebuffer. An acquire is done by using ggiResourceAcquire and it is released by calling ggiResourceRelease.
You can determine whether the DirectBuffer needs to be acquired by using ggiResourceMustAcquire.
Be aware that the read, write and stride fields of the DirectBuffer may be changed by an acquire, and that they may be NULL or invalid when the DirectBuffer is not acquired.
Paged buffers are indicated with page_size != 0 in ggi_directbuffer.
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.