From: Stéphane Marchesin Date: Mon, 24 Oct 2011 19:03:16 +0000 (-0700) Subject: st/glx: Implement texture_from_pixmap without DRI. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00ddc7ea47fdae09ca154d8b3a15c6f9a4926d68;p=mesa.git st/glx: Implement texture_from_pixmap without DRI. Makes texture_from_pixmap work with non-DRI llvmpipe. --- 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 @@ -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_ */