QNX-Screen官方文档理解(Buffers)

简介

Screen中的buffers可以分为internal buffers与external buffers

internal buffers

internal buffers可以通过Screen API来申请

screen_create_pixmap_buffer()
screen_create_window_buffer()
screen_create_stream_buffer()

如果SCREEN_USAGE_READ或SCREEN_USAGE_WRITE不足以满足预期的缓冲区使用要求,可以在创建缓冲区之前在Screen API对象上设置SCREEN_PROPERTY_USAGE。否则,只需通过调用适当的函数为Screen API对象创建缓冲区。例如,为窗口创建缓冲区:

...
screen_context_t ctx;                      
screen_window_t win;
int num_bufs = 2;
...
screen_create_window(&win, ctx);
screen_create_window_buffers(win, num_bufs);
...

要使用与Screen API对象关联的缓冲区,必须从对象中检索它。以下是你可以检索有效使用的缓冲区的方法(例如,用于比特或渲染目的):
pixmap

...
screen_context context;
screen_pixmap_t screen_pix = NULL;
screen_buffer_t pix_buf;
uint32_t *pix_ptr;
...
screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_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});
...
        

stream

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

window

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

external buffers

external buffers通过

screen_create_buffer()

来实现需要注意的是:只有在将外部缓冲区附加到像素图、窗口或流中的一个之后,你才能使用(例如渲染到)外部缓冲区。

由于内存位置或缓冲区大小的要求,驱动程序等应用程序可能需要分配自己的缓冲区。这些应用程序必须确保在分配缓冲区时满足所有的使用约束,以使Screen能够成功地附加缓冲区。未能满足使用约束还可能导致工件和系统不稳定。
创建自己的缓冲区并分配内存的应用程序必须:
1 通过调用screen_create_buffer()创建类型为screen_buffer_t的缓冲区。例如:

...
screen_buffer_t created_buf = NULL;
...
screen_create_buffer(&created_buf);
...

2 设置缓冲区属性。至少应用程序分配的缓冲区设置以下属性:

	SCREEN_PROPERTY_FORMAT 
	SCREEN_PROPERTY_BUFFER_SIZE
	SCREEN_PROPERTY_SIZE
	SCREEN_PROPERTY_STRIDE

如果你正在使用一种平面YUV格式,那么你还应该设置screen_property_planar_offset属性。
例如,对于格式为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});
...

3 为缓冲区分配内存并分配对它的访问权。
您可以使用SCREEN_PROPERTY_POINTER属性或SCREEN_PROPERTY_FD属性来分配内存。然而,注意你可能需要在内存上设置不同的属性,这取决于你使用的属性:
SCREEN_PROPERTY_POINTER
a 为缓冲区分配内存。
为缓冲区分配一些内存。如何以及从哪里分配内存取决于应用程序;它可以静态分配(从固定地址映射),也可以从共享内存对象分配。例如:

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

b 将指针分配给缓冲区。
您必须将SCREEN_PROPERTY_POINTER属性设置为指向已分配给该缓冲区的内存。例如:

...
screen_set_buffer_property_pv(created_buf, SCREEN_PROPERTY_POINTER, (void**)&mmap_ptr);
...

SCREEN_PROPERTY_FD
a 为缓冲区分配内存。
如何以及从哪里分配内存取决于应用程序;它可以静态分配(从固定地址映射),也可以从共享内存对象分配。例如:

...
int fd;
...
fd = shm_open(SHM_ANON, O_CREAT|O_EXCL|O_RDWR, 0400);
...

/* Seal the memory so it can't be modified */
if (0 != shm_ctl(shm_fd, SHMCTL_SEAL, 0, 0)){
		/* error */
		...
	}
...

当你使用SCREEN_PROPERTY_FD属性来指示内存时,你必须确保你:
调用shm_ctl()来设置SHMCTL_SEAL标志,以防止共享内存对象被修改。
确保在共享内存对象上没有设置shmctl_revoke标志。您可以使用SHMCTL_GET_FLAGS标志调用shm_ctl()来验证您正在使用的对象上设置了哪些标志。如果设置了shmctl_revoke标志,则不能将该对象与缓冲区关联。
b将文件描述符分配给缓冲区。
您必须将SCREEN_PROPERTY_FD属性设置为指向已分配给该缓冲区的内存。例如:

...
screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_FD, &fd);
...

4 在使用外部缓冲区之前,将其附加到像素图、窗口或流。看到“附加缓冲区(Attaching buffers)”。
您必须使用特权Screen上下文,它的类型中包含SCREEN_BUFFER_PROVIDER_CONTEXT来附加缓冲区。例如

...
screen_context_t screen_ctx;
...
screen_create_context(&screen_ctx, (SCREEN_APPLICATION_CONTEXT | SCREEN_BUFFER_PROVIDER_CONTEXT));
...

Attaching buffers
你可以附加一个缓冲区(类型为screen_buffer_t),通过分别调用以下函数将其与像素图、流或窗口关联起来:

screen_attach_pixmap_buffer()
screen_attach_stream_buffers()
screen_attach_window_buffers()

1 获取screen_buffer_t。
要访问缓冲区,你可以检索以下任何一个:
外部缓冲区(即调用screen_create_buffer()创建的缓冲区,并为其分配了内存)
通过调用screen_acquire_buffer()函数从流中获取缓冲区。例如:

screen_stream_t astream = NULL;
screen_buffer_t buffer = NULL;
...
screen_acquire_buffer(&buffer, astream, NULL, NULL, NULL, SCREEN_ACQUIRE_DONT_BLOCK);
...

通过调用带有返回缓冲区的有效属性的screen_get_*_property_pv()函数,从像素图、流或窗口获得缓冲区

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

2 设置Screen API对象(例如,pixmap,流,或窗口)上的SCREEN_PROPERTY_USAGE,你要把缓冲区附加到它上面。
在附加缓冲区之前,您应该从pixmap、流或窗口中指出缓冲区的预期使用情况,因为如果使用情况没有适当设置,Screen可能会阻止对缓冲区的访问。

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

3 通过调用适当的Screen API函数,将缓冲区附加到有效的Screen API对象上。
例如:

...
screen_attach_window_buffers(a_win, num_bufs, win_buf);
...

你可能感兴趣的:(QNX,java,算法,c++)