From: Junghoon Date: Sun, 18 Oct 2015 05:47:32 +0000 (+0900) Subject: pepper: pointer cursor implementation X-Git-Tag: submit/tizen/20151221.025226~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0dafc4753529307a10a80da3b026e24e45ea8d5e;p=platform%2Fcore%2Fuifw%2Fpepper.git pepper: pointer cursor implementation - implement wl_pointer::set_cursor - implement drm_cursor Change-Id: I45aac2e96b176a8480307a4465782c255e4ca2be --- diff --git a/src/lib/desktop-shell/desktop-shell-internal.h b/src/lib/desktop-shell/desktop-shell-internal.h index cf46bea..bd5c933 100644 --- a/src/lib/desktop-shell/desktop-shell-internal.h +++ b/src/lib/desktop-shell/desktop-shell-internal.h @@ -236,6 +236,9 @@ shell_surface_set_next_type(shell_surface_t *shsurf, shell_surface_type_t new_ty void shell_surface_set_parent(shell_surface_t *shsurf, pepper_surface_t *parent); +void +shell_surface_stack_top(shell_surface_t *shsurf, pepper_bool_t subtree); + /* */ shell_surface_t * get_shsurf_from_surface(pepper_surface_t *surface, desktop_shell_t *shell); diff --git a/src/lib/desktop-shell/shell-surface.c b/src/lib/desktop-shell/shell-surface.c index 2a74783..2ad6d6e 100644 --- a/src/lib/desktop-shell/shell-surface.c +++ b/src/lib/desktop-shell/shell-surface.c @@ -721,6 +721,27 @@ shell_surface_set_position(shell_surface_t *shsurf, double x, double y) } +void +shell_surface_stack_top(shell_surface_t *shsurf, pepper_bool_t subtree) +{ + pepper_view_t *cursor_view; + pepper_pointer_t *pointer; + shell_seat_t *shseat; + + pepper_view_stack_top(shsurf->view, subtree); + + pepper_list_for_each(shseat, &shsurf->shell->shseat_list, link) + { + pointer = pepper_seat_get_pointer(shseat->seat); + if (pointer) + { + cursor_view = pepper_pointer_get_cursor_view(pointer); + if (cursor_view) + pepper_view_stack_top(cursor_view, PEPPER_FALSE); + } + } +} + shell_surface_t * get_shsurf_from_surface(pepper_surface_t *surface, desktop_shell_t *shell) { @@ -1073,7 +1094,7 @@ shell_surface_map_popup(shell_surface_t *shsurf) pepper_view_map(shsurf->view); - pepper_view_stack_top(shsurf->view, PEPPER_TRUE); + shell_surface_stack_top(shsurf, PEPPER_TRUE); shell_surface_add_popup_grab(shsurf); } @@ -1112,7 +1133,7 @@ shell_surface_map_maximized(shell_surface_t *shsurf) pepper_view_map(shsurf->view); /* Set top of z-order */ - pepper_view_stack_top(shsurf->view, PEPPER_TRUE /*FIXME:*/); + shell_surface_stack_top(shsurf, PEPPER_TRUE /*FIXME:*/); } static void @@ -1215,7 +1236,7 @@ shell_surface_map_fullscreen(shell_surface_t *shsurf) shell_surface_place_fullscreen_surface(shsurf); pepper_view_map(shsurf->view); - pepper_view_stack_top(shsurf->view, PEPPER_TRUE /*FIXME*/ ); + shell_surface_stack_top(shsurf, PEPPER_TRUE /*FIXME*/ ); } void diff --git a/src/lib/desktop-shell/shell.c b/src/lib/desktop-shell/shell.c index baedc2a..b07cbc2 100644 --- a/src/lib/desktop-shell/shell.c +++ b/src/lib/desktop-shell/shell.c @@ -163,7 +163,14 @@ default_pointer_grab_button(pepper_pointer_t *pointer, void *data, } if (pointer_focus) - pepper_view_stack_top(pointer_focus, PEPPER_FALSE); + { + shell_seat_t *shseat = data; + desktop_shell_t *shell = shseat->shell; + pepper_surface_t *surface = pepper_view_get_surface(pointer_focus); + shell_surface_t *shsurf = get_shsurf_from_surface(surface, shell); + + shell_surface_stack_top(shsurf, PEPPER_FALSE); + } } pepper_pointer_send_button(pointer, pointer_focus, time, button, state); @@ -195,7 +202,7 @@ pointer_add_callback(pepper_event_listener_t *listener, pepper_object_t *object, void *info, void *data) { pepper_pointer_t *pointer = info; - pepper_pointer_set_grab(pointer, &default_pointer_grab, NULL); + pepper_pointer_set_grab(pointer, &default_pointer_grab, data); } static void diff --git a/src/lib/drm/drm-common.c b/src/lib/drm/drm-common.c index 856878c..398e9ac 100644 --- a/src/lib/drm/drm-common.c +++ b/src/lib/drm/drm-common.c @@ -258,6 +258,12 @@ pepper_drm_create(pepper_compositor_t *compositor, struct udev *udev, const char drm->resources = drmModeGetResources(drm->fd); PEPPER_CHECK(drm->resources, goto error, "drmModeGetResources() failed.\n"); + ret = drmGetCap(drm->fd, 0x8 /* DRM_CAP_CURSOR_WIDTH */, &cap); + drm->cursor_width = (ret == 0) ? cap : 64; + + ret = drmGetCap(drm->fd, 0x9 /* DRM_CAP_CURSOR_HEIGHT */, &cap); + drm->cursor_height = (ret == 0) ? cap : 64; + drm_init_planes(drm); drm_init_connectors(drm); udev_device_unref(udev_device); diff --git a/src/lib/drm/drm-internal.h b/src/lib/drm/drm-internal.h index 4cea181..a0e6198 100644 --- a/src/lib/drm/drm-internal.h +++ b/src/lib/drm/drm-internal.h @@ -84,6 +84,10 @@ struct pepper_drm #endif pepper_renderer_t *pixman_renderer; pepper_renderer_t *gl_renderer; + + pepper_bool_t cursor_broken; + int32_t cursor_width; + int32_t cursor_height; }; struct drm_connector @@ -159,6 +163,13 @@ struct drm_output pepper_bool_t page_flip_pending; int vblank_pending_count; + pepper_view_t *cursor_view; + pepper_buffer_t *cursor_buffer; + struct gbm_bo *cursor_bo[2]; + int cursor_bo_index; + int cursor_x, cursor_y; + pepper_bool_t need_set_cursor; + pepper_plane_t *cursor_plane; pepper_plane_t *primary_plane; pepper_plane_t *fb_plane; diff --git a/src/lib/drm/drm-output.c b/src/lib/drm/drm-output.c index ba443b6..0e75cfd 100644 --- a/src/lib/drm/drm-output.c +++ b/src/lib/drm/drm-output.c @@ -137,8 +137,41 @@ drm_output_set_mode(void *o, const pepper_output_mode_t *mode) static pepper_plane_t * assign_cursor_plane(drm_output_t *output, pepper_view_t *view) { - /* TODO: */ - return NULL; + int32_t w, h; + pepper_surface_t *surface; + pepper_buffer_t *buffer; + struct wl_resource *resource; + + if (output->cursor_view) + return NULL; + + if (!output->drm->gbm_device) + return NULL; + + if (output->drm->cursor_broken) + return NULL; + + pepper_view_get_size(view, &w, &h); + if ((output->drm->cursor_width < w) || (output->drm->cursor_height < h)) + return NULL; + + surface = pepper_view_get_surface(view); + buffer = pepper_surface_get_buffer(surface); + if (!buffer) + return NULL; + + resource = pepper_buffer_get_resource(buffer); + if (!resource || !wl_shm_buffer_get(resource)) + return NULL; + + output->cursor_view = view; + if (output->cursor_buffer != buffer) + { + output->cursor_buffer = buffer; + output->need_set_cursor = PEPPER_TRUE; + } + + return output->cursor_plane; } static pepper_plane_t * @@ -452,6 +485,79 @@ drm_output_start_repaint_loop(void *o) pepper_output_finish_frame(output->base, &ts); } +static void +drm_output_set_cursor(drm_output_t *output) +{ + pepper_drm_t *drm = output->drm; + pepper_surface_t *surface; + pepper_buffer_t *buffer; + + double x, y; + + if (!output->cursor_view) + { + drmModeSetCursor(drm->fd, output->crtc_id, 0, 0, 0); + return; + } + + surface = pepper_view_get_surface(output->cursor_view); + buffer = pepper_surface_get_buffer(surface); + + if (buffer && output->need_set_cursor) + { + + int32_t i, w, h, stride; + uint8_t *data; + uint32_t buf[drm->cursor_width * drm->cursor_height]; + + struct gbm_bo *bo; + struct wl_resource *resource; + struct wl_shm_buffer *shm_buffer; + + resource = pepper_buffer_get_resource(buffer); + + shm_buffer = wl_shm_buffer_get(resource); + stride = wl_shm_buffer_get_stride(shm_buffer); + data = wl_shm_buffer_get_data(shm_buffer); + + pepper_view_get_size(output->cursor_view, &w, &h); + + memset(buf, 0, sizeof(buf)); + wl_shm_buffer_begin_access(shm_buffer); + for (i = 0; i < h; i++) + memcpy(buf + i * drm->cursor_width, data + i * stride, w * sizeof(uint32_t)); + wl_shm_buffer_end_access(shm_buffer); + + output->cursor_bo_index ^= 1; + bo = output->cursor_bo[output->cursor_bo_index]; + gbm_bo_write(bo, buf, sizeof(buf)); + + if (drmModeSetCursor(drm->fd, output->crtc_id, gbm_bo_get_handle(bo).s32, + drm->cursor_width, drm->cursor_height)) + { + PEPPER_TRACE("failed to set cursor\n"); + drm->cursor_broken = PEPPER_TRUE; + } + + output->need_set_cursor = PEPPER_FALSE; + } + + pepper_view_get_position(output->cursor_view, &x, &y); + if ((output->cursor_x != (int)x) || (output->cursor_y != (int)y)) + { + if (drmModeMoveCursor(drm->fd, output->crtc_id, (int)x, (int)y)) + { + PEPPER_TRACE("failed to move cursor\n"); + drm->cursor_broken = PEPPER_TRUE; + } + + output->cursor_x = (int)x; + output->cursor_y = (int)y; + } + + output->cursor_view = NULL; +} + static void drm_output_repaint(void *o, const pepper_list_t *plane_list) { @@ -480,6 +586,8 @@ drm_output_repaint(void *o, const pepper_list_t *plane_list) output->page_flip_pending = PEPPER_TRUE; } + drm_output_set_cursor(output); + pepper_list_for_each(plane, &output->drm->plane_list, link) { drmVBlank vbl; @@ -532,15 +640,26 @@ drm_output_flush_surface_damage(void *o, pepper_surface_t *surface, pepper_bool_ pepper_renderer_flush_surface_damage(output->renderer, surface); - if (output->render_type == DRM_RENDER_TYPE_PIXMAN || - (buffer && !wl_shm_buffer_get(pepper_buffer_get_resource(buffer)))) - { - *keep_buffer = PEPPER_TRUE; - } - else + if (output->render_type == DRM_RENDER_TYPE_PIXMAN) + goto keep; + + if (buffer) { - *keep_buffer = PEPPER_FALSE; + int w, h; + + if (!wl_shm_buffer_get(pepper_buffer_get_resource(buffer))) + goto keep; + + pepper_buffer_get_size(buffer, &w, &h); + if ((w <= output->drm->cursor_width) && (h <= output->drm->cursor_height)) + goto keep; } + + *keep_buffer = PEPPER_FALSE; + return; + +keep: + *keep_buffer = PEPPER_TRUE; } struct pepper_output_backend drm_output_backend = @@ -776,6 +895,22 @@ drm_output_create(drm_connector_t *conn) if (use_overlay_env && strcmp(use_overlay_env, "1") == 0) output->use_overlay = PEPPER_TRUE; + if (drm->gbm_device) + { + int i; + + for (i = 0; i < 2; i++) + output->cursor_bo[i] = gbm_bo_create(drm->gbm_device, + drm->cursor_width, drm->cursor_height, + GBM_FORMAT_ARGB8888, + GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); + if (!output->cursor_bo[0] || !output->cursor_bo[1]) + { + PEPPER_TRACE("failed to create cursor bo\n"); + drm->cursor_broken = PEPPER_TRUE; + } + } + output->primary_plane = pepper_output_add_plane(output->base, NULL); PEPPER_CHECK(output->primary_plane, goto error, "pepper_output_add_plane() failed.\n"); @@ -817,6 +952,7 @@ error: void drm_output_destroy(void *o) { + int i; drm_output_t *output = o; drm_plane_t *plane; @@ -826,6 +962,12 @@ drm_output_destroy(void *o) return; } + for (i = 0; i < 2; i++) + { + if (output->cursor_bo[i]) + gbm_bo_destroy(output->cursor_bo[i]); + } + if (output->render_type == DRM_RENDER_TYPE_PIXMAN) fini_pixman_renderer(output); else if (output->render_type == DRM_RENDER_TYPE_GL) diff --git a/src/lib/pepper/pepper-internal.h b/src/lib/pepper/pepper-internal.h index 2255a83..83c2917 100644 --- a/src/lib/pepper/pepper-internal.h +++ b/src/lib/pepper/pepper-internal.h @@ -205,6 +205,7 @@ struct pepper_surface pixman_region32_t damage_region; pixman_region32_t opaque_region; pixman_region32_t input_region; + pepper_bool_t pickable; struct wl_list frame_callback_list; @@ -352,6 +353,10 @@ struct pepper_pointer double x_velocity; double y_velocity; + + pepper_view_t *cursor_view; + int32_t hotspot_x; + int32_t hotspot_y; }; pepper_pointer_t * diff --git a/src/lib/pepper/pepper.h b/src/lib/pepper/pepper.h index f0389c5..bcaaf43 100644 --- a/src/lib/pepper/pepper.h +++ b/src/lib/pepper/pepper.h @@ -1046,6 +1046,12 @@ pepper_pointer_get_grab(pepper_pointer_t *pointer); PEPPER_API void * pepper_pointer_get_grab_data(pepper_pointer_t *pointer); +PEPPER_API pepper_view_t * +pepper_pointer_get_cursor_view(pepper_pointer_t *pointer); + +PEPPER_API void +pepper_pointer_set_hotspot(pepper_pointer_t *pointer, int32_t x, int32_t y); + /* Keyboard. */ struct pepper_keyboard_grab { diff --git a/src/lib/pepper/pointer.c b/src/lib/pepper/pointer.c index f9621a3..fac1ed2 100644 --- a/src/lib/pepper/pointer.c +++ b/src/lib/pepper/pointer.c @@ -29,11 +29,52 @@ #include "pepper-internal.h" #include +static pepper_view_t * +get_cursor_view(pepper_pointer_t *pointer) +{ + if (pointer->cursor_view) + return pointer->cursor_view; + + pointer->cursor_view = pepper_compositor_add_view(pointer->seat->compositor); + + return pointer->cursor_view; +} + static void pointer_set_cursor(struct wl_client *client, struct wl_resource *resource, uint32_t serial, struct wl_resource *surface_resource, int32_t x, int32_t y) { - /* TODO: */ + pepper_pointer_t *pointer = (pepper_pointer_t *)wl_resource_get_user_data(resource); + pepper_surface_t *surface; + pepper_view_t *cursor_view; + + cursor_view = get_cursor_view(pointer); + PEPPER_CHECK(cursor_view, return, "failed to get cursor view\n"); + + if (!surface_resource) + { + pepper_view_set_surface(cursor_view, NULL); + return; + } + + surface = (pepper_surface_t *)wl_resource_get_user_data(surface_resource); + if (!surface->role) + pepper_surface_set_role(surface, "wl_pointer-cursor"); + else if (strcmp("wl_pointer-cursor", surface->role)) + return; + + if (surface != pepper_view_get_surface(cursor_view)) + { + surface->pickable = PEPPER_FALSE; + pixman_region32_fini(&surface->input_region); + pixman_region32_init(&surface->input_region); + pepper_view_set_surface(cursor_view, surface); + } + + pointer->hotspot_x = x; + pointer->hotspot_y = y; + pepper_view_set_position(cursor_view, pointer->x - x, pointer->y - y); + pepper_view_map(cursor_view); } static void @@ -93,6 +134,10 @@ pointer_set_position(pepper_pointer_t *pointer, uint32_t time, double x, double pointer_clamp(pointer); + if (pointer->cursor_view) + pepper_view_set_position(pointer->cursor_view, + x - pointer->hotspot_x, y - pointer->hotspot_y); + if (pointer->grab) pointer->grab->motion(pointer, pointer->data, time, pointer->x, pointer->y); @@ -652,3 +697,16 @@ pepper_pointer_get_grab_data(pepper_pointer_t *pointer) { return pointer->data; } + +PEPPER_API pepper_view_t * +pepper_pointer_get_cursor_view(pepper_pointer_t *pointer) +{ + return pointer->cursor_view; +} + +PEPPER_API void +pepper_pointer_set_hotspot(pepper_pointer_t *pointer, int32_t x, int32_t y) +{ + pointer->hotspot_x = x; + pointer->hotspot_y = y; +} diff --git a/src/lib/pepper/surface.c b/src/lib/pepper/surface.c index 9377acd..62b9959 100644 --- a/src/lib/pepper/surface.c +++ b/src/lib/pepper/surface.c @@ -327,6 +327,7 @@ pepper_surface_create(pepper_compositor_t *compositor, pixman_region32_init(&surface->damage_region); pixman_region32_init(&surface->opaque_region); pixman_region32_init_rect(&surface->input_region, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); + surface->pickable = PEPPER_TRUE; wl_list_init(&surface->frame_callback_list); pepper_list_init(&surface->view_list); @@ -453,7 +454,9 @@ pepper_surface_commit_state(pepper_surface_t *surface, pepper_surface_state_t *s /* surface.set_opaque_region(), surface.set_input_region(). */ pixman_region32_copy(&surface->opaque_region, &state->opaque_region); - pixman_region32_copy(&surface->input_region, &state->input_region); + + if (surface->pickable) + pixman_region32_copy(&surface->input_region, &state->input_region); pepper_list_for_each(view, &surface->view_list, surface_link) {