st/glx: Implement texture_from_pixmap without DRI.

Makes texture_from_pixmap work with non-DRI llvmpipe.
This commit is contained in:
Stéphane Marchesin
2011-10-24 12:03:16 -07:00
parent b1d93d2aa8
commit 00ddc7ea47
3 changed files with 136 additions and 9 deletions
+95 -1
View File
@@ -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 */);
}
}
+30 -8
View 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;
}
@@ -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_ */