转至元数据结尾
转至元数据起始

问题背景:FDE在鼠标操作过程中发现光标显示不流畅给人以系统卡顿的感觉。为了提升用户对FDE的使用体验,决定对FDE光标显示进行优化。

FDE光标显示原始方案是使用Android光标作为FDE的光标进行显示,weston光标和x11光标均被隐藏。如下图所示:

FDE光标显示原始方案图.drawio.png

原始方案中的缺点:FDE光标在Android client渲染,而后经历了hwcomposer、weston compositor、XServer composite三个阶段的合成,整个流程很长,时间延迟较大。

优化方案介绍:缩短FDE光标的渲染合成流程,减少延迟的时间,把FDE的光标层提到xserver端更早地渲染出来。而不是先作为作为Android client渲染再去参与后续的三次图形合成流程平白增加了延迟的时间。

在实际优化过程中,此问题分为了两个阶段的优化。

第一阶段:将Android光标内容提取出来,然后创建weston光标,将提取的Android光标的内容贴到新创建的weston光标上,然后隐藏掉Android光标和x11光标,让weston光标来代替Android光标作为FDE的光标进行显示。如下图所示:

第一阶段优化方案图.drawio.png

第一阶段优化方案中的关键流程如下图所示:

hwcomposer-Android光标转weston光标流程图.drawio.png

第二阶段:第一阶段优化后,FDE光标不需要经过Android端的hwcomposer进行合成,直接在weston compositor参与合成,渲染合成的流程缩短了,光标流畅度有在AMD显卡上有明显提升。因为后续的测试中在景嘉微显卡上运行时,FDE光标显示的流畅度虽有所提升,但仍然比较慢, 是因为weston的gl_renderer_repaint_output函数和在AMD显卡相比,在景嘉微显卡上运行很慢。为了进一步提升操作体验,在第一阶段的基础上继续进行优化,首先在景嘉微显卡上对比测试麒麟桌面应用操作光标比较流畅。

而FDE的weston窗口是运行在麒麟系统之上的,所以考虑为weston窗口创建自定义的x11光标,将weston client的光标内容提取出来并给到新创建的x11光标,然后隐藏Android光标和weston client光标,让x11光标作为FDE的光标进行显示。如下图所示:

第二阶段优化方案图.drawio.png

第二阶段优化方案中的关键流程如下图所示:

weston-weston光标转x11光标流程图.drawio.png

调试过程中的关键调用栈信息:

pointer_set_cursor调用栈信息.png

Android的hwcomposer将Android光标图层过滤并提取图形buffer数据,最后通过wayland协议调用wl_pointer_set_cursor接口将创建好的cursor_surface光标图层设置到weston光标。Android hwcomposer和weston间会基于libwayland-server.so库进行相关调用,最后weston的pointer_set_cursor方法会被调用。在此方法中能得到Android hwcomposer端设置的cursor_surface。并最终将cursor_surface内容贴到weston光标上。

而在weston光标转x11光标优化方案里,在pointer_set_cursor方法中我们可以得到weston光标图层weston_surface,根据weston_surface的宽高信息开辟一段临时内存空间用于存储weston光标图形数据,通过weston_surface_copy_content提取到weston光标的图形数据并保存到临时开辟的内存空间中。最后通过调用新增的函数set_custom_cursor创建并设置x11光标,同时调用pointer_unmap_sprite将weston光标隐藏。创建设置x11光标功能实现参照了libxcursor和libxrender库,其中的一些关键方法有

XcursorImageCreate: 创建XcursorImage,在创建好后接下来可将提取的weston光标图形数据赋给XcursorImage变量的XcursorPixel指针。

XcursorImageLoadCursor:此方法封装了Cursor的创建过程,将赋值好的XcursorImage作为参数传入。

XCreatePixmap:创建Pixmap

XCreateGC:创建GC图形上下文

XPutImage:在XcursorImage转换成XImage后,将XImage和Pixmap作为参数传入,将图形数据贴到Pixmap上。

XRenderCreatePicture:创建Picture,Pixmap作为参数传入将图形数据转到Picture上。

XRenderCreateCursor:创建Cursor,Picture作为参数传入。