Optimize fullscreen scanout abit
authorBenjamin Franzke <benjaminfranzke@googlemail.com>
Wed, 20 Apr 2011 15:06:13 +0000 (17:06 +0200)
committerBenjamin Franzke <benjaminfranzke@googlemail.com>
Wed, 20 Apr 2011 15:30:12 +0000 (17:30 +0200)
Use the drm fb_id used for the scanout-test
as well for the corresponding pageflip.

Move most of the scanout details into compositor-drm.

compositor/compositor-drm.c
compositor/compositor-wayland.c
compositor/compositor-x11.c
compositor/compositor.c
compositor/compositor.h

index 4133c19..ecc074f 100644 (file)
@@ -64,6 +64,8 @@ struct drm_output {
        EGLImageKHR image[2];
        uint32_t current;       
 
+       struct wlsc_surface *scanout_surface;
+
        uint32_t fs_surf_fb_id;
        uint32_t pending_fs_surf_fb_id;
 };
@@ -90,7 +92,6 @@ 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))
@@ -99,22 +100,8 @@ 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);
-
+       if (output->scanout_surface != NULL) {
+               output->scanout_surface = NULL;
                fb_id = output->fs_surf_fb_id;
        } else {
                fb_id = output->fb_id[output->current ^ 1];
@@ -151,8 +138,8 @@ page_flip_handler(int fd, unsigned int frame,
 }
 
 static int
-drm_output_image_is_scanoutable(struct wlsc_output *output_base,
-                               EGLImageKHR image)
+drm_output_prepare_scanout_surface(struct wlsc_output *output_base,
+                                  struct wlsc_surface *es)
 {
        struct drm_output *output = (struct drm_output *) output_base;
        struct drm_compositor *c =
@@ -161,22 +148,28 @@ drm_output_image_is_scanoutable(struct wlsc_output *output_base,
        int ret;
        uint32_t fb_id = 0;
 
-       eglExportDRMImageMESA(c->base.display, image,
+       if (es->width != output->base.width ||
+           es->height != output->base.height ||
+           es->image == EGL_NO_IMAGE_KHR)
+               return -1;
+
+       eglExportDRMImageMESA(c->base.display, es->image,
                              NULL, &handle, &stride);
 
+       if (handle == 0)
+               return -1;
+
        ret = drmModeAddFB(c->drm.fd,
                           output->base.width, output->base.height,
-                          32, 32, stride, handle,
-                          &fb_id);
+                          32, 32, stride, handle, &fb_id);
+
        if (ret)
-               return 0;
+               return -1;
 
-       /* FIXME: change interface to keep this fb_id,
-        * to be used directly in next pageflip? */
-       if (fb_id)
-               drmModeRmFB(c->drm.fd, fb_id);
+       output->fs_surf_fb_id = fb_id;
+       output->scanout_surface = es;
 
-       return fb_id != 0;
+       return 0;
 }
 
 static int
@@ -412,9 +405,11 @@ create_output_for_connector(struct drm_compositor *ec,
                return -1;
        }
 
+       output->scanout_surface = NULL;
        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.prepare_scanout_surface =
+               drm_output_prepare_scanout_surface;
        output->base.set_hardware_cursor = drm_output_set_cursor;
 
        wl_list_insert(ec->base.output_list.prev, &output->base.link);
index f457570..b2ec7c1 100644 (file)
@@ -197,10 +197,10 @@ wayland_output_present(struct wlsc_output *output_base)
 }
 
 static int
-wayland_output_image_is_scanoutable(struct wlsc_output *output_base,
-                                   EGLImageKHR image)
+wayland_output_prepare_scanout_surface(struct wlsc_output *output_base,
+                                      struct wlsc_surface *es)
 {
-       return 0;
+       return -1;
 }
 
 static int
@@ -260,7 +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.prepare_scanout_surface =
+               wayland_output_prepare_scanout_surface;
        output->base.set_hardware_cursor = wayland_output_set_cursor;
 
        wl_list_insert(c->base.output_list.prev, &output->base.link);
index 47843d4..04eca07 100644 (file)
@@ -192,10 +192,10 @@ x11_output_present(struct wlsc_output *output_base)
 }
 
 static int
-x11_output_image_is_scanoutable(struct wlsc_output *output_base,
-                               EGLImageKHR image)
+x11_output_prepare_scanout_surface(struct wlsc_output *output_base,
+                                  struct wlsc_surface *es)
 {
-       return 0;
+       return -1;
 }
 
 static int
@@ -354,7 +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.prepare_scanout_surface =
+               x11_output_prepare_scanout_surface;
        output->base.set_hardware_cursor = x11_output_set_cursor;
 
        wl_list_insert(c->base.output_list.prev, &output->base.link);
index 5ff7a45..333ab22 100644 (file)
@@ -550,21 +550,6 @@ 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)
 {
@@ -597,25 +582,25 @@ wlsc_output_repaint(struct wlsc_output *output)
                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->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);
+                   using_hardware_cursor) {
+                       if (output->prepare_scanout_surface(output, es) == 0) {
+                               /* We're drawing nothing now,
+                                * draw the damaged regions later. */
+                               pixman_region32_union(&ec->damage_region,
+                                                     &ec->damage_region,
+                                                     &total_damage);
+                               return;
+                       }
                }
+
+               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)
index 84c0139..6a7991c 100644 (file)
@@ -51,12 +51,10 @@ 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 (*prepare_scanout_surface)(struct wlsc_output *output,
+                                      struct wlsc_surface *es);
        int (*set_hardware_cursor)(struct wlsc_output *output,
                                   struct wl_input_device *input);
 };