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