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(®ion->region);
//通过pixman对region进行初始化
region->resource =
wl_resource_create(client, &wl_region_interface, 1, id);
//真正创建weston里面的object,初始化。
...
wl_resource_set_implementation(region->resource, ®ion_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(®ion->region, ®ion->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,
®ion->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);