weston渲染流程

wl_surface.attach assigns the given wl_buffer as the pending wl_buffer. wl_surface.commit makes the pending wl_buffer the new surface contents, and the size of the surface becomes the size calculated from the wl_buffer, as described above. After commit, there is no pending buffer until the next attach.

1.attach将wl_buffer设置为pending wl_buffer而不是currect。

2.commit将pending wl_buffer设置为currect surface的buffer。

3.surface的大小由buffer决定。

    Committing a pending wl_buffer allows the compositor to read the pixels in the wl_buffer. The compositor may access the pixels at any time after the wl_surface.commit request. When the compositor will not access the pixels anymore, it will send the wl_buffer.release event. Only after receiving wl_buffer.release, the client may reuse the wl_buffer. A wl_buffer that has been attached and then replaced by another attach instead of committed will not receive a release event, and is not used by the compositor.

    If wl_surface.attach is sent with a NULL wl_buffer, the following wl_surface.commit will remove the surface content. 

    看wayland官方文档的内容,是允许attch一个NULLbuffer随后commit的。但是我测试下来client会死等callback消息【卡死】;猜测是否为client端自己定义timer进行commit的提交能够实现透明效果,不应该等待server的callback消息。


 

参考weston-simple-shm

1.buffer

fd = os_create_anonymous_file(size);   
    用户空间创建size大小文件,取得fd。
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    将用户空间buffer映射到进程内核空间。
pool = wl_shm_create_pool(display->shm, fd, size);
    pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);[server]
    创建pool[pool保证公用同一个内核空间]。映射同一个fd;此时client与weston达成共享内存。
buffer->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, format);
    buffer->pool = pool;[server]
    通过pool获取wl_buffer。
wl_shm_pool_destroy(pool);
    !!!不明白此操作!!!
buffer->shm_data = data;
    提供给client的绘画地址。

 随即client会对buffer->shm_data空间执行绘画

2.attach

client:
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
    buffer->buffer是一个指向struct wl_buffer的指针
server:
surface_attach
    weston_surface_state_set_buffer(&surface->pending, buffer);
        state->buffer = buffer;
    把weston_surface_state->buffer与weston_buffer对象绑定;buffer是一个指向weston_buffer的指针
    实际上是:weston_surface->pending->buffer = buffer;
    /* All the pending state, that wl_surface.commit will apply. */
    对此我理解当wl_surface.commit执行时,会用到这些pending->buffer

本质上是需要window->surface与buffer->buffer 绑定

3.damage

This request is used to describe the regions where the pending buffer is different from the current surface contents, and where the surface therefore needs to be repainted. The compositor ignores the parts of the damage that fall outside of the surface.

client:
wl_surface_damage(window->surface, x, y, window->width - 40, window->height - 40);
此请求用于描述挂起缓冲区与当前表面内容不同的区域,以及表面因此需要重新绘制的位置。合成器忽略掉落在表面之外的部分损坏。
损坏是双缓冲状态,其中x和y指定损坏矩形的左上角。
server:
surface_damage
    pixman_region32_union_rect(&surface->pending.damage_surface,
 				   &surface->pending.damage_surface,
 				   x, y, width, height);
    获取surface后,将新的damage区域与原有的damage区域进行组合,得到新的damage区域。

4.frame

 Request a notification when it is a good time to start drawing a new frame, by creating a frame callback. This is useful for throttling redrawing operations, and driving animations.

如果客户端提交的更新时间早于某个更新,则某些更新可能无法显示,并且客户端通过过于频繁的绘制而浪费资源。【callback的作用就是解决上述问题】

    A server should avoid signaling the frame callbacks if the surface is not visible in any way, e.g. the surface is off-screen, or completely obscured by other opaque surfaces.

client:
window->callback = wl_surface_frame(window->surface);
    申请帧绘制回调,每当绘制完一帧就发送wl_callback::done消息给用户client
server:
surface_frame
    wl_list_insert(surface->pending.frame_callback_list.prev, &cb->link);
    在Server端创建Frame callback,它会被放在该surface下的frame_callback_list列表中。返回它的代理对象wl_callback

5.commit

https://happyseeker.github.io/graphic/2016/11/10/wayland-commit-relative-flow.html

Surface state (input, opaque, and damage regions, attached buffers, etc.) is double-buffered.

表面状态(输入,不透明和损坏区域,附加缓冲区等)是双缓冲的。

commit操作本质上就是为double buffer而设计,多次操作、一次提交。注意到之前的操作attach,damage,frame等仅仅在commit以后才会生效。

client:
wl_surface_commit(window->surface);
server:
surface_commit
     if (sub) {
 	weston_subsurface_commit(sub);
 	return;
     }
 	weston_surface_commit(surface);
    如果是subsurface则走subsurface_commit,否则走surface_commit
server:
weston_subsurface_commit(struct weston_subsurface *sub)
    判断父子surface为同步或异步
...【todo】
server:
weston_surface_commit
    weston_surface_commit_state(surface, &surface->pending);
      
             
    weston_surface_commit_subsurface_order(surface);
            //更新subsurface的顺序,其实也是将subsurface从pending列表换到当前的列表中
            ...【todo】

    weston_surface_schedule_repaint(surface);
            //重绘界面,这块逻辑复杂
weston_surface_commit_state
1    weston_surface_attach(surface, state->buffer);
        surface->compositor->renderer->attach(surface, buffer);
            gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
            最终调用gl_renderer_attach;根据buffer->resource的不同,调用不同的attch函数:
                gl_renderer_attach_shm
                gl_renderer_attach_egl
                gl_renderer_attach_dmabuf
                gl_renderer_attach_gbm_buffer
            //绑定buffer;将surface_attch的时候放在weston_surface_state里的buffer与weston_surface的buffer绑定。
            实际上是将pending-buffer送到currect_buffer。

2    weston_surface_state_set_buffer(state, NULL);
        //将pending-buffer置空。

3    weston_surface_build_buffer_matrix(surface, &surface->surface_to_buffer_matrix);
        //对surface进行旋转,裁剪,缩放等动作
4    weston_surface_update_size(surface);
        //设置surface大小;这两个函数不太明白
5    surface->committed(surface, state->sx, state->sy);

 
        //将pending state更新到current state中,state包括前面描述的诸多内容   

 

weston_surface_schedule_repaint(struct weston_surface *surface)
        weston_output_schedule_repaint(struct weston_output *output)
            output->idle_repaint_source = wl_event_loop_add_idle(loop, idle_repaint, output);
                idle_repaint(void *data)
                    output->start_repaint_loop(output);
                        drm_output_start_repaint_loop(struct weston_output *output_base)

 

为什么wayland中要有repaint操作?不是号称都是Client绘图、wayland负责合成?
确实Client绘图,compositor(服务端)负责合成。但由于client绘图实际实现为double buffer,client最初的绘图操作都是在pending buffer中进行的,并没有直接绘制到framebuffer中,所以,在client完成绘制后,需要进行commit操作,commit后,服务端会将相应的buffer会更新到当前的surface中,此时,需要进行repaint操作,将客户端相应的绘制内容最终拷贝到framebuffer中

这里的repaint操作,本质上只是将客户端更新的绘制内容(damage区域)提交给compositor,最后由compositor进行合成后绘制到界面上

 

代码段小部件

 

 

 

 

 

代码段小部件

 

 

代码段小部件

 

 

代码段小部件

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章