Merge remote-tracking branch 'bnf/fullscreen-pageflip'
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 20 Apr 2011 13:35:15 +0000 (09:35 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 20 Apr 2011 13:35:15 +0000 (09:35 -0400)
compositor/compositor-drm.c
compositor/compositor-wayland.c
compositor/compositor-x11.c
compositor/compositor.c
compositor/compositor.h
compositor/shm.c

index 10ba65a..4133c19 100644 (file)
@@ -63,6 +63,9 @@ struct drm_output {
        uint32_t fb_id[2];
        EGLImageKHR image[2];
        uint32_t current;       
+
+       uint32_t fs_surf_fb_id;
+       uint32_t pending_fs_surf_fb_id;
 };
 
 static int
@@ -87,6 +90,8 @@ drm_output_present(struct wlsc_output *output_base)
        struct drm_output *output = (struct drm_output *) output_base;
        struct drm_compositor *c =
                (struct drm_compositor *) output->base.compositor;
+       int ret;
+       uint32_t fb_id = 0;
 
        if (drm_output_prepare_render(&output->base))
                return -1;
@@ -94,8 +99,29 @@ drm_output_present(struct wlsc_output *output_base)
 
        output->current ^= 1;
 
+       if (output->base.scanout_surface) {
+               EGLint handle, stride;
+
+               eglExportDRMImageMESA(c->base.display,
+                                     output->base.scanout_surface->image,
+                                     NULL, &handle, &stride);
+
+               ret = drmModeAddFB(c->drm.fd,
+                                  output->base.width, output->base.height,
+                                  32, 32, stride, handle,
+                                  &output->fs_surf_fb_id);
+               if (ret)
+                       return -1;
+
+               printf("pageflip to fullscreen buffer: %d\n", handle);
+
+               fb_id = output->fs_surf_fb_id;
+       } else {
+               fb_id = output->fb_id[output->current ^ 1];
+       }
+
        drmModePageFlip(c->drm.fd, output->crtc_id,
-                       output->fb_id[output->current ^ 1],
+                       fb_id,
                        DRM_MODE_PAGE_FLIP_EVENT, output);
 
        return 0;
@@ -105,11 +131,114 @@ static void
 page_flip_handler(int fd, unsigned int frame,
                  unsigned int sec, unsigned int usec, void *data)
 {
-       struct wlsc_output *output = data;
+       struct drm_output *output = (struct drm_output *) data;
+       struct drm_compositor *c =
+               (struct drm_compositor *) output->base.compositor;
        uint32_t msecs;
 
+       if (output->pending_fs_surf_fb_id) {
+               drmModeRmFB(c->drm.fd, output->pending_fs_surf_fb_id);
+               output->pending_fs_surf_fb_id = 0;
+       }
+
+       if (output->fs_surf_fb_id) {
+               output->pending_fs_surf_fb_id = output->fs_surf_fb_id;
+               output->fs_surf_fb_id = 0;
+       }
+
        msecs = sec * 1000 + usec / 1000;
-       wlsc_output_finish_frame(output, msecs);
+       wlsc_output_finish_frame(&output->base, msecs);
+}
+
+static int
+drm_output_image_is_scanoutable(struct wlsc_output *output_base,
+                               EGLImageKHR image)
+{
+       struct drm_output *output = (struct drm_output *) output_base;
+       struct drm_compositor *c =
+               (struct drm_compositor *) output->base.compositor;
+       EGLint handle, stride;
+       int ret;
+       uint32_t fb_id = 0;
+
+       eglExportDRMImageMESA(c->base.display, image,
+                             NULL, &handle, &stride);
+
+       ret = drmModeAddFB(c->drm.fd,
+                          output->base.width, output->base.height,
+                          32, 32, stride, handle,
+                          &fb_id);
+       if (ret)
+               return 0;
+
+       /* FIXME: change interface to keep this fb_id,
+        * to be used directly in next pageflip? */
+       if (fb_id)
+               drmModeRmFB(c->drm.fd, fb_id);
+
+       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
@@ -285,6 +414,8 @@ create_output_for_connector(struct drm_compositor *ec,
 
        output->base.prepare_render = drm_output_prepare_render;
        output->base.present = drm_output_present;
+       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);
 
@@ -466,6 +597,50 @@ udev_drm_event(int fd, uint32_t mask, void *data)
        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
 drm_destroy(struct wlsc_compositor *ec)
 {
@@ -521,7 +696,8 @@ drm_compositor_create(struct wl_display *display, int connector)
        }
 
        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;
 
        glGenFramebuffers(1, &ec->base.fbo);
index 097b23e..f457570 100644 (file)
@@ -197,6 +197,20 @@ wayland_output_present(struct wlsc_output *output_base)
 }
 
 static int
+wayland_output_image_is_scanoutable(struct wlsc_output *output_base,
+                                   EGLImageKHR image)
+{
+       return 0;
+}
+
+static int
+wayland_output_set_cursor(struct wlsc_output *output_base,
+                         struct wl_input_device *input)
+{
+       return -1;
+}
+
+static int
 wayland_compositor_create_output(struct wayland_compositor *c,
                                 int width, int height)
 {
@@ -246,6 +260,8 @@ wayland_compositor_create_output(struct wayland_compositor *c,
 
        output->base.prepare_render = wayland_output_prepare_render;
        output->base.present = wayland_output_present;
+       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);
 
@@ -480,7 +496,6 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
                return NULL;
 
        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 */
        if (wlsc_compositor_init(&c->base, display) < 0)
index 108955f..47843d4 100644 (file)
@@ -191,6 +191,21 @@ x11_output_present(struct wlsc_output *output_base)
        return 0;
 }
 
+static int
+x11_output_image_is_scanoutable(struct wlsc_output *output_base,
+                               EGLImageKHR image)
+{
+       return 0;
+}
+
+static int
+x11_output_set_cursor(struct wlsc_output *output_base,
+                     struct wl_input_device *input)
+{
+       return -1;
+}
+
+
 static void
 x11_output_set_wm_protocols(struct x11_output *output)
 {
@@ -339,6 +354,8 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height)
 
        output->base.prepare_render = x11_output_prepare_render;
        output->base.present = x11_output_present;
+       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);
 
