Mesa是什么
Mesa是一个由OpenGL/Vulkan实现的位为开源图形驱动提供各种GL入口的项目,它编译出来的库如下:
./egl/libEGL.so
./amd/vulkan/libvulkan_radeon.so
./glx/libGL.so
./gbm/libgbm.so
./mapi/es1api/libGLESv1_CM.so
./mapi/es2api/libGLESv2.so
./mapi/shared-glapi/libglapi.so
./gallium/targets/lavapipe/libvulkan_lvp.so
./gallium/targets/xa/libxatracker.so
./gallium/targets/dri/libgallium_dri.so
./gallium/targets/va/libgallium_drv_video.so
./mesa/drivers/dri/libmesa_dri_drivers.so
./intel/vulkan/libvulkan_intel.so
Mesa有两个作用:
1.对接GPU硬件,将应用层对GL API的调用转换到对硬件GPU的调用上
2.实现各种纯软的GL API。
Mesa实现了将OpenGL/Vulkan API的调用转换到用户态的DRI驱动程序上,
AMD和Intel都提供了支持Mesa的GPU驱动程序
Gallium3D 是Mesa提出的用于简化GPU驱动开发的框架,下图展示了MESA如何通过libGL与内核打交道,以及新旧两种用户态设备驱动的方式。
1.左边的驱动程序非常简单,设备驱动部分是直接和硬件相关的,由硬件厂商开发驱动,这里的MESA相当于一个OpenGL转换器,把上层应用对于OpenGL的调用转换到对特定硬件的调用,缺乏驱动一致性,需要针对每一款GPU做驱动优化。
2.右边是Gallium3D的方案,特点是添加了分层。OS WInSys部分抽象了当前的操作系统使得同一个DeviceDriver可以用于不同的操作系统,API State Tracker部分抽象了上层的不同的GL接口,使得同一个DeviceDriver可以支持不同的GL接口。整体大大降低了DeviceDriver的开发和适配难度。
下图是Gallium3D的详细实现方案:
普通GUI client的渲染过程
在普通的GUI应用中,界面是由图形组件(GTK,QT)布局,进而生成了场景图。通过遍历场景图,将其渲染在surface。最后这个surface的buffer数据交给weston进行合成输出。
在进行场景图渲染的时候,是使用绘图工具进行的(Cario/Skia)。其中绘图工具常有多多个后端,其中的GPU加速后端,有OpenGL/Vulkan。
OpenGL ES是一个API的SPEC,基于MESA的开源方案实现。MESA中相关buffer的分配是由内核中的DRM接口实现,分配GEM Buffer Object。以i.MX8系列使用的芯原GPU为例,DRM所调用的GEM分配算法最终由GPU的非开源驱动实现,内核只是在DRM框架和非开源驱动之间搭了一个桥梁。
以wayland平台上的egl为例,其中的GEM Buffer Object对象分配过程如下:
src/egl/drivers/dri2/platform_wayland.c
eglCreateWindowSurface–>_eglCreateWindowSurfaceCommon–>
disp->Driver->CreateWindowSurface–>dri2_wl_create_window_surface(platform_wayland.c)(wl_proxy_create_wrapper代理传输数据的核心函数)
–>dri2_create_drawable–>dri2_create_buffer–>dri2_allocate_textures
–>dri2_drawable_get_buffers–>dri2_wl_get_buffers–>update_buffers
–>get_back_bo–>gbm_bo_create**()** */* Wrapper 函数,主要调用 gbm_dri_bo_create */*
–>intelImageExtension**.**createImage */* 函数指针:指向 intel_create_image() */*
–>**drm_intel_bo_alloc_tiled
–>bo_alloc_tiled
–>drm_intel_gem_bo_alloc_internal
–>drmIoctl**(drm_fd,** DRM_IOCTL_I915_GEM_CREATE**,** &create)
APP提交buffer的到最终显示到屏幕的过程可以用网购来比喻,
- 当天截止日期前 下单的,当天发货
- 错过了,就明天发货
Wayland Client 和 Server 如何提交Buffer
Client通过eglSwapBuffersWithDamageEXT将画好的buffer提交给compositor。
Server通过同一个api将合成好的一帧写入frame buffer。Client以及Server-Compositor加载了不同的EGL实现。
在weston的compositor启动的时候,会添加一个output_repaint_timer_handler定时器处理函数。进一步调用weston_output_repaint在下一个vblank时唤醒,更新frame buffer进行重绘制(client负责绘图,server合成)。
具体来看,
weston_output_repaint
–>output->repaint
–>drm_output_repaint
–>drm_output_render
–>drm_output_render_gl(dry-gbm.c)
–>(output->base.compositor->renderer->repaint_output)
–>gl_renderer_repaint_output(gl-render.c)
–>swap_buffers_with_damage(eglSwapBuffersWithDamageEXT)
定时中断处理函数不断调用eglSwapBuffersWithDamageEXT,而client端也调用同一个函数,因此server端可以接收client端的buffer将其更新到surface,使得server 调用drm进行合成输出。repaint操作本质上是将client调用eglSwapBuffersWithDamageEXT所更新的damage区域提交给compositor,compositor更新buffer后合成显示。
Wayland Client 和 Server各有哪些初始化步骤
- 获取 Surface,并将 Display,Surface 以及 Context 绑定在当前的渲染线程上。