st/glx: Implement texture_from_pixmap without DRI.
Makes texture_from_pixmap work with non-DRI llvmpipe.
This commit is contained in:
@@ -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 */);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user