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驱动程序

DRM和Wayland_驱动程序

Gallium3D 是Mesa提出的用于简化GPU驱动开发的框架,下图展示了MESA如何通过libGL与内核打交道,以及新旧两种用户态设备驱动的方式。

1.左边的驱动程序非常简单,设备驱动部分是直接和硬件相关的,由硬件厂商开发驱动,这里的MESA相当于一个OpenGL转换器,把上层应用对于OpenGL的调用转换到对特定硬件的调用,缺乏驱动一致性,需要针对每一款GPU做驱动优化。

2.右边是Gallium3D的方案,特点是添加了分层。OS WInSys部分抽象了当前的操作系统使得同一个DeviceDriver可以用于不同的操作系统,API State Tracker部分抽象了上层的不同的GL接口,使得同一个DeviceDriver可以支持不同的GL接口。整体大大降低了DeviceDriver的开发和适配难度。

下图是Gallium3D的详细实现方案:

DRM和Wayland_weston_02

普通GUI client的渲染过程

DRM和Wayland_weston_03

在普通的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的到最终显示到屏幕的过程可以用网购来比喻,

  • 当天截止日期前 下单的,当天发货
  • 错过了,就明天发货

DRM和Wayland_3d_04

DRM和Wayland_wayland_05

Wayland Client 和 Server 如何提交Buffer

Client通过eglSwapBuffersWithDamageEXT将画好的buffer提交给compositor。

Server通过同一个api将合成好的一帧写入frame buffer。Client以及Server-Compositor加载了不同的EGL实现。

DRM和Wayland_用户态_06

在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各有哪些初始化步骤

DRM和Wayland_weston_07

  • 获取 Surface,并将 Display,Surface 以及 Context 绑定在当前的渲染线程上。

DRM和Wayland_wayland_08