天天看点

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);