Skip to content
Commits on Source (7)
......@@ -862,11 +862,11 @@ shared_output_repainted(struct wl_listener *listener, void *data)
wl_list_for_each(sb, &so->shm.buffers, link)
pixman_region32_union(&sb->damage, &sb->damage, &damage);
/* Translate back to global space for transform_region */
pixman_region32_translate(&damage, so->output->x, so->output->y);
/* Transform to buffer coordinates */
weston_transformed_region(so->output->width, so->output->height,
so->output->transform,
so->output->current_scale,
&damage, &damage);
weston_region_global_to_output(&damage, so->output, &damage);
if (shared_output_ensure_tmp_data(so, &damage) < 0)
goto err_pixman_init;
......
......@@ -421,16 +421,10 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
return;
pixman_region32_init(&scanout_damage);
pixman_region32_copy(&scanout_damage, damage);
pixman_region32_translate(&scanout_damage,
-output->base.x, -output->base.y);
weston_transformed_region(output->base.width,
output->base.height,
output->base.transform,
output->base.current_scale,
&scanout_damage,
&scanout_damage);
weston_region_global_to_output(&scanout_damage,
&output->base,
damage);
assert(scanout_state->damage_blob_id == 0);
......
......@@ -210,7 +210,7 @@ drm_plane_state_coords_for_view(struct drm_plane_state *state,
struct drm_output *output = state->output;
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
pixman_region32_t dest_rect, src_rect;
pixman_box32_t *box, tbox;
pixman_box32_t *box;
float sxf1, syf1, sxf2, syf2;
if (!drm_view_transform_supported(ev, &output->base))
......@@ -227,17 +227,14 @@ drm_plane_state_coords_for_view(struct drm_plane_state *state,
pixman_region32_init(&dest_rect);
pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
&output->base.region);
pixman_region32_translate(&dest_rect, -output->base.x, -output->base.y);
weston_region_global_to_output(&dest_rect, &output->base, &dest_rect);
box = pixman_region32_extents(&dest_rect);
tbox = weston_transformed_rect(output->base.width,
output->base.height,
output->base.transform,
output->base.current_scale,
*box);
state->dest_x = tbox.x1;
state->dest_y = tbox.y1;
state->dest_w = tbox.x2 - tbox.x1;
state->dest_h = tbox.y2 - tbox.y1;
state->dest_x = box->x1;
state->dest_y = box->y1;
state->dest_w = box->x2 - box->x1;
state->dest_h = box->y2 - box->y1;
pixman_region32_fini(&dest_rect);
/* Now calculate the source rectangle, by finding the extents of the
......
......@@ -615,15 +615,7 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
int i, n;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, &sb->damage);
pixman_region32_translate(&damage, -sb->output->base.x,
-sb->output->base.y);
weston_transformed_region(sb->output->base.width,
sb->output->base.height,
sb->output->base.transform,
sb->output->base.current_scale,
&damage, &damage);
weston_region_global_to_output(&damage, &sb->output->base, &sb->damage);
if (sb->output->frame) {
frame_interior(sb->output->frame, &ix, &iy, &iwidth, &iheight);
......
......@@ -466,13 +466,9 @@ set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region
b = to_x11_backend(ec);
pixman_region32_init(&transformed_region);
pixman_region32_copy(&transformed_region, region);
pixman_region32_translate(&transformed_region,
-output_base->x, -output_base->y);
weston_transformed_region(output_base->width, output_base->height,
output_base->transform,
output_base->current_scale,
&transformed_region, &transformed_region);
weston_region_global_to_output(&transformed_region,
output_base,
region);
rects = pixman_region32_rectangles(&transformed_region, &nrects);
output_rects = calloc(nrects, sizeof(xcb_rectangle_t));
......
......@@ -172,8 +172,9 @@ weston_output_transform_coordinate(struct weston_output *output,
double *x, double *y);
void
weston_output_region_from_global(struct weston_output *output,
pixman_region32_t *region);
weston_region_global_to_output(pixman_region32_t *dst,
struct weston_output *output,
pixman_region32_t *src);
const struct weston_hdr_metadata_type1 *
weston_output_get_hdr_metadata_type1(const struct weston_output *output);
......
......@@ -658,126 +658,57 @@ weston_view_to_global_float(struct weston_view *view,
}
}
/** Transform a point to buffer coordinates
*
* \param width Surface width.
* \param height Surface height.
* \param transform Buffer transform.
* \param scale Buffer scale.
* \param sx Surface x coordinate of a point.
* \param sy Surface y coordinate of a point.
* \param[out] bx Buffer x coordinate of the point.
* \param[out] by Buffer Y coordinate of the point.
*
* Converts the given surface-local coordinates to buffer coordinates
* according to the given buffer transform and scale.
* This ignores wp_viewport.
*
* The given width and height must be the result of inverse scaled and
* inverse transformed buffer size.
*/
WL_EXPORT void
weston_transformed_coord(int width, int height,
enum wl_output_transform transform,
int32_t scale,
float sx, float sy, float *bx, float *by)
{
switch (transform) {
case WL_OUTPUT_TRANSFORM_NORMAL:
default:
*bx = sx;
*by = sy;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED:
*bx = width - sx;
*by = sy;
break;
case WL_OUTPUT_TRANSFORM_90:
*bx = sy;
*by = width - sx;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
*bx = sy;
*by = sx;
break;
case WL_OUTPUT_TRANSFORM_180:
*bx = width - sx;
*by = height - sy;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
*bx = sx;
*by = height - sy;
break;
case WL_OUTPUT_TRANSFORM_270:
*bx = height - sy;
*by = sx;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
*bx = height - sy;
*by = width - sx;
break;
}
*bx *= scale;
*by *= scale;
}
/** Transform a rectangle to buffer coordinates
*
* \param width Surface width.
* \param height Surface height.
* \param transform Buffer transform.
* \param scale Buffer scale.
* \param rect Rectangle in surface coordinates.
* \return Rectangle in buffer coordinates.
*
* Converts the given surface-local rectangle to buffer coordinates
* according to the given buffer transform and scale. The resulting
* rectangle is guaranteed to be well-formed.
* This ignores wp_viewport.
*
* The given width and height must be the result of inverse scaled and
* inverse transformed buffer size.
*/
WL_EXPORT pixman_box32_t
weston_transformed_rect(int width, int height,
enum wl_output_transform transform,
int32_t scale,
pixman_box32_t rect)
weston_matrix_transform_rect(struct weston_matrix *matrix,
pixman_box32_t rect)
{
float x1, x2, y1, y2;
pixman_box32_t ret;
int i;
pixman_box32_t out;
weston_transformed_coord(width, height, transform, scale,
rect.x1, rect.y1, &x1, &y1);
weston_transformed_coord(width, height, transform, scale,
rect.x2, rect.y2, &x2, &y2);
/* since pixman regions are defined by two corners we have
* to be careful with rotations that aren't multiples of 90.
* We need to take all four corners of the region and rotate
* them, then construct the largest possible two corner
* rectangle from the result.
*/
struct weston_vector corners[4] = {
{{rect.x1, rect.y1, 0, 1}},
{{rect.x2, rect.y1, 0, 1}},
{{rect.x1, rect.y2, 0, 1}},
{{rect.x2, rect.y2, 0, 1}},
};
if (x1 <= x2) {
ret.x1 = x1;
ret.x2 = x2;
} else {
ret.x1 = x2;
ret.x2 = x1;
for (i = 0; i < 4; i++) {
weston_matrix_transform(matrix, &corners[i]);
corners[i].f[0] /= corners[i].f[3];
corners[i].f[1] /= corners[i].f[3];
}
if (y1 <= y2) {
ret.y1 = y1;
ret.y2 = y2;
} else {
ret.y1 = y2;
ret.y2 = y1;
}
out.x1 = floor(corners[0].f[0]);
out.y1 = floor(corners[0].f[1]);
out.x2 = ceil(corners[0].f[0]);
out.y2 = ceil(corners[0].f[1]);
return ret;
for (i = 1; i < 4; i++) {
if (floor(corners[i].f[0]) < out.x1)
out.x1 = floor(corners[i].f[0]);
if (floor(corners[i].f[1]) < out.y1)
out.y1 = floor(corners[i].f[1]);
if (ceil(corners[i].f[0]) > out.x2)
out.x2 = ceil(corners[i].f[0]);
if (ceil(corners[i].f[1]) > out.y2)
out.y2 = ceil(corners[i].f[1]);
}
return out;
}
/** Transform a region by a matrix, restricted to axis-aligned transformations
/** Transform a region by a matrix
*
* Warning: This function does not work for projective, affine, or matrices
* that encode arbitrary rotations. Only 90-degree step rotations are
* supported.
* Warning: This function does not work perfectly for projective,
* affine, or matrices that encode arbitrary rotations. Only 90-degree
* step rotations are exact.
*
* More complicated matrices result in some expansion.
*/
WL_EXPORT void
weston_matrix_transform_region(pixman_region32_t *dest,
......@@ -792,196 +723,24 @@ weston_matrix_transform_region(pixman_region32_t *dest,
if (!dest_rects)
return;
for (i = 0; i < nrects; i++) {
struct weston_vector vec1 = {{
src_rects[i].x1, src_rects[i].y1, 0, 1
}};
weston_matrix_transform(matrix, &vec1);
vec1.f[0] /= vec1.f[3];
vec1.f[1] /= vec1.f[3];
struct weston_vector vec2 = {{
src_rects[i].x2, src_rects[i].y2, 0, 1
}};
weston_matrix_transform(matrix, &vec2);
vec2.f[0] /= vec2.f[3];
vec2.f[1] /= vec2.f[3];
if (vec1.f[0] < vec2.f[0]) {
dest_rects[i].x1 = floor(vec1.f[0]);
dest_rects[i].x2 = ceil(vec2.f[0]);
} else {
dest_rects[i].x1 = floor(vec2.f[0]);
dest_rects[i].x2 = ceil(vec1.f[0]);
}
if (vec1.f[1] < vec2.f[1]) {
dest_rects[i].y1 = floor(vec1.f[1]);
dest_rects[i].y2 = ceil(vec2.f[1]);
} else {
dest_rects[i].y1 = floor(vec2.f[1]);
dest_rects[i].y2 = ceil(vec1.f[1]);
}
}
pixman_region32_clear(dest);
pixman_region32_init_rects(dest, dest_rects, nrects);
free(dest_rects);
}
/** Transform a region to buffer coordinates
*
* \param width Surface width.
* \param height Surface height.
* \param transform Buffer transform.
* \param scale Buffer scale.
* \param[in] src Region in surface coordinates.
* \param[out] dest Resulting region in buffer coordinates.
*
* Converts the given surface-local region to buffer coordinates
* according to the given buffer transform and scale.
* This ignores wp_viewport.
*
* The given width and height must be the result of inverse scaled and
* inverse transformed buffer size.
*
* src and dest are allowed to point to the same memory for in-place conversion.
*/
WL_EXPORT void
weston_transformed_region(int width, int height,
enum wl_output_transform transform,
int32_t scale,
pixman_region32_t *src, pixman_region32_t *dest)
{
pixman_box32_t *src_rects, *dest_rects;
int nrects, i;
if (transform == WL_OUTPUT_TRANSFORM_NORMAL && scale == 1) {
if (src != dest)
pixman_region32_copy(dest, src);
return;
}
src_rects = pixman_region32_rectangles(src, &nrects);
dest_rects = malloc(nrects * sizeof(*dest_rects));
if (!dest_rects)
return;
if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
memcpy(dest_rects, src_rects, nrects * sizeof(*dest_rects));
} else {
for (i = 0; i < nrects; i++) {
switch (transform) {
default:
case WL_OUTPUT_TRANSFORM_NORMAL:
dest_rects[i].x1 = src_rects[i].x1;
dest_rects[i].y1 = src_rects[i].y1;
dest_rects[i].x2 = src_rects[i].x2;
dest_rects[i].y2 = src_rects[i].y2;
break;
case WL_OUTPUT_TRANSFORM_90:
dest_rects[i].x1 = src_rects[i].y1;
dest_rects[i].y1 = width - src_rects[i].x2;
dest_rects[i].x2 = src_rects[i].y2;
dest_rects[i].y2 = width - src_rects[i].x1;
break;
case WL_OUTPUT_TRANSFORM_180:
dest_rects[i].x1 = width - src_rects[i].x2;
dest_rects[i].y1 = height - src_rects[i].y2;
dest_rects[i].x2 = width - src_rects[i].x1;
dest_rects[i].y2 = height - src_rects[i].y1;
break;
case WL_OUTPUT_TRANSFORM_270:
dest_rects[i].x1 = height - src_rects[i].y2;
dest_rects[i].y1 = src_rects[i].x1;
dest_rects[i].x2 = height - src_rects[i].y1;
dest_rects[i].y2 = src_rects[i].x2;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED:
dest_rects[i].x1 = width - src_rects[i].x2;
dest_rects[i].y1 = src_rects[i].y1;
dest_rects[i].x2 = width - src_rects[i].x1;
dest_rects[i].y2 = src_rects[i].y2;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
dest_rects[i].x1 = src_rects[i].y1;
dest_rects[i].y1 = src_rects[i].x1;
dest_rects[i].x2 = src_rects[i].y2;
dest_rects[i].y2 = src_rects[i].x2;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
dest_rects[i].x1 = src_rects[i].x1;
dest_rects[i].y1 = height - src_rects[i].y2;
dest_rects[i].x2 = src_rects[i].x2;
dest_rects[i].y2 = height - src_rects[i].y1;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
dest_rects[i].x1 = height - src_rects[i].y2;
dest_rects[i].y1 = width - src_rects[i].x2;
dest_rects[i].x2 = height - src_rects[i].y1;
dest_rects[i].y2 = width - src_rects[i].x1;
break;
}
}
}
if (scale != 1) {
for (i = 0; i < nrects; i++) {
dest_rects[i].x1 *= scale;
dest_rects[i].x2 *= scale;
dest_rects[i].y1 *= scale;
dest_rects[i].y2 *= scale;
}
}
for (i = 0; i < nrects; i++)
dest_rects[i] = weston_matrix_transform_rect(matrix, src_rects[i]);
pixman_region32_clear(dest);
pixman_region32_init_rects(dest, dest_rects, nrects);
free(dest_rects);
}
static void
viewport_surface_to_buffer(struct weston_surface *surface,
float sx, float sy, float *bx, float *by)
{
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) {
*bx = sx;
*by = sy;
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);
}
*bx = sx * src_width / surface->width + src_x;
*by = sy * src_height / surface->height + src_y;
}
WL_EXPORT void
weston_surface_to_buffer_float(struct weston_surface *surface,
float sx, float sy, float *bx, float *by)
{
struct weston_buffer_viewport *vp = &surface->buffer_viewport;
struct weston_vector v = {{sx, sy, 0.0, 1.0}};
/* first transform coordinates if the viewport is set */
viewport_surface_to_buffer(surface, sx, sy, bx, by);
weston_matrix_transform(&surface->surface_to_buffer_matrix, &v);
weston_transformed_coord(surface->width_from_buffer,
surface->height_from_buffer,
vp->buffer.transform, vp->buffer.scale,
*bx, *by, bx, by);
*bx = v.f[0] / v.f[3];
*by = v.f[1] / v.f[3];
}
/** Transform a rectangle from surface coordinates to buffer coordinates
......@@ -1006,22 +765,8 @@ WL_EXPORT pixman_box32_t
weston_surface_to_buffer_rect(struct weston_surface *surface,
pixman_box32_t rect)
{
struct weston_buffer_viewport *vp = &surface->buffer_viewport;
float xf, yf;
/* first transform box coordinates if the viewport is set */
viewport_surface_to_buffer(surface, rect.x1, rect.y1, &xf, &yf);
rect.x1 = floorf(xf);
rect.y1 = floorf(yf);
viewport_surface_to_buffer(surface, rect.x2, rect.y2, &xf, &yf);
rect.x2 = ceilf(xf);
rect.y2 = ceilf(yf);
return weston_transformed_rect(surface->width_from_buffer,
surface->height_from_buffer,
vp->buffer.transform, vp->buffer.scale,
rect);
return weston_matrix_transform_rect(&surface->surface_to_buffer_matrix,
rect);
}
/** Transform a region from surface coordinates to buffer coordinates
......@@ -6457,10 +6202,11 @@ weston_compositor_reflow_outputs(struct weston_compositor *compositor,
}
}
/** Transform a region in-place from global to output coordinates
/** Transform a region from global to output coordinates
*
* \param dst The region transformed into output coordinates
* \param output The output that defines the transformation.
* \param region The region to be transformed in-place.
* \param src The region to be transformed, in global coordinates.
*
* This takes a region in the global coordinate system, and takes into account
* output position, transform and scale, and converts the region into output
......@@ -6470,14 +6216,11 @@ weston_compositor_reflow_outputs(struct weston_compositor *compositor,
* \ingroup output
*/
WL_EXPORT void
weston_output_region_from_global(struct weston_output *output,
pixman_region32_t *region)
{
pixman_region32_translate(region, -output->x, -output->y);
weston_transformed_region(output->width, output->height,
output->transform,
output->current_scale,
region, region);
weston_region_global_to_output(pixman_region32_t *dst,
struct weston_output *output,
pixman_region32_t *src)
{
weston_matrix_transform_region(dst, &output->matrix, src);
}
static void
......
......@@ -333,21 +333,9 @@ void
weston_view_move_to_plane(struct weston_view *view,
struct weston_plane *plane);
void
weston_transformed_coord(int width, int height,
enum wl_output_transform transform,
int32_t scale,
float sx, float sy, float *bx, float *by);
pixman_box32_t
weston_transformed_rect(int width, int height,
enum wl_output_transform transform,
int32_t scale,
pixman_box32_t rect);
void
weston_transformed_region(int width, int height,
enum wl_output_transform transform,
int32_t scale,
pixman_region32_t *src, pixman_region32_t *dest);
weston_matrix_transform_rect(struct weston_matrix *matrix,
pixman_box32_t rect);
void
weston_matrix_transform_region(pixman_region32_t *dest,
struct weston_matrix *matrix,
......
......@@ -414,8 +414,9 @@ draw_view_translated(struct weston_view *view, struct weston_output *output,
repaint_global,
&surface->opaque,
view);
weston_output_region_from_global(output,
&repaint_output);
weston_region_global_to_output(&repaint_output,
output,
&repaint_output);
repaint_region(view, output, &repaint_output, NULL,
PIXMAN_OP_SRC);
......@@ -426,7 +427,9 @@ draw_view_translated(struct weston_view *view, struct weston_output *output,
region_intersect_only_translation(&repaint_output,
repaint_global,
&surface_blend, view);
weston_output_region_from_global(output, &repaint_output);
weston_region_global_to_output(&repaint_output,
output,
&repaint_output);
repaint_region(view, output, &repaint_output, NULL,
PIXMAN_OP_OVER);
......@@ -462,7 +465,8 @@ draw_view_source_clipped(struct weston_view *view,
pixman_region32_init(&repaint_output);
pixman_region32_copy(&repaint_output, repaint_global);
weston_output_region_from_global(output, &repaint_output);
weston_region_global_to_output(&repaint_output, output,
&repaint_output);
repaint_region(view, output, &repaint_output, &buffer_region,
PIXMAN_OP_OVER);
......@@ -555,7 +559,7 @@ copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region)
pixman_region32_init(&output_region);
pixman_region32_copy(&output_region, region);
weston_output_region_from_global(output, &output_region);
weston_region_global_to_output(&output_region, output, &output_region);
pixman_image_set_clip_region32 (po->hw_buffer, &output_region);
pixman_region32_fini(&output_region);
......
......@@ -1447,12 +1447,9 @@ pixman_region_to_egl_y_invert(struct weston_output *output,
/* Translate from global to output co-ordinate space. */
pixman_region32_init(&transformed);
pixman_region32_copy(&transformed, global_region);
pixman_region32_translate(&transformed, -output->x, -output->y);
weston_transformed_region(output->width, output->height,
output->transform,
output->current_scale,
&transformed, &transformed);
weston_region_global_to_output(&transformed,
output,
global_region);
/* If we have borders drawn around the output, shift our output damage
* to account for borders being drawn around the outside, adding any
......@@ -1534,7 +1531,8 @@ blit_shadow_to_output(struct weston_output *output,
pixman_region32_intersect(&translated_damage, output_damage,
&output->region);
/* Convert to output pixel coordinates in-place */
weston_output_region_from_global(output, &translated_damage);
weston_region_global_to_output(&translated_damage, output,
&translated_damage);
rects = pixman_region32_rectangles(&translated_damage, &n_rects);
for (i = 0; i < n_rects; i++) {
......
......@@ -287,10 +287,9 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
pixman_region32_init(&damage);
pixman_region32_init(&transformed_damage);
pixman_region32_intersect(&damage, &output->region, data);
pixman_region32_translate(&damage, -output->x, -output->y);
weston_transformed_region(output->width, output->height,
output->transform, output->current_scale,
&damage, &transformed_damage);
weston_region_global_to_output(&transformed_damage,
output,
&damage);
pixman_region32_fini(&damage);
r = pixman_region32_rectangles(&transformed_damage, &n);
......