On Wed, May 21, 2014 at 07:36:21PM +0100, Neil Roberts wrote: > Previously if the output had a transform then the cursor plane would > be disabled. However as we have to copy the cursor image into a buffer > with the CPU anyway it probably won't cost much extra to also apply > the transform in the process and then we can avoid disabling the > plane. > > If the transform is either normal or flipped-180 then a slightly > faster path is used that still copies the lines one at a time with > memcpy. Otherwise there is a slower path which copies one pixel at a > time. > > Previously the check for whether to disable the plane was only looking > at whether the output has a transform. However it should probably have > also been disabled if the surface has a transform. This patch changes > it to just look at the surface transform instead. It could be possible > to work out a relative transform and apply that so that any > combinations of transforms will work, but this patch doesn't attempt > that.
Could we just use pixman here? We could also scale up the cursor image when possible with that. Kristian > --- > src/compositor-drm.c | 120 > ++++++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 113 insertions(+), 7 deletions(-) > > diff --git a/src/compositor-drm.c b/src/compositor-drm.c > index 7d514e4..553454d 100644 > --- a/src/compositor-drm.c > +++ b/src/compositor-drm.c > @@ -958,7 +958,7 @@ drm_output_prepare_cursor_view(struct weston_output > *output_base, > > if (c->gbm == NULL) > return NULL; > - if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL) > + if (viewport->buffer.transform != WL_OUTPUT_TRANSFORM_NORMAL) > return NULL; > if (viewport->buffer.scale != output_base->current_scale) > return NULL; > @@ -979,6 +979,102 @@ drm_output_prepare_cursor_view(struct weston_output > *output_base, > } > > static void > +transform_cursor_buffer_slow(enum wl_output_transform transform, > + uint32_t *buf, > + unsigned char *s, > + int32_t width, > + int32_t height, > + int stride) > +{ > + int angle = transform & 3; > + int swap_xy = transform & 1; > + int flip_x, flip_y; > + int buf_x_increment, buf_y_increment; > + int s_y_increment; > + int sx, sy; > + > + /* Flip here means we flip the direction of the destination > + * iterators */ > + flip_x = (angle & 1) ^ (angle >> 1); > + flip_y = (angle >> 1); > + > + if (swap_xy) { > + if (transform & 4) > + flip_y = !flip_y; > + > + if (flip_y) { > + buf += (width - 1) * 64; > + buf_x_increment = -64; > + } else { > + buf_x_increment = 64; > + } > + > + if (flip_x) { > + buf += height - 1; > + buf_y_increment = -1 - buf_x_increment * width; > + } else { > + buf_y_increment = 1 - buf_x_increment * width; > + } > + } else { > + if (transform & 4) > + flip_x = !flip_x; > + > + if (flip_x) { > + buf += width - 1; > + buf_x_increment = -1; > + } else { > + buf_x_increment = 1; > + } > + > + if (flip_y) { > + buf += (height - 1) * 64; > + buf_y_increment = -64 - buf_x_increment * width; > + } else { > + buf_y_increment = 64 - buf_x_increment * width; > + } > + } > + > + s_y_increment = stride - width * 4; > + > + for (sy = 0; sy < height; sy++) { > + for (sx = 0; sx < width; sx++) { > + memcpy(buf, s, 4); > + s += 4; > + buf += buf_x_increment; > + } > + s += s_y_increment; > + buf += buf_y_increment; > + } > +} > + > +static void > +transform_cursor_buffer(enum wl_output_transform transform, > + uint32_t *buf, > + unsigned char *s, > + int32_t width, > + int32_t height, > + int stride) > +{ > + int y; > + > + switch (transform) { > + case WL_OUTPUT_TRANSFORM_NORMAL: > + for (y = 0; y < height; y++) > + memcpy(buf + y * 64, s + y * stride, width * 4); > + break; > + case WL_OUTPUT_TRANSFORM_FLIPPED_180: > + for (y = 0; y < height; y++) > + memcpy(buf + y * 64, s + (height - 1 - y) * stride, > + width * 4); > + break; > + default: > + transform_cursor_buffer_slow(transform, > + buf, s, width, height, stride); > + break; > + } > +} > + > +static void > drm_output_set_cursor(struct drm_output *output) > { > struct weston_view *ev = output->cursor_view; > @@ -989,7 +1085,8 @@ drm_output_set_cursor(struct drm_output *output) > struct gbm_bo *bo; > uint32_t buf[64 * 64]; > unsigned char *s; > - int i, x, y; > + int x, y; > + pixman_box32_t cursor_rect; > > output->cursor_view = NULL; > if (ev == NULL) { > @@ -1009,9 +1106,9 @@ drm_output_set_cursor(struct drm_output *output) > stride = wl_shm_buffer_get_stride(buffer->shm_buffer); > s = wl_shm_buffer_get_data(buffer->shm_buffer); > wl_shm_buffer_begin_access(buffer->shm_buffer); > - for (i = 0; i < ev->surface->height; i++) > - memcpy(buf + i * 64, s + i * stride, > - ev->surface->width * 4); > + transform_cursor_buffer(output->base.transform, > + buf, s, ev->surface->width, > + ev->surface->height, stride); > wl_shm_buffer_end_access(buffer->shm_buffer); > > if (gbm_bo_write(bo, buf, sizeof buf) < 0) > @@ -1025,8 +1122,17 @@ drm_output_set_cursor(struct drm_output *output) > } > } > > - x = (ev->geometry.x - output->base.x) * output->base.current_scale; > - y = (ev->geometry.y - output->base.y) * output->base.current_scale; > + cursor_rect.x1 = ev->geometry.x - output->base.x; > + cursor_rect.y1 = ev->geometry.y - output->base.y; > + cursor_rect.x2 = cursor_rect.x1 + ev->surface->width; > + cursor_rect.y2 = cursor_rect.y1 + ev->surface->height; > + cursor_rect = weston_transformed_rect(output->base.width, > + output->base.height, > + output->base.transform, > + output->base.current_scale, > + cursor_rect); > + x = roundf(MIN(cursor_rect.x1, cursor_rect.x2)); > + y = roundf(MIN(cursor_rect.y1, cursor_rect.y2)); > if (output->cursor_plane.x != x || output->cursor_plane.y != y) { > if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y)) { > weston_log("failed to move cursor: %m\n"); > -- > 1.9.0 > > _______________________________________________ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel