aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStéphane Marchesin <[email protected]>2011-10-24 12:03:16 -0700
committerStéphane Marchesin <[email protected]>2011-10-25 14:35:46 -0700
commit00ddc7ea47fdae09ca154d8b3a15c6f9a4926d68 (patch)
treee8d31858387df383854f5ea79e187682ae776939
parentb1d93d2aa8395608e77f1c538aa2234ced3dda75 (diff)
st/glx: Implement texture_from_pixmap without DRI.
Makes texture_from_pixmap work with non-DRI llvmpipe.
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.c96
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_st.c38
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_st.h11
3 files changed, 136 insertions, 9 deletions
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
index ed786caaa43..d80e7c816f4 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
@@ -56,10 +56,13 @@
#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 */);
+
+ }
}
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c
index ec3f531f7df..f6439dc831b 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_st.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_st.c
@@ -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;
+}
+
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h
index 862597617e3..a2937281237 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_st.h
+++ b/src/gallium/state_trackers/glx/xlib/xm_st.h
@@ -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_ */