@@ -599,7 +616,6 @@ x11_compositor_create(struct wl_display *display, int width, int height)
                return NULL;
 
        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 */
        if (wlsc_compositor_init(&c->base, display) < 0)
index ed3069d..5ff7a45 100644 (file)
@@ -120,7 +120,7 @@ wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
        *v = t;
 }
 
-static struct wlsc_surface *
+struct wlsc_surface *
 wlsc_surface_create(struct wlsc_compositor *compositor,
                    int32_t x, int32_t y, int32_t width, int32_t height)
 {
@@ -143,6 +143,8 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
 
        surface->compositor = compositor;
        surface->visual = NULL;
+       surface->image = EGL_NO_IMAGE_KHR;
+       surface->saved_texture = 0;
        surface->x = x;
        surface->y = y;
        surface->width = width;
@@ -200,7 +202,15 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client)
        wlsc_surface_damage(surface);
 
        wl_list_remove(&surface->link);
-       glDeleteTextures(1, &surface->texture);
+       if (surface->saved_texture == 0)
+               glDeleteTextures(1, &surface->texture);
+       else
+               glDeleteTextures(1, &surface->saved_texture);
+
+
+       if (surface->image != EGL_NO_IMAGE_KHR)
+               eglDestroyImageKHR(surface->compositor->display,
+                                  surface->image);
 
        time = get_time();
        wl_list_for_each_safe(l, next,
@@ -282,40 +292,89 @@ wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface)
 {
        struct wlsc_surface *es = (struct wlsc_surface *) surface;
        struct wlsc_compositor *ec = es->compositor;
-       EGLImageKHR *image;
 
        if (buffer->attach) {
                buffer->attach(buffer, surface);
        } else {
-               image = eglCreateImageKHR(ec->display, ec->context,
-                                         EGL_WAYLAND_BUFFER_WL,
-                                         buffer, NULL);
+               es->image = eglCreateImageKHR(ec->display, ec->context,
+                                             EGL_WAYLAND_BUFFER_WL,
+                                             buffer, NULL);
 
+               if (es->saved_texture != 0)
+                       es->texture = es->saved_texture;
                glBindTexture(GL_TEXTURE_2D, es->texture);
-               glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+               glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, es->image);
                es->visual = buffer->visual;
-               eglDestroyImageKHR(ec->display, image);
        }
 }
 
