st/dri/sw: Implement texture_from_pixmap
authorBenjamin Franzke <benjaminfranzke@googlemail.com>
Fri, 9 Sep 2011 08:12:23 +0000 (10:12 +0200)
committerBenjamin Franzke <benjaminfranzke@googlemail.com>
Wed, 2 Nov 2011 14:43:27 +0000 (15:43 +0100)
This is a cleanup of commit 02f1b50987c0d24da3dcc36dbb44821c20d0660c.

Update tex buffer using a dri_drawable hook from implemented in sw/drisw.c.
This saves us the duplication of dri_drawable.c.

CC: Stuart Abercrombie <sabercrombie@chromium.org>
CC: Stéphane Marchesin <marcheu@chromium.org>
src/gallium/state_trackers/dri/common/dri_drawable.c
src/gallium/state_trackers/dri/common/dri_drawable.h
src/gallium/state_trackers/dri/drm/dri2.c
src/gallium/state_trackers/dri/sw/drisw.c

index 340404e6aa400b83447ef37ae4e3227c19c2707e..485616fde6c25a523a221418314d4269ca6bbe11 100644 (file)
@@ -207,6 +207,7 @@ dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
 
    dri_drawable_validate_att(drawable, ST_ATTACHMENT_FRONT_LEFT);
 
+   /* Use the pipe resource associated with the X drawable */
    pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
 
    if (pt) {
@@ -226,6 +227,8 @@ dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
          }
       }
 
+      drawable->update_tex_buffer(drawable, ctx, pt);
+
       ctx->st->teximage(ctx->st,
             (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT,
             0, internal_format, pt, FALSE);
index 007421ebe18ee1f439960d4e4f458dfb8b00615a..3e3876e74a572699b79355f27f433e4f3d238b08 100644 (file)
@@ -77,6 +77,10 @@ struct dri_drawable
 
    void (*flush_frontbuffer)(struct dri_drawable *drawable,
                              enum st_attachment_type statt);
+
+   void (*update_tex_buffer)(struct dri_drawable *drawable,
+                             struct dri_context *ctx,
+                             struct pipe_resource *res);
 };
 
 static INLINE struct dri_drawable *
index f3c9e1053cb868757a88a94005459f38f2454044..2e0bb7eecf14d9fd276a0968b5a7f092a938fe23 100644 (file)
@@ -380,6 +380,14 @@ dri2_flush_frontbuffer(struct dri_drawable *drawable,
    }
 }
 
+static void
+dri2_update_tex_buffer(struct dri_drawable *drawable,
+                       struct dri_context *ctx,
+                       struct pipe_resource *res)
+{
+   /* no-op */
+}
+
 static __DRIimage *
 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
 {
@@ -707,6 +715,7 @@ dri2_create_buffer(__DRIscreen * sPriv,
 
    drawable->allocate_textures = dri2_allocate_textures;
    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
+   drawable->update_tex_buffer = dri2_update_tex_buffer;
 
    return TRUE;
 }
index 082df55e8eac44eb7065c5b4c39dfe2d52a63f10..f336fe075f85172038c731dcd56c55f8e3fd43d4 100644 (file)
@@ -28,7 +28,7 @@
 
 /* TODO:
  *
- * xshm / texture_from_pixmap / EGLImage:
+ * xshm / EGLImage:
  *
  * Allow the loaders to use the XSHM extension. It probably requires callbacks
  * for createImage/destroyImage similar to DRI2 getBuffers.
@@ -39,6 +39,7 @@
 #include "util/u_inlines.h"
 #include "pipe/p_context.h"
 #include "state_tracker/drisw_api.h"
+#include "state_tracker/st_context.h"
 
 #include "dri_screen.h"
 #include "dri_context.h"
@@ -48,14 +49,13 @@ DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE);
 static boolean swrast_no_present = FALSE;
 
 static INLINE void
-get_drawable_info(__DRIdrawable *dPriv, int *w, int *h)
+get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h)
 {
    __DRIscreen *sPriv = dPriv->driScreenPriv;
    const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
-   int x, y;
 
    loader->getDrawableInfo(dPriv,
-                           &x, &y, w, h,
+                           x, y, w, h,
                            dPriv->loaderPrivate);
 }
 
@@ -74,8 +74,9 @@ static void
 drisw_update_drawable_info(struct dri_drawable *drawable)
 {
    __DRIdrawable *dPriv = drawable->dPriv;
+   int x, y;
 
-   get_drawable_info(dPriv, &dPriv->w, &dPriv->h);
+   get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
 }
 
 static void
@@ -228,6 +229,43 @@ drisw_allocate_textures(struct dri_drawable *drawable,
    drawable->old_h = height;
 }
 
+static void
+drisw_update_tex_buffer(struct dri_drawable *drawable,
+                        struct dri_context *ctx,
+                        struct pipe_resource *res)
+{
+   struct pipe_context *pipe = ((struct st_context *) ctx)->st->pipe;
+   __DRIdrawable *dPriv = drawable->dPriv;
+   __DRIscreen *sPriv = dPriv->driScreenPriv;
+   int x, y, w, h;
+   struct pipe_transfer *transfer;
+   char *map;
+   int ximage_stride, line;
+
+   get_drawable_info(dPriv, &x, &y, &w, &h);
+
+   transfer = pipe_get_transfer(pipe, res,
+                                0, 0, // level, layer,
+                                PIPE_TRANSFER_WRITE,
+                                x, y, w, h);
+   map = pipe_transfer_map(pipe, transfer);
+
+   /* Copy the Drawable content to the mapped texture buffer */
+   sPriv->swrast_loader->getImage(dPriv, x, y, w, h, map, dPriv->loaderPrivate);
+
+   /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
+      We assume 32 bit pixels. */
+   ximage_stride = w * 4;
+   for (line = h-1; line; --line) {
+      memmove(&map[line * transfer->stride],
+              &map[line * ximage_stride],
+              ximage_stride);
+   }
+
+   pipe_transfer_unmap(pipe, transfer);
+   pipe_transfer_destroy(pipe, transfer);
+}
+
 /*
  * Backend function for init_screen.
  */
@@ -289,6 +327,7 @@ drisw_create_buffer(__DRIscreen * sPriv,
    drawable->allocate_textures = drisw_allocate_textures;
    drawable->update_drawable_info = drisw_update_drawable_info;
    drawable->flush_frontbuffer = drisw_flush_frontbuffer;
+   drawable->update_tex_buffer = drisw_update_tex_buffer;
 
    return TRUE;
 }