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

本文介绍了Screen API中的内部和外部缓冲区管理方法,包括创建、设置属性、分配内存、附加到像素图、窗口或流等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

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 中 `screen/screen.h` 头文件相关文档及用途 在 QNX Neutrino RTOS 中,`screen/screen.h` 是与图形界面开发密切相关的一个头文件,主要用于访问和管理屏幕资源。QNX 提供了名为 **Screen Graphics Subsystem**(SGX 或 Screen)的图形子系统,用于支持嵌入式设备上的 2D 和 3D 图形渲染、窗口管理、输入事件处理等功能。该系统通过一组 C API 提供服务,`screen/screen.h` 是其核心头文件之一。 使用 `screen/screen.h` 可以完成诸如创建上下文(context)、建立窗口(window)、设置显示属性、绑定渲染目标等操作。开发者可以通过该接口与底层 GPU 驱动进行交互,适用于基于 QNX 的车载信息娱乐系统、工业控制界面等嵌入式应用场景。 以下是一个典型的初始化流程示例: ```c #include <screen/screen.h> screen_context_t context; screen_window_t window; screen_buffer_t buffer; // 创建上下文 screen_create_context(&context, SCREEN_APPLICATION_CONTEXT); // 创建窗口 screen_create_window(&window, context); // 设置窗口属性 int size[2] = {800, 600}; screen_set_window_property_iv(window, SCREEN_PROPERTY_SIZE, size); // 创建缓冲区并附加到窗口 screen_create_window_buffers(window, 1); screen_get_window_property_pv(window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)&buffer); // 设置当前渲染目标 screen_set_target_window(context, window, buffer); ``` 上述代码展示了如何利用 `screen/screen.h` 提供的 API 初始化一个图形窗口,并为其分配缓冲区和设置渲染目标[^1]。这些步骤通常出现在应用程序的初始化阶段,为后续媒体资源加载和图形绘制做准备。 此外,`screen/screen.h` 还支持多种图像格式转换、纹理映射、多层合成以及输入事件监听功能,例如触摸屏或鼠标事件的捕获。它与 EGL 和 OpenGL ES 等标准图形 API 兼容,允许开发者构建高性能的嵌入式图形应用。 需要注意的是,QNX Screen 子系统的文档主要由 **QNX Software Development Platform (SDP)** 提供,开发者可以通过官方文档查阅完整的 API 参考手册和编程指南。此外,QNX 提供了多个示例项目,如 `screen_graphics2d` 和 `screen_gles20`,可用于学习具体的图形编程技巧。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值