1. 程式人生 > >Wayland原始碼分析-damage相關流程

Wayland原始碼分析-damage相關流程

wayland程式碼分析系列,剛剛開始,慢慢來~

本文關注damage相關的流程

Damage?

什麼是damage?做圖形開發的同學應該還比較熟悉,準確定義就不去深究了。

可以理解為,當圖形應用需要重繪指定區域時,傳送的一種事件,X11協議中有針對Damage的專門的擴充套件協議,Wayland中,其實就是client向server傳送的一種事件(request),server端(compositor)收到事件後進行相應的處理,通常也就是重繪指定的區域。

初始情況下,wayland客戶端會將整個surface作為初始區域,傳送damage,目的時繪製surface。

流程

還是以weston程式碼中的最簡單的client示例程式碼simple-shm為例看看相關流程。

client在建立display、window之後,呼叫:wl_surface_damage傳送request,流程開始:

wl_surface_damage實現如下(由scanner工具生成,原始碼中沒有):

static inline void
wl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
{
	wl_proxy_marshal((struct wl_proxy *) wl_surface,
			 WL_SURFACE_DAMAGE, x, y, width, height);
}

本質上就是封裝相關資料,然後呼叫與服務端通訊的介面,將相應的request:WL_SURFACE_DAMAGE傳送給server,然後由server呼叫本地相應的介面完成處理。

服務端接收到相應request之後,呼叫本地介面(有關wayland客戶端和服務端通訊相關的機制,後續再抽空寫單獨的文章來說明),本地介面定義為:

static const struct wl_surface_interface surface_interface = {
	surface_destroy,
	surface_attach,
	surface_damage,
	surface_frame,
	surface_set_opaque_region,
	surface_set_input_region,
	surface_commit,
	surface_set_buffer_transform,
	surface_set_buffer_scale
};

可見damage對應介面為:surface_damage,實現為:

static void
surface_damage(struct wl_client *client,
	       struct wl_resource *resource,
	       int32_t x, int32_t y, int32_t width, int32_t height)
{
	struct weston_surface *surface = wl_resource_get_user_data(resource);

	pixman_region32_union_rect(&surface->pending.damage,
				   &surface->pending.damage,
				   x, y, width, height);
}

其實,就啥也沒幹,獲取surface後,將新的damage區域與原有的damage區域進行組合,得到新的damage區域。

另,wayland 0.99版本之後,都使用了double buffer state,對於damage區域也是如此,之前更新damage區域時,更新的都是pending的damage,在commit之後,才將pending.damage賦值給current damage,然後clear掉pending.damage供下次使用。然後,在服務端repaint surface時,會清理掉current.damage供下次使用。

從整個流程上看,其實就是更新了一下damage對應的區域而已,沒有其它操作,真正的繪圖操作是在客戶端commit後,由服務端compositor根據之前更新的damage區域來進行的,damage區域以外的區域不會被重繪。