-static struct wl_buffer *
-create_buffer_from_png(struct wlsc_compositor *ec,
-                      const char *filename, int width, int height)
+static void
+wlsc_sprite_attach(struct wlsc_sprite *sprite, struct wl_surface *surface)
+{
+       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;
-       struct wl_buffer *buffer;
+       struct wlsc_sprite *sprite;
 
        pixels = wlsc_load_image(filename, width, height);
        if(pixels == NULL)
-           return NULL;
+               return NULL;
+
+       sprite = malloc(sizeof *sprite);
+       if (sprite == NULL) {
+               free(pixels);
+               return NULL;
+       }
 
-       buffer = ec->create_buffer(ec, width, height, width * 4,
-                                  &ec->compositor.premultiplied_argb_visual,
-                                  pixels);
+       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);
 
-       return buffer;
+       return sprite;
 }
 
 static const struct {
@@ -342,12 +401,13 @@ create_pointer_images(struct wlsc_compositor *ec)
        const int width = 32, height = 32;
 
        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++) {
-               ec->pointer_buffers[i] =
-                       create_buffer_from_png(ec,
+               ec->pointer_sprites[i] =
+                       create_sprite_from_png(ec,
                                               pointer_images[i].filename,
-                                              width, height);
+                                              width, height,
+                                              SPRITE_USE_CURSOR);
        }
 }
 
