A buffer is an area of memory that stores pixel data. Multiple buffers can be associated with a window or stream, but only one buffer can be associated with a pixmap.
The buffers that you can create are:
You can create buffers for pixmaps, streams, and windows by calling one of the following Screen API functions.
You may set the SCREEN_PROPERTY_USAGE on the Screen API object before you create its buffer if SCREEN_USAGE_READ or SCREEN_USAGE_WRITE is insufficient for your intended usage of the buffer. Otherwise, simply create the buffer for the Screen API object by calling the appropriate function. For example, to create buffers for a window:
... screen_context_t ctx; screen_window_t win; int num_bufs = 2; ... screen_create_window(&win, ctx); screen_create_window_buffers(win, num_bufs); ...
You can now proceed to use the buffer. See Using buffers.
Applications such as drivers may have a requirement to allocate their own buffers because of memory location, or a buffer size requirement. These applications must ensure that all usage constraints are met when allocating the buffers to enable Screen to successfully attach the buffers. Failure to meet the usage constraints may also result in artifacts and system instability.
Applications that create their own buffers and allocate their memory must:
... screen_buffer_t created_buf = NULL; ... screen_create_buffer(&created_buf); ...
At a minimum, you must set the following properties for the buffer that your application allocates:
If you're using one of the planar YUV formats, then you should also set the SCREEN_PROPERTY_PLANAR_OFFSETS property.
For example for a buffer of format SCREEN_FORMAT_NV12:
... const int width=1024, height=64, stride=4096; const int nbytes = stride*height + stride*(height/2); ... screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_FORMAT, (const int[]){ SCREEN_FORMAT_NV12 }); screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_BUFFER_SIZE, (const int[]){ width, height }); screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_SIZE, (const int[]){ nbytes }); screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_STRIDE, (const int[]){ stride }); screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_PLANAR_OFFSETS, (const int []){ 0, (height * stride), -1 }); ...
Allocate some memory for the buffer. How and from where the memory is allocated is up to the application; it can be statically allocated (mapped from a fixed address) or allocated from a shared memory object. For example:
... int fd; uint32_t *mmap_ptr; ... fd = shm_open(SHM_ANON, O_CREAT|O_EXCL|O_RDWR, 0400); shm_ctl(fd, SHMCTL_ANON, 0, nbytes); mmap_ptr = mmap(NULL, nbytes , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); ...
You must set the SCREEN_PROPERTY_POINTER property to point to the the memory that's been allocated for this buffer.
... screen_set_buffer_property_pv(created_buf, SCREEN_PROPERTY_POINTER, (void**)&mmap_ptr); ...
You must be using a privileged Screen context that includes SCREEN_BUFFER_PROVIDER_CONTEXT in its type to attach the buffer. For example:
... screen_context_t screen_ctx; ... screen_create_context(&screen_ctx, (SCREEN_APPLICATION_CONTEXT | SCREEN_BUFFER_PROVIDER_CONTEXT)); ...
You can attach a buffer (of type screen_buffer_t) to associate it with a pixmap, stream, or window by calling the following functions respectively:
To attach buffers:
To get access to a buffer, you can retrieve any of the following:
screen_stream_t astream = NULL; screen_buffer_t buffer = NULL; ... screen_acquire_buffer(&buffer, astream, NULL, NULL, NULL, SCREEN_ACQUIRE_DONT_BLOCK); ...
... screen_buffer_t *win_buf; win_buf = calloc((size_t)num_bufs, sizeof(screen_buffer_t)); ... screen_get_window_property_pv(win, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)win_buf)); ...
From the pixmap, stream, or window, you should indicate the intended usage of the buffer before you attach it because if the usage isn't set appropriately, Screen may prevent access to the buffer.
... screen_window_t a_win; ... int usage = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE; screen_set_window_property_iv(a_win, SCREEN_PROPERTY_USAGE, &usage); ...
For example:
... screen_attach_window_buffers(a_win, num_bufs, win_buf); ...
To use a buffer that's associated with a Screen API object, you must retrieve it from the object. The following are ways that you can retrieve a buffer that's valid for use (e.g., for blitting or rendering purposes):
... screen_context context; screen_buffer_t pix_buf; uint32_t *pix_ptr; ... screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_BUFFERS, (void**)&pix_buf)); screen_get_buffer_property_pv(pix_buf, SCREEN_PROPERTY_POINTER, (void**)&pix_ptr)); ... screen_fill(context, pix_buf, (const int[]){SCREEN_BLIT_COLOR, 0xabcd, SCREEN_BLIT_END}); ...
... int num_bufs = 0; screen_buffer_t *stream_buf = NULL; screen_get_stream_property_iv(stream, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &num_bufs); a_stream_buf = calloc((size_t)num_bufs, sizeof(screen_buffer_t)); ... screen_get_stream_property_pv(stream, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)stream_buf)); ... screen_post_stream(stream, stream_buf[0], 0, NULL, 0)); ...
... screen_context ctx; screen_stream_t a_stream; screen_buffer_t buffer, dest_buffer; ... screen_acquire_buffer(&buffer, a_stream, NULL, NULL, NULL, SCREEN_ACQUIRE_DONT_BLOCK); ... screen_blit(ctx, buffer, dest_buffer, (const int[]){SCREEN_BLIT_COLOR, 0xabcd, SCREEN_BLIT_END}); ...
... int num_bufs = 0; screen_buffer_t *win_buf = NULL; screen_get_window_property_iv(win, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &num_bufs); other_win_buf = calloc((size_t)num_bufs, sizeof(screen_buffer_t)); ... screen_get_window_property_pv(win, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)win_buf)); ... screen_post_window(win, win_buf[0], 0, NULL, 0)); ...