st/glx: Implement texture_from_pixmap without DRI.
authorStéphane Marchesin <marcheu@chromium.org>
Mon, 24 Oct 2011 19:03:16 +0000 (12:03 -0700)
committerStéphane Marchesin <marcheu@chromium.org>
Tue, 25 Oct 2011 21:35:46 +0000 (14:35 -0700)
Makes texture_from_pixmap work with non-DRI llvmpipe.

src/gallium/state_trackers/glx/xlib/xm_api.c
src/gallium/state_trackers/glx/xlib/xm_st.c
src/gallium/state_trackers/glx/xlib/xm_st.h

index ed786caaa43f1a5e5f4093d48aa65d78b312bdee..d80e7c816f4cdbb4ec896b5ec87ef5f018426b81 100644 (file)
 #include "xm_api.h"
 #include "xm_st.h"
 
+#include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
-#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
 #include "util/u_atomic.h"
+#include "util/u_inlines.h"
 
 #include "xm_public.h"
 #include <GL/glx.h>
@@ -1306,12 +1309,103 @@ void XMesaGarbageCollect( void )
 }
 
 
+static enum st_attachment_type xmesa_attachment_type(int glx_attachment)
+{
+   switch(glx_attachment) {
+      case GLX_FRONT_LEFT_EXT:
+         return ST_ATTACHMENT_FRONT_LEFT;
+      case GLX_FRONT_RIGHT_EXT:
+         return ST_ATTACHMENT_FRONT_RIGHT;
+      case GLX_BACK_LEFT_EXT:
+         return ST_ATTACHMENT_BACK_LEFT;
+      case GLX_BACK_RIGHT_EXT:
+         return ST_ATTACHMENT_BACK_RIGHT;
+      default:
+         assert(0);
+         return ST_ATTACHMENT_FRONT_LEFT;
+   }
+}
 
 
 PUBLIC void
 XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
                   const int *attrib_list)
 {
+   struct st_context_iface *st = stapi->get_current(stapi);
+   struct st_framebuffer_iface* stfbi = drawable->stfb;
+   struct pipe_resource *res;
+   int x, y, w, h;
+   XMesaContext xmesa = XMesaGetCurrentContext();
+   enum st_attachment_type st_attachment = xmesa_attachment_type(buffer);
+
+   x = 0;
+   y = 0;
+   w = drawable->width;
+   h = drawable->height;
+
+   /* We need to validate our attachments before using them,
+    * in case the texture doesn't exist yet. */
+   xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment);
+   res = xmesa_get_attachment(stfbi, st_attachment);
+
+   if (res) {
+      struct pipe_context* pipe = xmesa_get_context(stfbi);
+      enum pipe_format internal_format = res->format;
+      struct pipe_transfer *tex_xfer;
+      char *map;
+      int line, ximage_stride;
+
+      internal_format = choose_pixel_format(drawable->xm_visual);
+
+      tex_xfer = pipe_get_transfer(pipe, res,
+                                   0, 0,    /* level, layer */
+                                   PIPE_TRANSFER_WRITE,
+                                   x, y,
+                                   w, h);
+      if (!tex_xfer)
+         return;
+
+      /* Grab the XImage that we want to turn into a texture. */
+      XImage *img = XGetImage(dpy,
+                              drawable->ws.drawable,
+                              x, y,
+                              w, h,
+                              AllPlanes,
+                              ZPixmap);
+
+      if (!img) {
+         pipe_transfer_destroy(pipe, tex_xfer);
+         return;
+      }
+
+      map = pipe_transfer_map(pipe, tex_xfer);
+
+      if (!map) {
+         pipe_transfer_destroy(pipe, tex_xfer);
+         return;
+      }
+
+      /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
+         We assume 32 bit pixels. */
+      ximage_stride = w * 4;
+
+      for (line = 0; line < h; line++)
+         memcpy(&map[line * tex_xfer->stride],
+                &img->data[line * ximage_stride],
+                ximage_stride);
+
+      pipe_transfer_unmap(pipe, tex_xfer);
+
+      pipe_transfer_destroy(pipe, tex_xfer);
+
+      st->teximage(st,
+                   ST_TEXTURE_2D,
+                   0,    /* level */
+                   internal_format,
+                   res,
+                   FALSE /* no mipmap */);
+
+   }
 }
 
 
index ec3f531f7dff3a0f5164524844e8fea25cbb4038..f6439dc831ba206c2e6025bc1ad8d750edd91617 100644 (file)
@@ -97,13 +97,7 @@ xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
    if (!src_ptex || !dst_ptex)
       return;
 
-   pipe = xstfb->display->pipe;
-   if (!pipe) {
-      pipe = xstfb->screen->context_create(xstfb->screen, NULL);
-      if (!pipe)
-         return;
-      xstfb->display->pipe = pipe;
-   }
+   pipe = xmesa_get_context(stfbi);
 
    u_box_2d(x, y, width, height, &src_box);
 
@@ -116,7 +110,7 @@ xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi,
  * Remove outdated textures and create the requested ones.
  * This is a helper used during framebuffer validation.
  */
-static boolean
+boolean
 xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
                                        unsigned width, unsigned height,
                                        unsigned mask)
@@ -362,3 +356,31 @@ xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
    if (dst == ST_ATTACHMENT_FRONT_LEFT)
       xmesa_st_framebuffer_display(stfbi, dst);
 }
+
+struct pipe_resource*
+xmesa_get_attachment(struct st_framebuffer_iface *stfbi,
+                     enum st_attachment_type st_attachment)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+   struct pipe_resource* res;
+
+   res = xstfb->textures[st_attachment];
+   return res;
+}
+
+struct pipe_context*
+xmesa_get_context(struct st_framebuffer_iface* stfbi)
+{
+   struct pipe_context *pipe;
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+
+   pipe = xstfb->display->pipe;
+   if (!pipe) {
+      pipe = xstfb->screen->context_create(xstfb->screen, NULL);
+      if (!pipe)
+         return NULL;
+      xstfb->display->pipe = pipe;
+   }
+   return pipe;
+}
+
index 862597617e30c6a47c90a9d5f44edcd51d455fcd..a293728123782c2e1d64d9ffe17a3f9403046c9f 100644 (file)
@@ -49,4 +49,15 @@ xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
                           enum st_attachment_type dst,
                           int x, int y, int w, int h);
 
+struct pipe_resource*
+xmesa_get_attachment(struct st_framebuffer_iface *stfbi,
+                     enum st_attachment_type st_attachment);
+
+struct pipe_context*
+xmesa_get_context(struct st_framebuffer_iface* stfbi);
+
+boolean
+xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
+                                       unsigned width, unsigned height,
+                                       unsigned mask);
 #endif /* _XM_ST_H_ */