implement get/put_tile() for xlib driver
authorBrian <brian.paul@tungstengraphics.com>
Thu, 1 Nov 2007 17:23:50 +0000 (11:23 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 1 Nov 2007 17:23:50 +0000 (11:23 -0600)
src/mesa/pipe/softpipe/sp_surface.c
src/mesa/pipe/softpipe/sp_surface.h
src/mesa/pipe/xlib/xm_surface.c

index 3aa72ef569b41471be33a6c0f66a0bca33d82b1c..ccaf38de3e46be5c8d4d5beb4d2601a825c8afc5 100644 (file)
@@ -502,9 +502,8 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
 /**
  * Move raw block of pixels from surface to user memory.
  */
-static void
-softpipe_get_tile(struct pipe_context *pipe,
-                  struct pipe_surface *ps,
+void
+softpipe_get_tile(struct pipe_context *pipe, struct pipe_surface *ps,
                   uint x, uint y, uint w, uint h,
                   void *p, int dst_stride)
 {
@@ -535,9 +534,8 @@ softpipe_get_tile(struct pipe_context *pipe,
 /**
  * Move raw block of pixels from user memory to surface.
  */
-static void
-softpipe_put_tile(struct pipe_context *pipe,
-                  struct pipe_surface *ps,
+void
+softpipe_put_tile(struct pipe_context *pipe, struct pipe_surface *ps,
                   uint x, uint y, uint w, uint h,
                   const void *p, int src_stride)
 {
index 7e08ce7a2b33c91c643af02d4d98d4eafa3172b0..cf87e1a92ce3d0c24d36ef9bf79aad0993074d1f 100644 (file)
@@ -45,6 +45,15 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
                          unsigned face, unsigned level, unsigned zslice);
 
 
+extern void
+softpipe_get_tile(struct pipe_context *pipe, struct pipe_surface *ps,
+                  uint x, uint y, uint w, uint h, void *p, int dst_stride);
+
+extern void
+softpipe_put_tile(struct pipe_context *pipe, struct pipe_surface *ps,
+                  uint x, uint y, uint w, uint h,
+                  const void *p, int src_stride);
+
 extern void
 softpipe_get_tile_rgba(struct pipe_context *pipe,
                        struct pipe_surface *ps,
index a5e0f7949451ecc16cff529e0a80eea0e7ca42c6..94fc2cae68b8519e8512356ec921e21bac9e4b8e 100644 (file)
@@ -70,19 +70,138 @@ xmesa_rb(struct pipe_surface *ps)
 #define FLIP(Y) Y = xrb->St.Base.Height - (Y) - 1;
 
 
+/**
+ * Return raw pixels from pixmap or XImage.
+ */
 void
 xmesa_get_tile(struct pipe_context *pipe, struct pipe_surface *ps,
                uint x, uint y, uint w, uint h, void *p, int dst_stride)
 {
+   struct xmesa_surface *xms = xmesa_surface(ps);
+   XMesaImage *ximage = NULL;
+   ubyte *dst = (ubyte *) p;
+   uint i;
+
+   if (!xms->drawable && !xms->ximage) {
+      /* not an X surface */
+      softpipe_get_tile(pipe, ps, x, y, w, h, p, dst_stride);
+      return;
+   }
+
+   if (!xms->ximage) {
+      /* XImage = pixmap data */
+      assert(xms->drawable);
+      ximage = XGetImage(xms->display, xms->drawable, x, y, w, h,
+                         AllPlanes, ZPixmap);
+      x = y = 0;
+   }
+   else {
+      ximage = xms->ximage;
+   }
+   
+   switch (ps->format) {
+   case PIPE_FORMAT_U_A8_R8_G8_B8:
+      if (!dst_stride) {
+         dst_stride = w * 4;
+      }
+      for (i = 0; i < h; i++) {
+         memcpy(dst, ximage->data + y * ximage->bytes_per_line + x * 4, 4 * w);
+         dst += dst_stride;
+      }
+      break;
+   case PIPE_FORMAT_U_R5_G6_B5:
+      if (!dst_stride) {
+         dst_stride = w * 2;
+      }
+      for (i = 0; i < h; i++) {
+         memcpy(dst, ximage->data + y * ximage->bytes_per_line + x * 2, 4 * 2);
+         dst += dst_stride;
+      }
+      break;
+   default:
+      assert(0);
+   }
 
+   if (!xms->ximage) {
+      XMesaDestroyImage(ximage);
+   }
 }
 
 
+/**
+ * Put raw pixels into pixmap or XImage.
+ */
 void
 xmesa_put_tile(struct pipe_context *pipe, struct pipe_surface *ps,
                uint x, uint y, uint w, uint h, const void *p, int src_stride)
 {
+   struct xmesa_surface *xms = xmesa_surface(ps);
+   const ubyte *src = (const ubyte *) p;
+   XMesaImage *ximage;
 
+   if (!xms->drawable && !xms->ximage) {
+      /* not an X surface */
+      softpipe_put_tile(pipe, ps, x, y, w, h, p, src_stride);
+      return;
+   }
+
+   if (xms->ximage) {
+      /* put to ximage */
+      ximage = xms->ximage;
+      char *dst;
+      int i;
+
+      switch (ps->format) {
+      case PIPE_FORMAT_U_A8_R8_G8_B8:
+         if (!src_stride) {
+            src_stride = w * 4;
+         }
+         dst = ximage->data + y * ximage->bytes_per_line + x * 4;
+         for (i = 0; i < h; i++) {
+            memcpy(dst, src, w * 4);
+            dst += ximage->bytes_per_line;
+            src += src_stride;
+         }
+         break;
+      case PIPE_FORMAT_U_R5_G6_B5:
+         if (!src_stride) {
+            src_stride = w * 2;
+         }
+         dst = ximage->data + y * ximage->bytes_per_line + x * 2;
+         for (i = 0; i < h; i++) {
+            memcpy(dst, src, w * 2);
+            dst += ximage->bytes_per_line;
+            src += src_stride;
+         }
+         break;
+      default:
+         assert(0);
+      }
+   }
+   else {
+      /* put to pixmap/window */
+      /* Create temp XImage for data */
+#ifdef XFree86Server
+      ximage = XMesaCreateImage(GET_VISUAL_DEPTH(v), w, h, p);
+#else
+      XVisualInfo *visinfo = xms->xrb->Parent->xm_visual->visinfo;
+      ximage = XCreateImage(xms->display,
+                            visinfo->visual,
+                            visinfo->depth,
+                            ZPixmap, 0,   /* format, offset */
+                            (char *) p,   /* data */
+                            w, h,         /* width, height */
+                            32,           /* bitmap_pad */
+                            0);           /* bytes_per_line */
+#endif
+
+      /* send XImage data to pixmap */
+      XPutImage(xms->display, xms->drawable, xms->gc,
+                ximage, 0, 0, x, y, w, h);
+      /* clean-up */
+      ximage->data = NULL; /* prevents freeing user data at 'p' */
+      XMesaDestroyImage(ximage);
+   }
 }