渲染流水线
一个Wayland client要将内存渲染到屏幕上,首先要申请一个graphic buffer,绘制完后传给Wayland compositor并通知其重绘。Wayland compositor收集所有Wayland client的请求,然后以一定周期把所有提交的graphic buffer进行合成。合成完后进行输出。本质上,client需要将窗口内容绘制到一个和compositor共享的buffer上。这个buffer可以是普通共享内存,也可以是DRM中的GBM或是gralloc提供的可供硬件(如GPU)操作的graphic buffer,当然你也可以直接调用ion的接口去创建buffer。在大多数移动平台上,没有专门的显存,因此它们最终都来自系统内存,区别在于图形加速硬件一般会要求物理连续且符合对齐要求的内存。如果是普通共享内存,一般是物理不连续的,多数情况用软件渲染。有些图形驱动也支持用物理不连续内存做硬件加速,但效率相对会低一些。根据buffer类型的不同,client可以选择自己绘制,或是通过Cairo,OpenGL绘制,或是更高层的如Qt,GTK+这些widget库等绘制。绘制完后client将buffer的handle传给server,以及需要重绘的区域。在server端,compositor将该buffer转为纹理(如果是共享内存使用glTexImage2D上传纹理[我在gl_render_attach_shm中没有找到这个函数,只看到了ensure_textures,fd的传输是在client创建buffer的时候的surface_attach,对应的内容应该就在wl_shm_pool之中;因为虽然client到server直接给fd,ok,那么server到gpu的copy是哪里实现的呢?猜测可能是get_surface_state->gl_renderer_create_surface->gl_renderer_flush_damage;或者weston_output_repaint->output_accumulate_damage->surface_flush_damage],
硬件加速buffer用GL_OES_EGL_image_external扩展生成外部纹理)。最后将其与其它的窗口内容进行合成。下面是抽象的流程图。
使用drm-backend,client绘画如果用opengl+opengles,直接与gpu的driver交互;compositor下面的gl-renderer与pixman-renderer一般是二选一。
标准的基于egl的绘画,可以参考simple-egl.c的代码,client调用opengl/opengles实现绘画,最终是eglswapbuffer;server这边有对应buffer的gbm object以及handle,根据damage等条件,一系列条件决定合成,合成会最少有一张经过gpu合成的完整的scan-out图(可能有overlay,也可能有cursor)然后addfb2为对应的buffer创建framebuffer对象,并且返回fbid,后面就是ioctl的标准处理流程
参考https://github.com/wayland-project/weston/blob/master/clients/simple-shm.c & https://github.com/wayland-project/wayland/blob/master/protocol/wayland.xml