一,Screen应用开发简述
QNX Screen图形子系统是一个图形框架,因此,使用该框架开发的应用程序在复杂性和功能上可能会有很大差异。也就是说,大多数Screen应用程序在简化后,会执行某种渲染,以便在显示器上显示最终图像。
为了开发一个基本的QNX Screen应用程序,你需要遵循以下步骤:
- 创建Screen上下文:Screen上下文是Screen应用程序的起点,它提供了与Screen服务进行交互的接口。
- 创建渲染目标:渲染目标是应用程序绘制图像的地方。你可以创建一个窗口作为渲染目标,或者创建一个离屏的渲染目标。
- 设置渲染目标的属性:你可以设置渲染目标的各种属性,如大小、颜色格式、缓冲区数量等。
- 为渲染目标创建缓冲区:渲染目标使用缓冲区来存储图像数据。你需要为渲染目标创建一个或多个缓冲区。
- 渲染到目标:使用你的图形API(如OpenGL ES或OpenVG)在渲染目标的缓冲区上进行绘制。
- 提交图像:当你完成绘制后,你需要将渲染目标的缓冲区提交给Screen服务,以便在显示器上显示。
- 处理Screen事件:Screen应用程序通常需要响应用户输入或其他事件。你可以注册事件处理程序来处理这些事件。
二,创建Screen上下文
通过调用screen_create_context创建一个Screen上下文,例如:
...
screen_context_t screen_ctx;
screen_create_context(&screen_ctx, SCREEN_APPLICATION_CONTEXT);
...
应用程序与Screen的大部分交互都在此上下文的范围内。你可以通过此上下文识别和访问Screen API对象。
我们必须为应用程序创建具有适当权限的上下文。应用程序所需的权限类型可能取决于其功能。
二,创建一个渲染目标
这是指应用程序将要渲染的一个或多个缓冲区。渲染目标可以是流、位图或窗口。您还可以根据应用程序的需要,将这些目标组合使用。
例如:
...
screen_context_t screen_ctx;
screen_window_t screen_win;
...
screen_create_window(&screen_win, screen_ctx);
...
三,设置渲染目标的属性
现在已经创建了目标,我们必须在目标上设置相应的属性。至少,我们应该设置使用属性(SCREEN_PROPERTY_USAGE)。
...
int usage = SCREEN_USAGE_NATIVE;
...
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
...
此外,应用程序执行的渲染类型也会影响你需要设置渲染目标上的哪些属性。
四,为你的渲染目标创建缓冲区
你需要为你的渲染目标创建一个或多个缓冲区
...
/* Use a double-buffered window. This allows your application to work on a frame while* Screen is updating the framebuffer with previous changes.*/
int nbuffers = 2;
...
screen_create_window_buffers(screen_win, nbuffers);
...
缓冲区个数取决于你的渲染目标。
五,渲染你的目标
在Screen应用程序的渲染循环中,我们需要访问渲染目标的缓冲区,绘制到缓冲区,并发布图像。
每次在可以渲染到目标之前,我们需要访问渲染目标的缓冲区。这些缓冲区就是我们将要复制和写入的区域。我们可以通过检索渲染目标的SCREEN_PROPERTY_ Render_BUFFERS来获得所要渲染的缓冲区的句柄。
例如:
...while (1) {...screen_buffer_t screen_buf[2];screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)screen_buf);...}
...
至此,你可以使用不同的方法来绘制图像到缓冲区中。例如,可以使用 screen_fill() 来请求复制像素。
...while (1) {...screen_buffer_t screen_buf[2];screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)screen_buf);...int win_background[] = { SCREEN_BLIT_COLOR, 0xffffff00, SCREEN_BLIT_END };screen_fill(screen_ctx, screen_buf[0], win_background);...}
...
六,发布图像
到目前为止,已经渲染到目标或请求操作(例如填充),接下来需要触发Screen将图像显示在显示器上。如何做到这一点可能取决于应用程序如何渲染到缓冲区。例如,如果正在渲染一个窗口,则可以调用screen_post_window()。
...while (1) {screen_buffer_t screen_buf[2];screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)screen_buf);...int win_background[] = { SCREEN_BLIT_COLOR, 0xffffff00, SCREEN_BLIT_END };screen_fill(screen_ctx, screen_buf[0], win_background);...screen_post_window(screen_win, screen_buf[0], 0, NULL, 0);...}
...
七,处理Screen事件
Screen事件包括输入事件和一般事件,它们与应用程序的上下文相关联,并可以在渲染循环中处理。
...
int val;
...while (1) {while (!screen_get_event(screen_ctx, screen_ev, 0)) {screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TYPE, &val);switch (val) {case SCREEN_EVENT_KEYBOARD:screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_FLAGS, &val);if (val & KEY_DOWN) {screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SYM, &val);switch (val) {case KEYCODE_ESCAPE:{/* clean up resources */return EXIT_SUCCESS;}default:break;}}break;...}}...screen_buffer_t screen_buf[2];screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)screen_buf);...int win_background[] = { SCREEN_BLIT_COLOR, 0xffffff00, SCREEN_BLIT_END };screen_fill(screen_ctx, screen_buf[0], win_background);...screen_post_window(screen_win, screen_buf[0], 0, NULL, 0);...}
...
当然,我们可以选择应用程序将处理的事件类型。