diff options
Diffstat (limited to 'src/pixman-renderer.c')
-rw-r--r-- | src/pixman-renderer.c | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c index 26f6f279..74ed58f4 100644 --- a/src/pixman-renderer.c +++ b/src/pixman-renderer.c @@ -139,6 +139,35 @@ region_global_to_output(struct weston_output *output, pixman_region32_t *region) #define D2F(v) pixman_double_to_fixed((double)v) static void +transform_apply_viewport(pixman_transform_t *transform, + struct weston_surface *surface) +{ + struct weston_buffer_viewport *vp = &surface->buffer_viewport; + double src_width, src_height; + double src_x, src_y; + + if (vp->buffer.src_width == wl_fixed_from_int(-1)) { + if (vp->surface.width == -1) + return; + + src_x = 0.0; + src_y = 0.0; + src_width = surface->width_from_buffer; + src_height = surface->height_from_buffer; + } else { + src_x = wl_fixed_to_double(vp->buffer.src_x); + src_y = wl_fixed_to_double(vp->buffer.src_y); + src_width = wl_fixed_to_double(vp->buffer.src_width); + src_height = wl_fixed_to_double(vp->buffer.src_height); + } + + pixman_transform_scale(transform, NULL, + D2F(src_width / surface->width), + D2F(src_height / surface->height)); + pixman_transform_translate(transform, NULL, D2F(src_x), D2F(src_y)); +} + +static void repaint_region(struct weston_view *ev, struct weston_output *output, pixman_region32_t *region, pixman_region32_t *surf_region, pixman_op_t pixman_op) @@ -147,10 +176,13 @@ repaint_region(struct weston_view *ev, struct weston_output *output, (struct pixman_renderer *) output->compositor->renderer; struct pixman_surface_state *ps = get_surface_state(ev->surface); struct pixman_output_state *po = get_output_state(output); + struct weston_buffer_viewport *vp = &ev->surface->buffer_viewport; pixman_region32_t final_region; float view_x, view_y; pixman_transform_t transform; pixman_fixed_t fw, fh; + pixman_image_t *mask_image; + pixman_color_t mask = { 0, }; /* The final region to be painted is the intersection of * 'region' and 'surf_region'. However, 'region' is in the global @@ -257,33 +289,12 @@ repaint_region(struct weston_view *ev, struct weston_output *output, pixman_double_to_fixed ((double)-ev->geometry.y)); } - if (ev->surface->buffer_viewport.viewport_set) { - double viewport_x, viewport_y, viewport_width, viewport_height; - double ratio_x, ratio_y; - - viewport_x = wl_fixed_to_double(ev->surface->buffer_viewport.src_x); - viewport_y = wl_fixed_to_double(ev->surface->buffer_viewport.src_y); - viewport_width = wl_fixed_to_double(ev->surface->buffer_viewport.src_width); - viewport_height = wl_fixed_to_double(ev->surface->buffer_viewport.src_height); - - ratio_x = viewport_width / ev->surface->buffer_viewport.dst_width; - ratio_y = viewport_height / ev->surface->buffer_viewport.dst_height; + transform_apply_viewport(&transform, ev->surface); - pixman_transform_scale(&transform, NULL, - pixman_double_to_fixed(ratio_x), - pixman_double_to_fixed(ratio_y)); - pixman_transform_translate(&transform, NULL, pixman_double_to_fixed(viewport_x), - pixman_double_to_fixed(viewport_y)); - } + fw = pixman_int_to_fixed(ev->surface->width); + fh = pixman_int_to_fixed(ev->surface->height); - pixman_transform_scale(&transform, NULL, - pixman_double_to_fixed(ev->surface->buffer_viewport.scale), - pixman_double_to_fixed(ev->surface->buffer_viewport.scale)); - - fw = pixman_int_to_fixed(pixman_image_get_width(ps->image)); - fh = pixman_int_to_fixed(pixman_image_get_height(ps->image)); - - switch (ev->surface->buffer_viewport.transform) { + switch (vp->buffer.transform) { case WL_OUTPUT_TRANSFORM_FLIPPED: case WL_OUTPUT_TRANSFORM_FLIPPED_90: case WL_OUTPUT_TRANSFORM_FLIPPED_180: @@ -295,7 +306,7 @@ repaint_region(struct weston_view *ev, struct weston_output *output, break; } - switch (ev->surface->buffer_viewport.transform) { + switch (vp->buffer.transform) { default: case WL_OUTPUT_TRANSFORM_NORMAL: case WL_OUTPUT_TRANSFORM_FLIPPED: @@ -317,9 +328,13 @@ repaint_region(struct weston_view *ev, struct weston_output *output, break; } + pixman_transform_scale(&transform, NULL, + pixman_double_to_fixed(vp->buffer.scale), + pixman_double_to_fixed(vp->buffer.scale)); + pixman_image_set_transform(ps->image, &transform); - if (ev->transform.enabled || output->current_scale != ev->surface->buffer_viewport.scale) + if (ev->transform.enabled || output->current_scale != vp->buffer.scale) pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0); else pixman_image_set_filter(ps->image, PIXMAN_FILTER_NEAREST, NULL, 0); @@ -327,9 +342,16 @@ repaint_region(struct weston_view *ev, struct weston_output *output, if (ps->buffer_ref.buffer) wl_shm_buffer_begin_access(ps->buffer_ref.buffer->shm_buffer); + if (ev->alpha < 1.0) { + mask.alpha = 0xffff * ev->alpha; + mask_image = pixman_image_create_solid_fill(&mask); + } else { + mask_image = NULL; + } + pixman_image_composite32(pixman_op, ps->image, /* src */ - NULL /* mask */, + mask_image, /* mask */ po->shadow_image, /* dest */ 0, 0, /* src_x, src_y */ 0, 0, /* mask_x, mask_y */ @@ -337,6 +359,9 @@ repaint_region(struct weston_view *ev, struct weston_output *output, pixman_image_get_width (po->shadow_image), /* width */ pixman_image_get_height (po->shadow_image) /* height */); + if (mask_image) + pixman_image_unref(mask_image); + if (ps->buffer_ref.buffer) wl_shm_buffer_end_access(ps->buffer_ref.buffer->shm_buffer); @@ -384,8 +409,9 @@ draw_view(struct weston_view *ev, struct weston_output *output, } /* TODO: Implement repaint_region_complex() using pixman_composite_trapezoids() */ - if (ev->transform.enabled && - ev->transform.matrix.type != WESTON_MATRIX_TRANSFORM_TRANSLATE) { + if (ev->alpha != 1.0 || + (ev->transform.enabled && + ev->transform.matrix.type != WESTON_MATRIX_TRANSFORM_TRANSLATE)) { repaint_region(ev, output, &repaint, NULL, PIXMAN_OP_OVER); } else { /* blended region is whole surface minus opaque region: */ |