接上一篇
display:weston渲染流程:buffer+attach+damage+frame
display:weston渲染流程:buffer+attach+damage+frame_maze的专栏-CSDN博客
5.commit
Surface state (input, opaque and damage regions, attached buffers, etc.) is double-buffered.
表面状态(输入,不透明和损坏区域,附加缓冲区等)是双缓冲的。=>[防止图像抖动]
commit操作本质上就是为double buffer而设计,多次操作、一次提交。注意到之前的操作attach,damage,frame等仅仅在commit以后才会生效。(之前的操作都是对pending结构体的操作,只有commit以后才会切换到current结构体上)
client:
wl_surface_commit(window->surface);
server: weston/libweston/compositor.c::surface_commit
surface_commit
...
weston_surface_is_pending_viewport_source_valid //对pending的buffer进行缩放/旋转相关操作
这里写错了,没有旋转相关操作!只有裁剪或者缩放
weston_surface_is_pending_viewport_dst_size_int //缩放相关校验,服务为wp_viewporter;
...
if (surface->pending.acquire_fence_fd >= 0) { //fence相关的内容,同步保证互斥buffer的fence
/* We support fences for both wp_linux_dmabuf and opaque EGL
* buffers, as mandated by minor version 2 of the
* zwp_linux_explicit_synchronization_v1 protocol. Since
* renderers that support fences currently only support these
* two buffer types plus SHM buffers, we can just check for the
* SHM buffer case here.
*/
if(!surface->pending,buffer)
fd_clear(&surface->pending.acquire_fence_fd);
if(wl_shm_buffer_get(surface->pending.buffer->resource))
fd_clear(******fd);
如果没buffer,清空对应fence,如果buffer是shm的,清空fence
...
}
...
if (sub) {
weston_subsurface_commit(sub); //1
return;
}
weston_surface_commit(surface);
...
wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
if (sub->surface != surface)
weston_subsurface_parent_commit(sub, 0); //看上去主要是处理subsurface的view对应的位置
...
weston_view_set_position //这个是绝对坐标
...
}
如果是subsurface则走subsurface_commit,否则走surface_commit
1.weston_subsurface_commit(struct weston_subsurface *sub)
if (weston_subsurface_is_synchronized(sub)) {
weston_subsurface_commit_to_cache(sub);
} else {
if (sub->has_cached_data) {
/* flush accumulated state from cache */
weston_subsurface_commit_to_cache(sub);
weston_subsurface_commit_from_cache(sub);
} else {
weston_surface_commit(surface);
}
wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
if (tmp->surface != surface)
weston_subsurface_parent_commit(tmp, 0);
}
}
判断父子surface为同步或异步,并完成相应的commit操作
...
目前weston在commit的逻辑里面加载了对fence的支持。 shm-buffer还不支持
buffer对应绘画的部分,viewport对应最终显示的状态,中间有一个缩放或者裁剪的过程。
补充:
wl_subsurface::set_sync - set sub-surface to synchronized mode
Change the commit behaviour of the sub-surface to synchronized mode, also described
as the parent dependent mode.
In synchronized mode, wl_surface.commit on a sub-surface will accumulate the
committed state in a cache, but the state will not be applied and hence will not
change the compositor output. The cached state is applied to the sub-surface
immediately after the parent surface's state is applied. This ensures atomic
updates of the parent and all its synchronized sub-surfaces. Applying the cached
state will invalidate the cache, so further parent surface commits do not
(re-)apply old state.
wl_subsurface::set_sync—将subsurface设置为同步模式
将子表面的提交行为更改为同步模式,也就是描述作为父依赖模式。
在同步模式下,子表面上的wl_surface.commit将提交状态累积在缓存中,
if (weston_subsurface_is_synchronized(sub)) {
weston_subsurface_commit_to_cache(sub);
但是该状态不会被应用,因此也不会被更改compositor的输出。
在应用父表面的状态之后立即执行“缓存的状态应用于子表面”。
这样可以确保原子性父类及其所有同步子表面的更新。
已经使用的subsurface的缓存将被使用后无效话,下次父表面的提交将不会再次应用子表面的老的state.
另外一种:
wl_subsurface::set_desync - set sub-surface to desynchronized mode
Change the commit behaviour of the sub-surface to desynchronized mode, also described as
independent or freely running mode.
In desynchronized mode, wl_surface.commit on a sub-surface will apply the pending state
directly, without caching, as happens normally with a wl_surface. Calling
wl_surface.commit on the parent surface has no effect on the sub-surface's wl_surface
state. This mode allows a sub-surface to be updated on its own.
If cached state exists when wl_surface.commit is called in desynchronized mode, the
pending state is added to the cached state, and applied as a whole. This invalidates the cache.
Note: even if a sub-surface is set to desynchronized, a parent sub-surface may override
it to behave as synchronized. For details, see wl_subsurface.
If a surface's parent surface behaves as desynchronized, then the cached state is applied
on set_desync.
将子表面的提交行为更改为去同步模式,也称为独立或自由运行模式。
在不同步模式下,子表面上的wl_surface.commit将直接应用挂起状态,而不使用缓存,就像在wl_surface上
通常所做的那样。在父表面上调用wl_surface.commit对子表面的wl_surface状态没有影响。此模式允许子表
面自行更新。
如果在以非同步模式调用wl_surface.commit时存在缓存状态,则将挂起状态添加到缓存状态,并作为一个整
体应用。这会使缓存失效。也就是,本来应该是对pending结构体做操作,变量换成了cached结构体
server:
2.weston_surface_commit
weston_surface_commit_state(surface, &surface->pending);
//注意参数,一个是之前的pending;把pending里面存储的状态转移给surface
weston_surface_commit_subsurface_order(surface);
//更新subsurface的顺序,其实也是将subsurface从pending列表换到当前的列表中
...【todo】
weston_surface_schedule_repaint(surface);
//重绘界面,这块逻辑复杂
weston_surface_commit::weston_surface_commit_state
里面很多egl函数看不懂,见此参考gl-renderer.c的gl_renderer_setup 里面存在关联操作,如:
3728 gr->image_target_texture_2d =
3729 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
weston_surface_commit_state
0 surface->buffer_viewport = state->buffer_viewport;
具体内容查看buffer_viewport结构体,主要与缩放设置相关
把pending交给对应的surface
...
if(state->newly_attached) {
fence相关,也是把pending的acquire_fence_fd给到surface,
//attach。之前已经画好的图,在attach里面绑定到surface上面,gl_renderer创建texture。将之前client自己画好的buffer和这个[不一定一个]texture关联上。
1 weston_surface_attach(surface, state->buffer);
weston_buffer_reference(&surface->buffer_ref, buffer); //先关联weston_surface和weston_buffer
surface->compositor->renderer->attach(surface, buffer); //一般来说,有gl_renderer就不会使用pixman等软件渲染backend;关于attach,本质上是执行ensure_textures(gs, num_planes);
gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
weston_buffer_reference(&gs->buffer_ref, buffer); //再关联gl_surface_state和weston_buffer
最终调用gl_renderer_attach;根据buffer->resource的不同,调用不同的attch函数:
gl_renderer_attach_shm //不同的图像格式需要的plane不一样,yuv普遍多一些[yuv分开存放,一个存y,一个存v或者uv...];app申请了shm的server,有wl_shm_buffer的实例,会走入这个逻辑;
//创建gl_sruface_state gs对象指针,填充gs结构体,为gs对象生成并绑定GL_TEXTURE_2D texture对象
gs->target = GL_TEXTURE_2D; //设置为2D纹理
gs->surface = es; //es是weston_surface;gs是gl_surface_state
ensure_textures(gs, GL_TEXTURE_2D, num_planes); //为从client传过来的buffer创建2d纹理;不同format的纹理数不一样,shm里面的逻辑只有在第一次创建次client的时候才有,后续无论图片如何变化都不再进入。也就是为新的buffer创建texture
gl_renderer_attach_egl
buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
ensure_textures //同上
egl_image_create //为对应buffer创建egl_image
eglCreateImage //这部分请查看我文章对eglapi的笔记!!!
image_target_