@@ -355,7 +415,7 @@ static struct wlsc_surface *
 background_create(struct wlsc_output *output, const char *filename)
 {
        struct wlsc_surface *background;
-       struct wl_buffer *buffer;
+       struct wlsc_sprite *sprite;
 
        background = wlsc_surface_create(output->compositor,
                                         output->x, output->y,
@@ -363,15 +423,14 @@ background_create(struct wlsc_output *output, const char *filename)
        if (background == NULL)
                return NULL;
 
-       buffer = create_buffer_from_png(output->compositor,
-                                       filename,
-                                       output->width, output->height);
-       if (buffer == NULL) {
+       sprite = create_sprite_from_png(output->compositor, filename,
+                                       output->width, output->height, 0);
+       if (sprite == NULL) {
                free(background);
                return NULL;
        }
 
-       wlsc_buffer_attach(buffer, &background->surface);
+       wlsc_sprite_attach(sprite, &background->surface);
 
        return background;
 }
@@ -491,6 +550,21 @@ wlsc_output_finish_frame(struct wlsc_output *output, int msecs)
        compositor->repaint_on_timeout = 1;
 }
 
+static int
+wlsc_surface_is_scanoutable(struct wlsc_surface *es,
+                           struct wlsc_output *output)
+{
+       if (es->width != output->width ||
+           es->height != output->height ||
+           es->image == NULL)
+               return 0;
+
+       if (!output->image_is_scanoutable(output, es->image))
+               return 0;
+
+       return 1;
+}
+
 static void
 wlsc_output_repaint(struct wlsc_output *output)
 {
@@ -498,6 +572,7 @@ wlsc_output_repaint(struct wlsc_output *output)
        struct wlsc_surface *es;
        struct wlsc_input_device *eid;
        pixman_region32_t new_damage, total_damage, repaint;
+       int using_hardware_cursor = 1;
 
        output->prepare_render(output);
 
@@ -518,12 +593,29 @@ wlsc_output_repaint(struct wlsc_output *output)
                              &output->previous_damage_region);
        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;
+
        es = container_of(ec->surface_list.next, struct wlsc_surface, link);
        if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN &&
            es->fullscreen_output == output) {
-               if (es->width < output->width || es->height < output->height)
-                       glClear(GL_COLOR_BUFFER_BIT);
-               wlsc_surface_draw(es, output, &total_damage);
+               if (es->visual == &ec->compositor.rgb_visual &&
+                   using_hardware_cursor &&
+                   wlsc_surface_is_scanoutable(es, output)) {
+                       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 {
+                       if (es->width < output->width ||
+                           es->height < output->height)
+                               glClear(GL_COLOR_BUFFER_BIT);
+                       wlsc_surface_draw(es, output, &total_damage);
+               }
        } else {
                wl_list_for_each(es, &ec->surface_list, link) {
                        if (es->visual != &ec->compositor.rgb_visual)
@@ -563,8 +655,12 @@ wlsc_output_repaint(struct wlsc_output *output)
                wlsc_surface_draw(ec->overlay, output, &total_damage);
 
        if (ec->focus)
-               wl_list_for_each(eid, &ec->input_device_list, link)
-                       wlsc_surface_draw(eid->sprite, output, &total_damage);
+               wl_list_for_each(eid, &ec->input_device_list, link) {
+                       if (&eid->input_device != ec->input_device ||
+                           !using_hardware_cursor)
+                               wlsc_surface_draw(eid->sprite, output,
+                                                 &total_damage);
+               }
 }
 
 static void
@@ -788,23 +884,37 @@ const static struct wl_surface_interface surface_interface = {
 
 static void
 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_buffer_attach(buffer, &device->sprite->surface);
        device->hotspot_x = x;
        device->hotspot_y = y;
 
        device->sprite->x = device->input_device.x - device->hotspot_x;
        device->sprite->y = device->input_device.y - device->hotspot_y;
-       device->sprite->width = buffer->width;
-       device->sprite->height = buffer->height;
+       device->sprite->width = width;
+       device->sprite->height = height;
        wlsc_surface_update_matrix(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
 wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
@@ -813,10 +923,10 @@ wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
        struct wlsc_compositor *compositor =
                (struct wlsc_compositor *) device->input_device.compositor;
 
-       wlsc_input_device_attach(device,
-                                compositor->pointer_buffers[type],
-                                pointer_images[type].hotspot_x,
-                                pointer_images[type].hotspot_y);
+       wlsc_input_device_attach_sprite(device,
+                                       compositor->pointer_sprites[type],
+                                       pointer_images[type].hotspot_x,
+                                       pointer_images[type].hotspot_y);
 }
 
 static void
@@ -1242,7 +1352,7 @@ input_device_attach(struct wl_client *client,
                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 = {
index e48c2b2..84c0139 100644 (file)
@@ -51,8 +51,14 @@ struct wlsc_output {
        int repaint_needed;
        int finished;
 
+       struct wlsc_surface *scanout_surface;
+
        int (*prepare_render)(struct wlsc_output *output);
        int (*present)(struct wlsc_output *output);
+       int (*image_is_scanoutable)(struct wlsc_output *output,
+                                   EGLImageKHR image);
+       int (*set_hardware_cursor)(struct wlsc_output *output,
+                                  struct wl_input_device *input);
 };
 
 enum wlsc_pointer_type {
@@ -82,6 +88,14 @@ struct wlsc_shm {
        struct wl_object object;
 };
 
+struct wlsc_sprite {
+       GLuint texture;
+       EGLImageKHR image;
+       struct wl_visual *visual;
+       int width;
+       int height;
+};
+
 struct wlsc_compositor {
        struct wl_compositor compositor;
 
@@ -91,7 +105,7 @@ struct wlsc_compositor {
        EGLConfig config;
        GLuint fbo;
        GLuint proj_uniform, tex_uniform;
-       struct wl_buffer **pointer_buffers;
+       struct wlsc_sprite **pointer_sprites;
        struct wl_display *wl_display;
 
        /* We implement the shell interface. */
@@ -118,10 +132,8 @@ struct wlsc_compositor {
 
        void (*destroy)(struct wlsc_compositor *ec);
        int (*authenticate)(struct wlsc_compositor *c, uint32_t id);
-       struct wl_buffer *(*create_buffer)(struct wlsc_compositor *c,
-                                          int32_t width, int32_t height,
-                                          int32_t stride, struct wl_visual *visual,
-                                          void *data);
+       EGLImageKHR (*create_cursor_image)(struct wlsc_compositor *c,
+                                          int32_t width, int32_t height);
 };
 
 #define MODIFIER_CTRL  (1 << 8)
@@ -146,7 +158,7 @@ enum wlsc_surface_map_type {
 struct wlsc_surface {
        struct wl_surface surface;
        struct wlsc_compositor *compositor;
-       GLuint texture;
+       GLuint texture, saved_texture;
        int32_t x, y, width, height;
        int32_t saved_x, saved_y;
        struct wl_list link;
@@ -157,6 +169,8 @@ struct wlsc_surface {
        struct wlsc_output *output;
        enum wlsc_surface_map_type map_type;
        struct wlsc_output *fullscreen_output;
+
+       EGLImageKHR image;
 };
 
 void
@@ -204,6 +218,9 @@ wlsc_compositor_add_binding(struct wlsc_compositor *compositor,
 void
 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
 wlsc_surface_assign_output(struct wlsc_surface *surface);
index 967ff72..4c17a08 100644 (file)
@@ -195,24 +195,3 @@ wlsc_shm_init(struct wlsc_compositor *ec)
 
        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;
-}