Make use of a hardware cursor in compositor-drm
This commit is contained in:
+109
-1
@@ -179,6 +179,68 @@ drm_output_image_is_scanoutable(struct wlsc_output *output_base,
|
|||||||
return fb_id != 0;
|
return fb_id != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_output_set_cursor(struct wlsc_output *output_base,
|
||||||
|
struct wl_input_device *input)
|
||||||
|
{
|
||||||
|
struct drm_output *output = (struct drm_output *) output_base;
|
||||||
|
struct drm_compositor *c =
|
||||||
|
(struct drm_compositor *) output->base.compositor;
|
||||||
|
struct wlsc_input_device *eid = (struct wlsc_input_device *) input;
|
||||||
|
EGLint handle, stride;
|
||||||
|
int ret = -1;
|
||||||
|
pixman_region32_t cursor_region;
|
||||||
|
|
||||||
|
pixman_region32_init_rect(&cursor_region,
|
||||||
|
eid->sprite->x, eid->sprite->y,
|
||||||
|
eid->sprite->width, eid->sprite->height);
|
||||||
|
|
||||||
|
pixman_region32_intersect_rect(&cursor_region, &cursor_region,
|
||||||
|
output->base.x, output->base.y,
|
||||||
|
output->base.width, output->base.height);
|
||||||
|
|
||||||
|
if (!pixman_region32_not_empty(&cursor_region)) {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eid->sprite->image == EGL_NO_IMAGE_KHR)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (eid->sprite->width > 64 || eid->sprite->height > 64)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
eglExportDRMImageMESA(c->base.display, eid->sprite->image,
|
||||||
|
NULL, &handle, &stride);
|
||||||
|
|
||||||
|
if (stride != 64 * 4) {
|
||||||
|
fprintf(stderr, "info: cursor stride is != 64\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = drmModeSetCursor(c->drm.fd, output->crtc_id, handle, 64, 64);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "failed to set cursor: %s\n", strerror(-ret));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = drmModeMoveCursor(c->drm.fd, output->crtc_id,
|
||||||
|
eid->sprite->x - output->base.x,
|
||||||
|
eid->sprite->y - output->base.y);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "failed to move cursor: %s\n", strerror(-ret));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: set hardware cursor\n");
|
||||||
|
|
||||||
|
out:
|
||||||
|
pixman_region32_fini(&cursor_region);
|
||||||
|
if (ret)
|
||||||
|
drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_drm_input(int fd, uint32_t mask, void *data)
|
on_drm_input(int fd, uint32_t mask, void *data)
|
||||||
{
|
{
|
||||||
@@ -353,6 +415,7 @@ create_output_for_connector(struct drm_compositor *ec,
|
|||||||
output->base.prepare_render = drm_output_prepare_render;
|
output->base.prepare_render = drm_output_prepare_render;
|
||||||
output->base.present = drm_output_present;
|
output->base.present = drm_output_present;
|
||||||
output->base.image_is_scanoutable = drm_output_image_is_scanoutable;
|
output->base.image_is_scanoutable = drm_output_image_is_scanoutable;
|
||||||
|
output->base.set_hardware_cursor = drm_output_set_cursor;
|
||||||
|
|
||||||
wl_list_insert(ec->base.output_list.prev, &output->base.link);
|
wl_list_insert(ec->base.output_list.prev, &output->base.link);
|
||||||
|
|
||||||
@@ -534,6 +597,50 @@ udev_drm_event(int fd, uint32_t mask, void *data)
|
|||||||
udev_device_unref(event);
|
udev_device_unref(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EGLImageKHR
|
||||||
|
drm_compositor_create_cursor_image(struct wlsc_compositor *ec,
|
||||||
|
int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
EGLint image_attribs[] = {
|
||||||
|
EGL_WIDTH, 0,
|
||||||
|
EGL_HEIGHT, 0,
|
||||||
|
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
|
||||||
|
0, 0,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
EGLint stride, name;
|
||||||
|
EGLImageKHR tmp_image, image;
|
||||||
|
|
||||||
|
if (width > 64 || height > 64)
|
||||||
|
return EGL_NO_IMAGE_KHR;
|
||||||
|
|
||||||
|
image_attribs[1] = 64;
|
||||||
|
image_attribs[3] = 64;
|
||||||
|
image_attribs[6] = EGL_DRM_BUFFER_USE_MESA;
|
||||||
|
image_attribs[7] = EGL_DRM_BUFFER_USE_SCANOUT_MESA;
|
||||||
|
|
||||||
|
tmp_image = eglCreateDRMImageMESA(ec->display, image_attribs);
|
||||||
|
|
||||||
|
eglExportDRMImageMESA(ec->display, tmp_image, &name, NULL, &stride);
|
||||||
|
|
||||||
|
if (stride == 64)
|
||||||
|
return tmp_image;
|
||||||
|
|
||||||
|
/* recreate image width stide 64 forced */
|
||||||
|
image_attribs[1] = width;
|
||||||
|
image_attribs[3] = height;
|
||||||
|
image_attribs[6] = EGL_DRM_BUFFER_STRIDE_MESA;
|
||||||
|
image_attribs[7] = 64;
|
||||||
|
|
||||||
|
image = eglCreateImageKHR(ec->display, EGL_NO_CONTEXT, EGL_DRM_BUFFER_MESA,
|
||||||
|
(EGLClientBuffer)(intptr_t) name, image_attribs);
|
||||||
|
eglExportDRMImageMESA(ec->display, image, &name, NULL, &stride);
|
||||||
|
|
||||||
|
eglDestroyImageKHR(ec->display, tmp_image);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drm_destroy(struct wlsc_compositor *ec)
|
drm_destroy(struct wlsc_compositor *ec)
|
||||||
{
|
{
|
||||||
@@ -589,7 +696,8 @@ drm_compositor_create(struct wl_display *display, int connector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ec->base.destroy = drm_destroy;
|
ec->base.destroy = drm_destroy;
|
||||||
ec->base.create_buffer = wlsc_shm_buffer_create;
|
ec->base.create_cursor_image = drm_compositor_create_cursor_image;
|
||||||
|
|
||||||
ec->base.focus = 1;
|
ec->base.focus = 1;
|
||||||
|
|
||||||
glGenFramebuffers(1, &ec->base.fbo);
|
glGenFramebuffers(1, &ec->base.fbo);
|
||||||
|
|||||||
@@ -203,6 +203,13 @@ wayland_output_image_is_scanoutable(struct wlsc_output *output_base,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wayland_output_set_cursor(struct wlsc_output *output_base,
|
||||||
|
struct wl_input_device *input)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wayland_compositor_create_output(struct wayland_compositor *c,
|
wayland_compositor_create_output(struct wayland_compositor *c,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
@@ -254,6 +261,7 @@ wayland_compositor_create_output(struct wayland_compositor *c,
|
|||||||
output->base.prepare_render = wayland_output_prepare_render;
|
output->base.prepare_render = wayland_output_prepare_render;
|
||||||
output->base.present = wayland_output_present;
|
output->base.present = wayland_output_present;
|
||||||
output->base.image_is_scanoutable = wayland_output_image_is_scanoutable;
|
output->base.image_is_scanoutable = wayland_output_image_is_scanoutable;
|
||||||
|
output->base.set_hardware_cursor = wayland_output_set_cursor;
|
||||||
|
|
||||||
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
||||||
|
|
||||||
@@ -488,7 +496,6 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
c->base.destroy = wayland_destroy;
|
c->base.destroy = wayland_destroy;
|
||||||
c->base.create_buffer = wlsc_shm_buffer_create;
|
|
||||||
|
|
||||||
/* Can't init base class until we have a current egl context */
|
/* Can't init base class until we have a current egl context */
|
||||||
if (wlsc_compositor_init(&c->base, display) < 0)
|
if (wlsc_compositor_init(&c->base, display) < 0)
|
||||||
|
|||||||
@@ -198,6 +198,14 @@ x11_output_image_is_scanoutable(struct wlsc_output *output_base,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
x11_output_set_cursor(struct wlsc_output *output_base,
|
||||||
|
struct wl_input_device *input)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
x11_output_set_wm_protocols(struct x11_output *output)
|
x11_output_set_wm_protocols(struct x11_output *output)
|
||||||
{
|
{
|
||||||
@@ -347,6 +355,7 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height)
|
|||||||
output->base.prepare_render = x11_output_prepare_render;
|
output->base.prepare_render = x11_output_prepare_render;
|
||||||
output->base.present = x11_output_present;
|
output->base.present = x11_output_present;
|
||||||
output->base.image_is_scanoutable = x11_output_image_is_scanoutable;
|
output->base.image_is_scanoutable = x11_output_image_is_scanoutable;
|
||||||
|
output->base.set_hardware_cursor = x11_output_set_cursor;
|
||||||
|
|
||||||
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
||||||
|
|
||||||
@@ -582,7 +591,6 @@ x11_compositor_create(struct wl_display *display, int width, int height)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
c->base.destroy = x11_destroy;
|
c->base.destroy = x11_destroy;
|
||||||
c->base.create_buffer = wlsc_shm_buffer_create;
|
|
||||||
|
|
||||||
/* Can't init base class until we have a current egl context */
|
/* Can't init base class until we have a current egl context */
|
||||||
if (wlsc_compositor_init(&c->base, display) < 0)
|
if (wlsc_compositor_init(&c->base, display) < 0)
|
||||||
|
|||||||
+112
-28
@@ -120,7 +120,7 @@ wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
|
|||||||
*v = t;
|
*v = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlsc_surface *
|
struct wlsc_surface *
|
||||||
wlsc_surface_create(struct wlsc_compositor *compositor,
|
wlsc_surface_create(struct wlsc_compositor *compositor,
|
||||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||||
{
|
{
|
||||||
@@ -144,6 +144,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
|
|||||||
surface->compositor = compositor;
|
surface->compositor = compositor;
|
||||||
surface->visual = NULL;
|
surface->visual = NULL;
|
||||||
surface->image = EGL_NO_IMAGE_KHR;
|
surface->image = EGL_NO_IMAGE_KHR;
|
||||||
|
surface->saved_texture = 0;
|
||||||
surface->x = x;
|
surface->x = x;
|
||||||
surface->y = y;
|
surface->y = y;
|
||||||
surface->width = width;
|
surface->width = width;
|
||||||
@@ -201,7 +202,11 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client)
|
|||||||
wlsc_surface_damage(surface);
|
wlsc_surface_damage(surface);
|
||||||
|
|
||||||
wl_list_remove(&surface->link);
|
wl_list_remove(&surface->link);
|
||||||
|
if (surface->saved_texture == 0)
|
||||||
glDeleteTextures(1, &surface->texture);
|
glDeleteTextures(1, &surface->texture);
|
||||||
|
else
|
||||||
|
glDeleteTextures(1, &surface->saved_texture);
|
||||||
|
|
||||||
|
|
||||||
if (surface->image != EGL_NO_IMAGE_KHR)
|
if (surface->image != EGL_NO_IMAGE_KHR)
|
||||||
eglDestroyImageKHR(surface->compositor->display,
|
eglDestroyImageKHR(surface->compositor->display,
|
||||||
@@ -295,30 +300,81 @@ wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface)
|
|||||||
EGL_WAYLAND_BUFFER_WL,
|
EGL_WAYLAND_BUFFER_WL,
|
||||||
buffer, NULL);
|
buffer, NULL);
|
||||||
|
|
||||||
|
if (es->saved_texture != 0)
|
||||||
|
es->texture = es->saved_texture;
|
||||||
glBindTexture(GL_TEXTURE_2D, es->texture);
|
glBindTexture(GL_TEXTURE_2D, es->texture);
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
|
||||||
es->visual = buffer->visual;
|
es->visual = buffer->visual;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_buffer *
|
static void
|
||||||
create_buffer_from_png(struct wlsc_compositor *ec,
|
wlsc_sprite_attach(struct wlsc_sprite *sprite, struct wl_surface *surface)
|
||||||
const char *filename, int width, int height)
|
{
|
||||||
|
struct wlsc_surface *es = (struct wlsc_surface *) surface;
|
||||||
|
|
||||||
|
es->image = sprite->image;
|
||||||
|
if (sprite->image != EGL_NO_IMAGE_KHR) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, es->texture);
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
|
||||||
|
} else {
|
||||||
|
if (es->saved_texture == 0)
|
||||||
|
es->saved_texture = es->texture;
|
||||||
|
es->texture = sprite->texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
es->visual = sprite->visual;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum sprite_usage {
|
||||||
|
SPRITE_USE_CURSOR = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct wlsc_sprite *
|
||||||
|
create_sprite_from_png(struct wlsc_compositor *ec,
|
||||||
|
const char *filename, int width, int height,
|
||||||
|
uint32_t usage)
|
||||||
{
|
{
|
||||||
uint32_t *pixels;
|
uint32_t *pixels;
|
||||||
struct wl_buffer *buffer;
|
struct wlsc_sprite *sprite;
|
||||||
|
|
||||||
pixels = wlsc_load_image(filename, width, height);
|
pixels = wlsc_load_image(filename, width, height);
|
||||||
if(pixels == NULL)
|
if(pixels == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buffer = ec->create_buffer(ec, width, height, width * 4,
|
sprite = malloc(sizeof *sprite);
|
||||||
&ec->compositor.premultiplied_argb_visual,
|
if (sprite == NULL) {
|
||||||
pixels);
|
free(pixels);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite->visual = &ec->compositor.premultiplied_argb_visual;
|
||||||
|
sprite->width = width;
|
||||||
|
sprite->height = height;
|
||||||
|
sprite->image = EGL_NO_IMAGE_KHR;
|
||||||
|
|
||||||
|
if (usage & SPRITE_USE_CURSOR && ec->create_cursor_image != NULL)
|
||||||
|
sprite->image = ec->create_cursor_image(ec, width, height);
|
||||||
|
|
||||||
|
glGenTextures(1, &sprite->texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, sprite->texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
if (sprite->image != EGL_NO_IMAGE_KHR) {
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, sprite->image);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||||
|
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
} else {
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
|
||||||
|
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
free(pixels);
|
free(pixels);
|
||||||
|
|
||||||
return buffer;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -345,12 +401,13 @@ create_pointer_images(struct wlsc_compositor *ec)
|
|||||||
const int width = 32, height = 32;
|
const int width = 32, height = 32;
|
||||||
|
|
||||||
count = ARRAY_LENGTH(pointer_images);
|
count = ARRAY_LENGTH(pointer_images);
|
||||||
ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers);
|
ec->pointer_sprites = malloc(count * sizeof *ec->pointer_sprites);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
ec->pointer_buffers[i] =
|
ec->pointer_sprites[i] =
|
||||||
create_buffer_from_png(ec,
|
create_sprite_from_png(ec,
|
||||||
pointer_images[i].filename,
|
pointer_images[i].filename,
|
||||||
width, height);
|
width, height,
|
||||||
|
SPRITE_USE_CURSOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +415,7 @@ static struct wlsc_surface *
|
|||||||
background_create(struct wlsc_output *output, const char *filename)
|
background_create(struct wlsc_output *output, const char *filename)
|
||||||
{
|
{
|
||||||
struct wlsc_surface *background;
|
struct wlsc_surface *background;
|
||||||
struct wl_buffer *buffer;
|
struct wlsc_sprite *sprite;
|
||||||
|
|
||||||
background = wlsc_surface_create(output->compositor,
|
background = wlsc_surface_create(output->compositor,
|
||||||
output->x, output->y,
|
output->x, output->y,
|
||||||
@@ -366,15 +423,14 @@ background_create(struct wlsc_output *output, const char *filename)
|
|||||||
if (background == NULL)
|
if (background == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buffer = create_buffer_from_png(output->compositor,
|
sprite = create_sprite_from_png(output->compositor, filename,
|
||||||
filename,
|
output->width, output->height, 0);
|
||||||
output->width, output->height);
|
if (sprite == NULL) {
|
||||||
if (buffer == NULL) {
|
|
||||||
free(background);
|
free(background);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlsc_buffer_attach(buffer, &background->surface);
|
wlsc_sprite_attach(sprite, &background->surface);
|
||||||
|
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
@@ -516,6 +572,7 @@ wlsc_output_repaint(struct wlsc_output *output)
|
|||||||
struct wlsc_surface *es;
|
struct wlsc_surface *es;
|
||||||
struct wlsc_input_device *eid;
|
struct wlsc_input_device *eid;
|
||||||
pixman_region32_t new_damage, total_damage, repaint;
|
pixman_region32_t new_damage, total_damage, repaint;
|
||||||
|
int using_hardware_cursor = 1;
|
||||||
|
|
||||||
output->prepare_render(output);
|
output->prepare_render(output);
|
||||||
|
|
||||||
@@ -536,14 +593,23 @@ wlsc_output_repaint(struct wlsc_output *output)
|
|||||||
&output->previous_damage_region);
|
&output->previous_damage_region);
|
||||||
pixman_region32_copy(&output->previous_damage_region, &new_damage);
|
pixman_region32_copy(&output->previous_damage_region, &new_damage);
|
||||||
|
|
||||||
|
if (ec->focus)
|
||||||
|
if (output->set_hardware_cursor(output, ec->input_device) < 0)
|
||||||
|
using_hardware_cursor = 0;
|
||||||
|
|
||||||
output->scanout_surface = NULL;
|
output->scanout_surface = NULL;
|
||||||
|
|
||||||
es = container_of(ec->surface_list.next, struct wlsc_surface, link);
|
es = container_of(ec->surface_list.next, struct wlsc_surface, link);
|
||||||
if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN &&
|
if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN &&
|
||||||
es->fullscreen_output == output) {
|
es->fullscreen_output == output) {
|
||||||
if (es->visual == &ec->compositor.rgb_visual &&
|
if (es->visual == &ec->compositor.rgb_visual &&
|
||||||
|
using_hardware_cursor &&
|
||||||
wlsc_surface_is_scanoutable(es, output)) {
|
wlsc_surface_is_scanoutable(es, output)) {
|
||||||
output->scanout_surface = es;
|
output->scanout_surface = es;
|
||||||
|
/* we're drawing nothing now, draw the damages later */
|
||||||
|
pixman_region32_union(&ec->damage_region,
|
||||||
|
&ec->damage_region,
|
||||||
|
&total_damage);
|
||||||
} else {
|
} else {
|
||||||
if (es->width < output->width ||
|
if (es->width < output->width ||
|
||||||
es->height < output->height)
|
es->height < output->height)
|
||||||
@@ -589,8 +655,12 @@ wlsc_output_repaint(struct wlsc_output *output)
|
|||||||
wlsc_surface_draw(ec->overlay, output, &total_damage);
|
wlsc_surface_draw(ec->overlay, output, &total_damage);
|
||||||
|
|
||||||
if (ec->focus)
|
if (ec->focus)
|
||||||
wl_list_for_each(eid, &ec->input_device_list, link)
|
wl_list_for_each(eid, &ec->input_device_list, link) {
|
||||||
wlsc_surface_draw(eid->sprite, output, &total_damage);
|
if (&eid->input_device != ec->input_device ||
|
||||||
|
!using_hardware_cursor)
|
||||||
|
wlsc_surface_draw(eid->sprite, output,
|
||||||
|
&total_damage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -814,23 +884,37 @@ const static struct wl_surface_interface surface_interface = {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
wlsc_input_device_attach(struct wlsc_input_device *device,
|
wlsc_input_device_attach(struct wlsc_input_device *device,
|
||||||
struct wl_buffer *buffer, int x, int y)
|
int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
wlsc_surface_damage(device->sprite);
|
wlsc_surface_damage(device->sprite);
|
||||||
|
|
||||||
wlsc_buffer_attach(buffer, &device->sprite->surface);
|
|
||||||
device->hotspot_x = x;
|
device->hotspot_x = x;
|
||||||
device->hotspot_y = y;
|
device->hotspot_y = y;
|
||||||
|
|
||||||
device->sprite->x = device->input_device.x - device->hotspot_x;
|
device->sprite->x = device->input_device.x - device->hotspot_x;
|
||||||
device->sprite->y = device->input_device.y - device->hotspot_y;
|
device->sprite->y = device->input_device.y - device->hotspot_y;
|
||||||
device->sprite->width = buffer->width;
|
device->sprite->width = width;
|
||||||
device->sprite->height = buffer->height;
|
device->sprite->height = height;
|
||||||
wlsc_surface_update_matrix(device->sprite);
|
wlsc_surface_update_matrix(device->sprite);
|
||||||
|
|
||||||
wlsc_surface_damage(device->sprite);
|
wlsc_surface_damage(device->sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wlsc_input_device_attach_buffer(struct wlsc_input_device *device,
|
||||||
|
struct wl_buffer *buffer, int x, int y)
|
||||||
|
{
|
||||||
|
wlsc_buffer_attach(buffer, &device->sprite->surface);
|
||||||
|
wlsc_input_device_attach(device, x, y, buffer->width, buffer->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wlsc_input_device_attach_sprite(struct wlsc_input_device *device,
|
||||||
|
struct wlsc_sprite *sprite, int x, int y)
|
||||||
|
{
|
||||||
|
wlsc_sprite_attach(sprite, &device->sprite->surface);
|
||||||
|
wlsc_input_device_attach(device, x, y, sprite->width, sprite->height);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
|
wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
|
||||||
@@ -839,8 +923,8 @@ wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
|
|||||||
struct wlsc_compositor *compositor =
|
struct wlsc_compositor *compositor =
|
||||||
(struct wlsc_compositor *) device->input_device.compositor;
|
(struct wlsc_compositor *) device->input_device.compositor;
|
||||||
|
|
||||||
wlsc_input_device_attach(device,
|
wlsc_input_device_attach_sprite(device,
|
||||||
compositor->pointer_buffers[type],
|
compositor->pointer_sprites[type],
|
||||||
pointer_images[type].hotspot_x,
|
pointer_images[type].hotspot_x,
|
||||||
pointer_images[type].hotspot_y);
|
pointer_images[type].hotspot_y);
|
||||||
}
|
}
|
||||||
@@ -1268,7 +1352,7 @@ input_device_attach(struct wl_client *client,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlsc_input_device_attach(device, buffer, x, y);
|
wlsc_input_device_attach_buffer(device, buffer, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct wl_input_device_interface input_device_interface = {
|
const static struct wl_input_device_interface input_device_interface = {
|
||||||
|
|||||||
+17
-6
@@ -57,6 +57,8 @@ struct wlsc_output {
|
|||||||
int (*present)(struct wlsc_output *output);
|
int (*present)(struct wlsc_output *output);
|
||||||
int (*image_is_scanoutable)(struct wlsc_output *output,
|
int (*image_is_scanoutable)(struct wlsc_output *output,
|
||||||
EGLImageKHR image);
|
EGLImageKHR image);
|
||||||
|
int (*set_hardware_cursor)(struct wlsc_output *output,
|
||||||
|
struct wl_input_device *input);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wlsc_pointer_type {
|
enum wlsc_pointer_type {
|
||||||
@@ -86,6 +88,14 @@ struct wlsc_shm {
|
|||||||
struct wl_object object;
|
struct wl_object object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wlsc_sprite {
|
||||||
|
GLuint texture;
|
||||||
|
EGLImageKHR image;
|
||||||
|
struct wl_visual *visual;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
struct wlsc_compositor {
|
struct wlsc_compositor {
|
||||||
struct wl_compositor compositor;
|
struct wl_compositor compositor;
|
||||||
|
|
||||||
@@ -95,7 +105,7 @@ struct wlsc_compositor {
|
|||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
GLuint proj_uniform, tex_uniform;
|
GLuint proj_uniform, tex_uniform;
|
||||||
struct wl_buffer **pointer_buffers;
|
struct wlsc_sprite **pointer_sprites;
|
||||||
struct wl_display *wl_display;
|
struct wl_display *wl_display;
|
||||||
|
|
||||||
/* We implement the shell interface. */
|
/* We implement the shell interface. */
|
||||||
@@ -122,10 +132,8 @@ struct wlsc_compositor {
|
|||||||
|
|
||||||
void (*destroy)(struct wlsc_compositor *ec);
|
void (*destroy)(struct wlsc_compositor *ec);
|
||||||
int (*authenticate)(struct wlsc_compositor *c, uint32_t id);
|
int (*authenticate)(struct wlsc_compositor *c, uint32_t id);
|
||||||
struct wl_buffer *(*create_buffer)(struct wlsc_compositor *c,
|
EGLImageKHR (*create_cursor_image)(struct wlsc_compositor *c,
|
||||||
int32_t width, int32_t height,
|
int32_t width, int32_t height);
|
||||||
int32_t stride, struct wl_visual *visual,
|
|
||||||
void *data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MODIFIER_CTRL (1 << 8)
|
#define MODIFIER_CTRL (1 << 8)
|
||||||
@@ -150,7 +158,7 @@ enum wlsc_surface_map_type {
|
|||||||
struct wlsc_surface {
|
struct wlsc_surface {
|
||||||
struct wl_surface surface;
|
struct wl_surface surface;
|
||||||
struct wlsc_compositor *compositor;
|
struct wlsc_compositor *compositor;
|
||||||
GLuint texture;
|
GLuint texture, saved_texture;
|
||||||
int32_t x, y, width, height;
|
int32_t x, y, width, height;
|
||||||
int32_t saved_x, saved_y;
|
int32_t saved_x, saved_y;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
@@ -210,6 +218,9 @@ wlsc_compositor_add_binding(struct wlsc_compositor *compositor,
|
|||||||
void
|
void
|
||||||
wlsc_binding_destroy(struct wlsc_binding *binding);
|
wlsc_binding_destroy(struct wlsc_binding *binding);
|
||||||
|
|
||||||
|
struct wlsc_surface *
|
||||||
|
wlsc_surface_create(struct wlsc_compositor *compositor,
|
||||||
|
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||||
|
|
||||||
void
|
void
|
||||||
wlsc_surface_assign_output(struct wlsc_surface *surface);
|
wlsc_surface_assign_output(struct wlsc_surface *surface);
|
||||||
|
|||||||
@@ -195,24 +195,3 @@ wlsc_shm_init(struct wlsc_compositor *ec)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_buffer *
|
|
||||||
wlsc_shm_buffer_create(struct wlsc_compositor *ec, int width, int height,
|
|
||||||
int stride, struct wl_visual *visual,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct wlsc_shm_buffer *buffer;
|
|
||||||
void *pixels;
|
|
||||||
|
|
||||||
pixels = malloc(stride * height);
|
|
||||||
if (!pixels)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memcpy(pixels, data, stride * height);
|
|
||||||
|
|
||||||
buffer = wlsc_shm_buffer_init(ec, width, height,
|
|
||||||
stride, visual, pixels);
|
|
||||||
buffer->mapped = 0;
|
|
||||||
|
|
||||||
return &buffer->buffer;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user