天天看點

display: weston: opaque region筆記

client的設定方法:

region = wl_compositor_create_region(window->display->compositor);
wl_region_add(region, 0, 0,
	      window->geometry.width,
	      window->geometry.height);
wl_surface_set_opaque_region(window->surface, region);
wl_region_destroy(region);
           

server的對應操作:

static void
compositor_create_region(struct wl_client *client,
			 struct wl_resource *resource, uint32_t id)
{
	struct weston_region *region;
    //建立region對象
	region = malloc(sizeof *region);
...
	pixman_region32_init(&region->region);
    //通過pixman對region進行初始化
	region->resource =
		wl_resource_create(client, &wl_region_interface, 1, id);
    //真正建立weston裡面的object,初始化。
...
	wl_resource_set_implementation(region->resource, &region_interface,
				       region, destroy_region);
    //任然是初始化的一部分。
}
初始化weston_region以及他的resource
           
static void
region_add(struct wl_client *client, struct wl_resource *resource,
	   int32_t x, int32_t y, int32_t width, int32_t height)
{
	struct weston_region *region = wl_resource_get_user_data(resource);

	pixman_region32_union_rect(&region->region, &region->region,
				   x, y, width, height);
}
//其實就是通過pixman對region建立一個矩形區域。
           
static void
surface_set_opaque_region(struct wl_client *client,
			  struct wl_resource *resource,
			  struct wl_resource *region_resource)
{
	struct weston_surface *surface = wl_resource_get_user_data(resource);
	struct weston_region *region;

	if (region_resource) {
		region = wl_resource_get_user_data(region_resource);
		pixman_region32_copy(&surface->pending.opaque,
				     &region->region);
	} else {
		pixman_region32_clear(&surface->pending.opaque);
	}
}
//把surface與region進行一個綁定,如果region參數為null。則清空surface的region區域;
當然現在還是更新的pending部分,沒有實際應用。不commit都是pending
理論上這個值隻設定一次就可以。但是建議在不性能考慮的時候每次commit都設定一下。
           
static void
region_destroy(struct wl_client *client, struct wl_resource *resource)
{
	wl_resource_destroy(resource);
}
釋放resource
           

總的來說很簡單,client遵循完全一緻的操作邏輯,server這邊也是中規中矩的簡單操作。後面就要看commit以及後續怎麼處理region

/* wl_surface.set_opaque_region */
	pixman_region32_init(&opaque);
	pixman_region32_intersect_rect(&opaque, &state->opaque,
				       0, 0, surface->width, surface->height);
    //主要是和surface的區域做一個交集的動作,取交集部分作為不透明區域
	if (!pixman_region32_equal(&opaque, &surface->opaque)) {
		pixman_region32_copy(&surface->opaque, &opaque);
    //把對應的區域拷貝到surface裡面,而不是pending的了。
		wl_list_for_each(view, &surface->views, surface_link)
			weston_view_geometry_dirty(view);
            //簡單也簡單,就是view->transform.dirty = 1;屬性
	}

	pixman_region32_fini(&opaque);

pending 的不透明區域并不會因為一幀完整的commit而消失,是以理論上設定一次即可。
           

随後唯一的調用就在draw_view也就是合成的地方了

/* blended region is whole surface minus opaque region: */
	pixman_region32_init_rect(&surface_blend, 0, 0,
				  ev->surface->width, ev->surface->height);
//先假設全部區域都是可混合的
	if (ev->geometry.scissor_enabled)
		pixman_region32_intersect(&surface_blend, &surface_blend,
					  &ev->geometry.scissor);
	pixman_region32_subtract(&surface_blend, &surface_blend,
				 &ev->surface->opaque);
//合成的時候是從下往上畫的。上面用到opaque region也很簡單,這個view哪些部分是blend區域,哪部分是opaque區域。
	/* XXX: Should we be using ev->transform.opaque here? */
	pixman_region32_init(&surface_opaque);
	if (ev->geometry.scissor_enabled)
		pixman_region32_intersect(&surface_opaque,
					  &ev->surface->opaque,
					  &ev->geometry.scissor);
	else
		pixman_region32_copy(&surface_opaque, &ev->surface->opaque);