mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 19:40:10 +01:00
Overhaul the Xlib winsys layer.
Front/back color buffers are now allocated with ordinary malloc() via the winsys buffer functions. To display surfaces in SwapBuffers() or flush_frontbuffer() we create an XImage that wraps the surface, then use XPutImage to copy to the window. Shared memory transport disabled for now.
This commit is contained in:
parent
f77ce9e4fa
commit
749d723287
7 changed files with 259 additions and 2365 deletions
|
|
@ -1433,7 +1433,6 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
glxCtx->xmesaContext->direct = GL_FALSE;
|
||||
glxCtx->glxContext.isDirect = GL_FALSE;
|
||||
glxCtx->glxContext.currentDpy = dpy;
|
||||
glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
|
||||
|
|
@ -1565,7 +1564,7 @@ Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
|
|||
if (!b) {
|
||||
return 0;
|
||||
}
|
||||
return b->frontxrb->pixmap;
|
||||
return b->drawable;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1591,7 +1590,7 @@ Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
|
|||
if (!b) {
|
||||
return 0;
|
||||
}
|
||||
return b->frontxrb->pixmap;
|
||||
return b->drawable;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1662,9 +1661,9 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
|
|||
static Bool
|
||||
Fake_glXIsDirect( Display *dpy, GLXContext ctx )
|
||||
{
|
||||
struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
|
||||
(void) dpy;
|
||||
return glxCtx->xmesaContext->direct;
|
||||
(void) ctx;
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2360,7 +2359,7 @@ Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
|
|||
* glXMakeCurrent takes.
|
||||
*/
|
||||
if (xmbuf)
|
||||
return (GLXPbuffer) xmbuf->frontxrb->pixmap;
|
||||
return (GLXPbuffer) xmbuf->drawable;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2444,7 +2443,6 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
glxCtx->xmesaContext->direct = GL_FALSE;
|
||||
glxCtx->glxContext.isDirect = GL_FALSE;
|
||||
glxCtx->glxContext.currentDpy = dpy;
|
||||
glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
|
||||
|
|
@ -2642,7 +2640,7 @@ Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixm
|
|||
{
|
||||
XMesaVisual xmvis = (XMesaVisual) config;
|
||||
XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
|
||||
return xmbuf->frontxrb->pixmap; /* need to return an X ID */
|
||||
return xmbuf->drawable; /* need to return an X ID */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2667,7 +2665,6 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re
|
|||
return NULL;
|
||||
}
|
||||
|
||||
glxCtx->xmesaContext->direct = GL_FALSE;
|
||||
glxCtx->glxContext.isDirect = GL_FALSE;
|
||||
glxCtx->glxContext.currentDpy = dpy;
|
||||
glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
|
||||
|
|
@ -2736,7 +2733,7 @@ Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
|
|||
/* A GLXPbuffer handle must be an X Drawable because that's what
|
||||
* glXMakeCurrent takes.
|
||||
*/
|
||||
return (GLXPbuffer) xmbuf->frontxrb->pixmap;
|
||||
return (GLXPbuffer) xmbuf->drawable;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -41,7 +41,6 @@
|
|||
#include "state_tracker/st_context.h"
|
||||
|
||||
|
||||
#if defined(USE_XSHM) && !defined(XFree86Server)
|
||||
static volatile int mesaXErrorFlag = 0;
|
||||
|
||||
/**
|
||||
|
|
@ -458,8 +457,8 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb)
|
|||
if (!xmesa_find_buffer(b->display, b->cmap, b)) {
|
||||
#ifdef XFree86Server
|
||||
int client = 0;
|
||||
if (b->frontxrb->drawable)
|
||||
client = CLIENT_ID(b->frontxrb->drawable->id);
|
||||
if (b->drawable)
|
||||
client = CLIENT_ID(b->drawable->id);
|
||||
(void)FreeColors(b->cmap, client,
|
||||
b->num_alloced, b->alloced_colors, 0);
|
||||
#else
|
||||
|
|
@ -478,21 +477,6 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb)
|
|||
|
||||
if (fb->Visual.doubleBufferMode) {
|
||||
/* free back ximage/pixmap/shmregion */
|
||||
if (b->backxrb->ximage) {
|
||||
#if defined(USE_XSHM) && !defined(XFree86Server)
|
||||
if (b->shm) {
|
||||
XShmDetach( b->display, &b->shminfo );
|
||||
XDestroyImage( b->backxrb->ximage );
|
||||
shmdt( b->shminfo.shmaddr );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
XMesaDestroyImage( b->backxrb->ximage );
|
||||
b->backxrb->ximage = NULL;
|
||||
}
|
||||
if (b->backxrb->pixmap) {
|
||||
XMesaFreePixmap( b->display, b->backxrb->pixmap );
|
||||
}
|
||||
}
|
||||
|
||||
if (b->rowimage) {
|
||||
|
|
|
|||
|
|
@ -70,689 +70,6 @@ const int xmesa_kernel1[16] = {
|
|||
|
||||
|
||||
|
||||
#define CLIP_TILE \
|
||||
do { \
|
||||
if (x >= ps->width) \
|
||||
return; \
|
||||
if (y >= ps->height) \
|
||||
return; \
|
||||
if (x + w > ps->width) \
|
||||
w = ps->width - x; \
|
||||
if (y + h > ps->height) \
|
||||
h = ps->height -y; \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are used to trap XGetImage() calls which
|
||||
* generate BadMatch errors if the drawable isn't mapped.
|
||||
*/
|
||||
|
||||
#ifndef XFree86Server
|
||||
static int caught_xgetimage_error = 0;
|
||||
static int (*old_xerror_handler)( XMesaDisplay *dpy, XErrorEvent *ev );
|
||||
static unsigned long xgetimage_serial;
|
||||
|
||||
/*
|
||||
* This is the error handler which will be called if XGetImage fails.
|
||||
*/
|
||||
static int xgetimage_error_handler( XMesaDisplay *dpy, XErrorEvent *ev )
|
||||
{
|
||||
if (ev->serial==xgetimage_serial && ev->error_code==BadMatch) {
|
||||
/* caught the expected error */
|
||||
caught_xgetimage_error = 0;
|
||||
}
|
||||
else {
|
||||
/* call the original X error handler, if any. otherwise ignore */
|
||||
if (old_xerror_handler) {
|
||||
(*old_xerror_handler)( dpy, ev );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Call this right before XGetImage to setup error trap.
|
||||
*/
|
||||
static void catch_xgetimage_errors( XMesaDisplay *dpy )
|
||||
{
|
||||
xgetimage_serial = NextRequest( dpy );
|
||||
old_xerror_handler = XSetErrorHandler( xgetimage_error_handler );
|
||||
caught_xgetimage_error = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Call this right after XGetImage to check if an error occured.
|
||||
*/
|
||||
static int check_xgetimage_errors( void )
|
||||
{
|
||||
/* restore old handler */
|
||||
(void) XSetErrorHandler( old_xerror_handler );
|
||||
/* return 0=no error, 1=error caught */
|
||||
return caught_xgetimage_error;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for XGetImage() that catches BadMatch errors that can occur
|
||||
* when the window is unmapped or the x/y/w/h extend beyond the window
|
||||
* bounds.
|
||||
* If build into xserver, wrap the internal GetImage method.
|
||||
*/
|
||||
static XMesaImage *
|
||||
xget_image(XMesaDisplay *dpy, Drawable d, int x, int y, uint w, uint h)
|
||||
{
|
||||
#ifdef XFree86Server
|
||||
uint bpp = 4; /* XXX fix this */
|
||||
XMesaImage *ximage = (XMesaImage *) malloc(sizeof(XMesaImage));
|
||||
if (ximage) {
|
||||
ximage->data = malloc(width * height * bpp);
|
||||
}
|
||||
(*dpy->GetImage)(d, x, y, w, h, ZPixmap, ~0L, (pointer)ximage->data);
|
||||
ximage->width = w;
|
||||
ximage->height = h;
|
||||
ximage->bytes_per_row = w * bpp;
|
||||
return ximage;
|
||||
#else
|
||||
int error;
|
||||
XMesaImage *ximage;
|
||||
catch_xgetimage_errors(dpy);
|
||||
ximage = XGetImage(dpy, d, x, y, w, h, AllPlanes, ZPixmap);
|
||||
error = check_xgetimage_errors();
|
||||
return ximage;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return raw pixels from pixmap or XImage.
|
||||
*/
|
||||
void
|
||||
xmesa_get_tile(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, void *p, int dst_stride)
|
||||
{
|
||||
const uint w0 = w;
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
XMesaImage *ximage = NULL;
|
||||
ubyte *dst = (ubyte *) p;
|
||||
uint i;
|
||||
|
||||
if (!xms->drawable && !xms->ximage) {
|
||||
/* not an X surface */
|
||||
softpipe_get_tile(pipe, ps, x, y, w, h, p, dst_stride);
|
||||
return;
|
||||
}
|
||||
|
||||
CLIP_TILE;
|
||||
|
||||
if (!xms->ximage) {
|
||||
/* XImage = pixmap data */
|
||||
assert(xms->drawable);
|
||||
ximage = xget_image(xms->display, xms->drawable, x, y, w, h);
|
||||
if (!ximage)
|
||||
return;
|
||||
x = y = 0;
|
||||
}
|
||||
else {
|
||||
ximage = xms->ximage;
|
||||
}
|
||||
|
||||
/* this could be optimized/simplified */
|
||||
switch (ps->format) {
|
||||
case PIPE_FORMAT_U_A8_R8_G8_B8:
|
||||
if (!dst_stride) {
|
||||
dst_stride = w0 * 4;
|
||||
}
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy(dst, ximage->data + y * ximage->bytes_per_line + x * 4, 4 * w);
|
||||
dst += dst_stride;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_U_R5_G6_B5:
|
||||
if (!dst_stride) {
|
||||
dst_stride = w0 * 2;
|
||||
}
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy(dst, ximage->data + y * ximage->bytes_per_line + x * 2, 4 * 2);
|
||||
dst += dst_stride;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!xms->ximage) {
|
||||
XMesaDestroyImage(ximage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put raw pixels into pixmap or XImage.
|
||||
*/
|
||||
void
|
||||
xmesa_put_tile(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, const void *p, int src_stride)
|
||||
{
|
||||
const uint w0 = w;
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
const ubyte *src = (const ubyte *) p;
|
||||
XMesaImage *ximage;
|
||||
|
||||
if (!xms->drawable && !xms->ximage) {
|
||||
/* not an X surface */
|
||||
softpipe_put_tile(pipe, ps, x, y, w, h, p, src_stride);
|
||||
return;
|
||||
}
|
||||
|
||||
CLIP_TILE;
|
||||
|
||||
if (xms->ximage) {
|
||||
/* put to ximage */
|
||||
ximage = xms->ximage;
|
||||
char *dst;
|
||||
uint i;
|
||||
|
||||
/* this could be optimized/simplified */
|
||||
switch (ps->format) {
|
||||
case PIPE_FORMAT_U_A8_R8_G8_B8:
|
||||
if (!src_stride) {
|
||||
src_stride = w0 * 4;
|
||||
}
|
||||
dst = ximage->data + y * ximage->bytes_per_line + x * 4;
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy(dst, src, w * 4);
|
||||
dst += ximage->bytes_per_line;
|
||||
src += src_stride;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_U_R5_G6_B5:
|
||||
if (!src_stride) {
|
||||
src_stride = w0 * 2;
|
||||
}
|
||||
dst = ximage->data + y * ximage->bytes_per_line + x * 2;
|
||||
for (i = 0; i < h; i++) {
|
||||
memcpy(dst, src, w * 2);
|
||||
dst += ximage->bytes_per_line;
|
||||
src += src_stride;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* put to pixmap/window */
|
||||
/* Create temp XImage for data */
|
||||
#ifdef XFree86Server
|
||||
ximage = XMesaCreateImage(GET_VISUAL_DEPTH(v), w, h, p);
|
||||
#else
|
||||
XVisualInfo *visinfo = xms->xrb->Parent->xm_visual->visinfo;
|
||||
ximage = XCreateImage(xms->display,
|
||||
visinfo->visual,
|
||||
visinfo->depth,
|
||||
ZPixmap, 0, /* format, offset */
|
||||
(char *) p, /* data */
|
||||
w, h, /* width, height */
|
||||
32, /* bitmap_pad */
|
||||
0); /* bytes_per_line */
|
||||
#endif
|
||||
|
||||
/* send XImage data to pixmap */
|
||||
XPutImage(xms->display, xms->drawable, xms->gc,
|
||||
ximage, 0, 0, x, y, w, h);
|
||||
/* clean-up */
|
||||
ximage->data = NULL; /* prevents freeing user data at 'p' */
|
||||
XMesaDestroyImage(ximage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xmesa_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, float *pixels)
|
||||
{
|
||||
const uint w0 = w;
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
XMesaImage *ximage = NULL;
|
||||
float *pRow = pixels;
|
||||
uint i, j;
|
||||
|
||||
if (!xms->drawable && !xms->ximage) {
|
||||
/* not an X surface */
|
||||
softpipe_get_tile_rgba(pipe, ps, x, y, w, h, pixels);
|
||||
return;
|
||||
}
|
||||
|
||||
CLIP_TILE;
|
||||
|
||||
if (!xms->ximage) {
|
||||
/* XImage = pixmap data */
|
||||
assert(xms->drawable);
|
||||
ximage = xget_image(xms->display, xms->drawable, x, y, w, h);
|
||||
if (!ximage)
|
||||
return;
|
||||
x = y = 0;
|
||||
}
|
||||
else {
|
||||
ximage = xms->ximage;
|
||||
}
|
||||
|
||||
switch (ps->format) {
|
||||
case PIPE_FORMAT_U_A8_R8_G8_B8:
|
||||
{
|
||||
const uint *src
|
||||
= (uint *) (ximage->data + y * ximage->bytes_per_line + x * 4);
|
||||
for (i = 0; i < h; i++) {
|
||||
float *p = pRow;
|
||||
for (j = 0; j < w; j++) {
|
||||
uint pix = src[j];
|
||||
ubyte r = ((pix >> 16) & 0xff);
|
||||
ubyte g = ((pix >> 8) & 0xff);
|
||||
ubyte b = ( pix & 0xff);
|
||||
ubyte a = ((pix >> 24) & 0xff);
|
||||
p[0] = UBYTE_TO_FLOAT(r);
|
||||
p[1] = UBYTE_TO_FLOAT(g);
|
||||
p[2] = UBYTE_TO_FLOAT(b);
|
||||
p[3] = UBYTE_TO_FLOAT(a);
|
||||
p += 4;
|
||||
}
|
||||
src += ximage->width;
|
||||
pRow += 4 * w0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_U_B8_G8_R8_A8:
|
||||
{
|
||||
const uint *src
|
||||
= (uint *) (ximage->data + y * ximage->bytes_per_line + x * 4);
|
||||
for (i = 0; i < h; i++) {
|
||||
float *p = pRow;
|
||||
for (j = 0; j < w; j++) {
|
||||
uint pix = src[j];
|
||||
ubyte r = ((pix >> 8) & 0xff);
|
||||
ubyte g = ((pix >> 16) & 0xff);
|
||||
ubyte b = ((pix >> 24) & 0xff);
|
||||
ubyte a = ( pix & 0xff);
|
||||
p[0] = UBYTE_TO_FLOAT(r);
|
||||
p[1] = UBYTE_TO_FLOAT(g);
|
||||
p[2] = UBYTE_TO_FLOAT(b);
|
||||
p[3] = UBYTE_TO_FLOAT(a);
|
||||
p += 4;
|
||||
}
|
||||
src += ximage->width;
|
||||
pRow += 4 * w0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_U_R5_G6_B5:
|
||||
{
|
||||
ushort *src
|
||||
= (ushort *) (ximage->data + y * ximage->bytes_per_line + x * 2);
|
||||
for (i = 0; i < h; i++) {
|
||||
float *p = pRow;
|
||||
for (j = 0; j < w; j++) {
|
||||
uint pix = src[j];
|
||||
ubyte r = (pix >> 8) | ((pix >> 13) & 0x7);
|
||||
ubyte g = (pix >> 3) | ((pix >> 9) & 0x3);
|
||||
ubyte b = ((pix & 0x1f) << 3) | ((pix >> 2) & 0x3);
|
||||
p[0] = UBYTE_TO_FLOAT(r);
|
||||
p[1] = UBYTE_TO_FLOAT(g);
|
||||
p[2] = UBYTE_TO_FLOAT(b);
|
||||
p[3] = 1.0;
|
||||
p += 4;
|
||||
}
|
||||
src += ximage->width;
|
||||
pRow += 4 * w0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Bad format in xmesa_get_tile_rgba()\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!xms->ximage) {
|
||||
XMesaDestroyImage(ximage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xmesa_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, const float *pixels)
|
||||
{
|
||||
const uint x0 = x, y0 = y, w0 = w;
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
XMesaImage *ximage;
|
||||
uint i, j;
|
||||
|
||||
if (!xms->drawable && !xms->ximage) {
|
||||
/* not an X surface */
|
||||
softpipe_put_tile_rgba(pipe, ps, x, y, w, h, pixels);
|
||||
return;
|
||||
}
|
||||
|
||||
CLIP_TILE;
|
||||
|
||||
if (!xms->ximage) {
|
||||
/* create temp XImage */
|
||||
char *data = (char *) malloc(w * h * 4);
|
||||
#ifdef XFree86Server
|
||||
ximage = XMesaCreateImage(GET_VISUAL_DEPTH(v), w, h, data);
|
||||
#else
|
||||
XVisualInfo *visinfo = xms->xrb->Parent->xm_visual->visinfo;
|
||||
ximage = XCreateImage(xms->display,
|
||||
visinfo->visual,
|
||||
visinfo->depth,
|
||||
ZPixmap, 0, /* format, offset */
|
||||
data, /* data */
|
||||
w, h, /* width, height */
|
||||
32, /* bitmap_pad */
|
||||
0); /* bytes_per_line */
|
||||
#endif
|
||||
x = y = 0;
|
||||
}
|
||||
else {
|
||||
ximage = xms->ximage;
|
||||
}
|
||||
|
||||
/* convert floats to ximage's format */
|
||||
switch (ps->format) {
|
||||
case PIPE_FORMAT_U_A8_R8_G8_B8:
|
||||
{
|
||||
uint *dst
|
||||
= (uint *) (ximage->data + y * ximage->bytes_per_line + x * 4);
|
||||
const float *pRow = pixels;
|
||||
for (i = 0; i < h; i++) {
|
||||
const float *p = pRow;
|
||||
for (j = 0; j < w; j++) {
|
||||
ubyte r, g, b, a;
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(r, p[0]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(g, p[1]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(b, p[2]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(a, p[3]);
|
||||
dst[j] = PACK_8A8R8G8B(r, g, b, a);
|
||||
p += 4;
|
||||
}
|
||||
dst += ximage->width;
|
||||
pRow += 4 * w0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_U_B8_G8_R8_A8:
|
||||
{
|
||||
uint *dst
|
||||
= (uint *) (ximage->data + y * ximage->bytes_per_line + x * 4);
|
||||
const float *pRow = pixels;
|
||||
for (i = 0; i < h; i++) {
|
||||
const float *p = pRow;
|
||||
for (j = 0; j < w; j++) {
|
||||
ubyte r, g, b, a;
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(r, p[0]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(g, p[1]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(b, p[2]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(a, p[3]);
|
||||
dst[j] = PACK_8B8G8R8A(r, g, b, a);
|
||||
p += 4;
|
||||
}
|
||||
dst += ximage->width;
|
||||
pRow += 4 * w0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_U_R5_G6_B5:
|
||||
{
|
||||
ushort *dst =
|
||||
(ushort *) (ximage->data + y * ximage->bytes_per_line + x * 2);
|
||||
const float *pRow = pixels;
|
||||
for (i = 0; i < h; i++) {
|
||||
const float *p = pRow;
|
||||
for (j = 0; j < w; j++) {
|
||||
ubyte r, g, b;
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(r, p[0]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(g, p[1]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(b, p[2]);
|
||||
dst[j] = PACK_5R6G5B(r, g, b);
|
||||
p += 4;
|
||||
}
|
||||
dst += ximage->width;
|
||||
pRow += 4 * w0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Bad format in xmesa_put_tile_rgba()\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!xms->ximage) {
|
||||
/* send XImage data to pixmap */
|
||||
XPutImage(xms->display, xms->drawable, xms->gc,
|
||||
ximage, 0, 0, x0, y0, w, h);
|
||||
/* clean-up */
|
||||
free(ximage->data);
|
||||
ximage->data = NULL;
|
||||
XMesaDestroyImage(ximage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clear_pixmap_surface(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
assert(xms);
|
||||
assert(xms->display);
|
||||
assert(xms->drawable);
|
||||
assert(xms->gc);
|
||||
XMesaSetForeground( xms->display, xms->gc, value );
|
||||
XMesaFillRectangle( xms->display, xms->drawable, xms->gc,
|
||||
0, 0, ps->width, ps->height);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_nbit_ximage_surface(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
int width = xms->surface.width;
|
||||
int height = xms->surface.height;
|
||||
int i, j;
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
XMesaPutPixel(xms->ximage, i, j, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_8bit_ximage_surface(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
memset(xms->ximage->data,
|
||||
value,
|
||||
xms->ximage->bytes_per_line * xms->ximage->height);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_16bit_ximage_surface(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
const int n = xms->ximage->width * xms->ximage->height;
|
||||
ushort *dst = (ushort *) xms->ximage->data;
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
dst[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
|
||||
static void
|
||||
clear_24bit_ximage_surface(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
const ubyte r = (value ) & 0xff;
|
||||
const ubyte g = (value >> 8) & 0xff;
|
||||
const ubyte b = (value >> 16) & 0xff;
|
||||
|
||||
if (r == g && g == b) {
|
||||
/* same value for all three components (gray) */
|
||||
memset(xms->ximage->data, r,
|
||||
xms->ximage->bytes_per_line * xms->ximage->height);
|
||||
}
|
||||
else {
|
||||
/* non-gray clear color */
|
||||
const int n = xms->ximage->width * xms->ximage->height;
|
||||
int i;
|
||||
bgr_t *ptr3 = (bgr_t *) xms->ximage->data;
|
||||
for (i = 0; i < n; i++) {
|
||||
ptr3->r = r;
|
||||
ptr3->g = g;
|
||||
ptr3->b = b;
|
||||
ptr3++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_32bit_ximage_surface(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
|
||||
if (value == 0) {
|
||||
/* common case */
|
||||
memset(xms->ximage->data, value,
|
||||
xms->ximage->bytes_per_line * xms->ximage->height);
|
||||
}
|
||||
else {
|
||||
const int n = xms->ximage->width * xms->ximage->height;
|
||||
uint *dst = (uint *) xms->ximage->data;
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called to create a pipe_surface for each X renderbuffer.
|
||||
* Note: this is being used instead of pipe->surface_alloc() since we
|
||||
* have special/unique quad read/write functions for X.
|
||||
*/
|
||||
struct pipe_surface *
|
||||
xmesa_new_color_surface(struct pipe_winsys *winsys, GLuint pipeFormat)
|
||||
{
|
||||
struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
|
||||
|
||||
assert(pipeFormat);
|
||||
|
||||
xms->surface.format = pipeFormat;
|
||||
xms->surface.refcount = 1;
|
||||
xms->surface.winsys = winsys;
|
||||
|
||||
/* Note, the buffer we allocate doesn't actually have any storage
|
||||
* since we're drawing into an XImage or Pixmap.
|
||||
* The surface's size will get set in the xmesa_alloc_front/back_storage()
|
||||
* functions.
|
||||
*/
|
||||
xms->surface.buffer = winsys->buffer_create(winsys, 0x0);
|
||||
|
||||
return &xms->surface;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->surface_alloc() to create new surfaces (textures,
|
||||
* renderbuffers, etc.
|
||||
*/
|
||||
struct pipe_surface *
|
||||
xmesa_surface_alloc(struct pipe_context *pipe, GLuint pipeFormat)
|
||||
{
|
||||
struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
|
||||
|
||||
assert(pipe);
|
||||
assert(pipeFormat);
|
||||
|
||||
xms->surface.format = pipeFormat;
|
||||
xms->surface.refcount = 1;
|
||||
xms->surface.winsys = pipe->winsys;
|
||||
|
||||
return &xms->surface;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via pipe->clear() to clear entire surface to a certain value.
|
||||
* If the surface is not an X pixmap or XImage, pass the call to
|
||||
* softpipe_clear().
|
||||
*/
|
||||
void
|
||||
xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, uint value)
|
||||
{
|
||||
struct xmesa_surface *xms = xmesa_surface(ps);
|
||||
|
||||
/* XXX actually, we should just discard any cached tiles from this
|
||||
* surface since we don't want to accidentally re-use them after clearing.
|
||||
*/
|
||||
pipe->flush(pipe, 0);
|
||||
|
||||
{
|
||||
struct softpipe_context *sp = softpipe_context(pipe);
|
||||
if (ps == sp_tile_cache_get_surface(sp, sp->cbuf_cache[0])) {
|
||||
float clear[4];
|
||||
clear[0] = 0.2; /* XXX hack */
|
||||
clear[1] = 0.2;
|
||||
clear[2] = 0.2;
|
||||
clear[3] = 0.2;
|
||||
sp_tile_cache_clear(sp->cbuf_cache[0], clear);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
(void) clear_8bit_ximage_surface;
|
||||
(void) clear_24bit_ximage_surface;
|
||||
#endif
|
||||
|
||||
if (xms->ximage) {
|
||||
/* back color buffer */
|
||||
switch (xms->surface.format) {
|
||||
case PIPE_FORMAT_U_R5_G6_B5:
|
||||
clear_16bit_ximage_surface(pipe, ps, value);
|
||||
break;
|
||||
case PIPE_FORMAT_U_A8_R8_G8_B8:
|
||||
case PIPE_FORMAT_U_B8_G8_R8_A8:
|
||||
clear_32bit_ximage_surface(pipe, ps, value);
|
||||
break;
|
||||
default:
|
||||
clear_nbit_ximage_surface(pipe, ps, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (xms->drawable) {
|
||||
/* front color buffer */
|
||||
clear_pixmap_surface(pipe, ps, value);
|
||||
}
|
||||
else {
|
||||
/* other kind of buffer */
|
||||
softpipe_clear(pipe, ps, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** XXX unfinished sketch... */
|
||||
struct pipe_surface *
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#include "main/macros.h"
|
||||
|
||||
#include "pipe/p_winsys.h"
|
||||
#include "pipe/p_format.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/softpipe/sp_winsys.h"
|
||||
|
||||
|
||||
|
|
@ -54,17 +56,52 @@ struct xm_buffer
|
|||
};
|
||||
|
||||
|
||||
struct xmesa_surface
|
||||
{
|
||||
struct pipe_surface surface;
|
||||
/* no extra fields for now */
|
||||
};
|
||||
|
||||
/* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
|
||||
|
||||
/**
|
||||
* Derived from softpipe_winsys.
|
||||
* We just need one extra field which indicates the pixel format to use for
|
||||
* drawing surfaces so that we're compatible with the XVisual/window format.
|
||||
*/
|
||||
struct xmesa_softpipe_winsys
|
||||
{
|
||||
struct softpipe_winsys spws;
|
||||
uint pixelformat;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Cast wrapper */
|
||||
static INLINE struct xmesa_surface *
|
||||
xmesa_surface(struct pipe_surface *ps)
|
||||
{
|
||||
assert(0);
|
||||
return (struct xmesa_surface *) ps;
|
||||
}
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE struct xmesa_softpipe_winsys *
|
||||
xmesa_softpipe_winsys(struct softpipe_winsys *spws)
|
||||
{
|
||||
return (struct xmesa_softpipe_winsys *) spws;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
|
||||
* buffer pointer...
|
||||
*/
|
||||
static inline struct xm_buffer *
|
||||
static INLINE struct xm_buffer *
|
||||
xm_bo( struct pipe_buffer_handle *bo )
|
||||
{
|
||||
return (struct xm_buffer *) bo;
|
||||
}
|
||||
|
||||
static inline struct pipe_buffer_handle *
|
||||
static INLINE struct pipe_buffer_handle *
|
||||
pipe_bo( struct xm_buffer *bo )
|
||||
{
|
||||
return (struct pipe_buffer_handle *) bo;
|
||||
|
|
@ -156,6 +193,33 @@ xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
|
|||
memcpy(data, b + offset, size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display/copy the image in the surface into the X window specified
|
||||
* by the XMesaBuffer.
|
||||
*/
|
||||
void
|
||||
xmesa_display_surface(XMesaBuffer b, const struct pipe_surface *surf)
|
||||
{
|
||||
XImage *ximage = b->tempImage;
|
||||
struct xm_buffer *xm_buf = xm_bo(surf->buffer);
|
||||
|
||||
/* check that the XImage has been previously initialized */
|
||||
assert(ximage->format);
|
||||
assert(ximage->bitmap_unit);
|
||||
|
||||
/* update XImage's fields */
|
||||
ximage->width = surf->width;
|
||||
ximage->height = surf->height;
|
||||
ximage->bytes_per_line = surf->pitch * (ximage->bits_per_pixel / 8);
|
||||
ximage->data = xm_buf->data;
|
||||
|
||||
/* display image in Window */
|
||||
XPutImage(b->xm_visual->display, b->drawable, b->gc,
|
||||
ximage, 0, 0, 0, 0, surf->width, surf->height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xm_flush_frontbuffer(struct pipe_winsys *pws,
|
||||
struct pipe_surface *surf,
|
||||
|
|
@ -166,9 +230,13 @@ xm_flush_frontbuffer(struct pipe_winsys *pws,
|
|||
* If we instead did front buffer rendering to a temporary XImage,
|
||||
* this would be the place to copy the Ximage to the on-screen Window.
|
||||
*/
|
||||
XMesaContext xmctx = (XMesaContext) context_private;
|
||||
|
||||
xmesa_display_surface(xmctx->xm_buffer, surf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
xm_printf(struct pipe_winsys *pws, const char *fmtString, ...)
|
||||
{
|
||||
|
|
@ -178,6 +246,7 @@ xm_printf(struct pipe_winsys *pws, const char *fmtString, ...)
|
|||
va_end( args );
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
xm_get_name(struct pipe_winsys *pws)
|
||||
{
|
||||
|
|
@ -219,7 +288,6 @@ round_up(unsigned n, unsigned multiple)
|
|||
return (n + multiple - 1) & ~(multiple - 1);
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
xm_surface_pitch(struct pipe_winsys *winsys, unsigned cpp, unsigned width,
|
||||
unsigned flags)
|
||||
|
|
@ -243,12 +311,7 @@ xm_surface_alloc(struct pipe_winsys *ws, GLuint pipeFormat)
|
|||
xms->surface.format = pipeFormat;
|
||||
xms->surface.refcount = 1;
|
||||
xms->surface.winsys = ws;
|
||||
#if 0
|
||||
/*
|
||||
* This is really just a softpipe surface, not an XImage/Pixmap surface.
|
||||
*/
|
||||
softpipe_init_surface_funcs(&xms->surface);
|
||||
#endif
|
||||
|
||||
return &xms->surface;
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +324,7 @@ xm_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
|
|||
surf->refcount--;
|
||||
if (surf->refcount == 0) {
|
||||
if (surf->buffer)
|
||||
winsys->buffer_reference(winsys, &surf->buffer, NULL);
|
||||
winsys->buffer_reference(winsys, &surf->buffer, NULL);
|
||||
free(surf);
|
||||
}
|
||||
*s = NULL;
|
||||
|
|
@ -274,7 +337,7 @@ xm_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
|
|||
* For Xlib, this is a singleton object.
|
||||
* Nothing special for the Xlib driver so no subclassing or anything.
|
||||
*/
|
||||
struct pipe_winsys *
|
||||
static struct pipe_winsys *
|
||||
xmesa_get_pipe_winsys(void)
|
||||
{
|
||||
static struct pipe_winsys *ws = NULL;
|
||||
|
|
@ -308,59 +371,65 @@ xmesa_get_pipe_winsys(void)
|
|||
|
||||
|
||||
/**
|
||||
* XXX this depends on the depths supported by the screen (8/16/32/etc).
|
||||
* Maybe when we're about to create a context/drawable we create a new
|
||||
* softpipe_winsys object that corresponds to the specified screen...
|
||||
* The winsys being queried will have been created at glXCreateContext
|
||||
* time, with a pixel format corresponding to the context's visual.
|
||||
*
|
||||
* Also, this query only really matters for on-screen drawables.
|
||||
* For textures and FBOs we (softpipe) can support any format.o
|
||||
* XXX we should pass a flag indicating if the format is going to be
|
||||
* use for a drawing surface vs. a texture. In the later case, we
|
||||
* can support any format.
|
||||
*/
|
||||
static boolean
|
||||
xmesa_is_format_supported(struct softpipe_winsys *sws, uint format)
|
||||
{
|
||||
/* Any format supported by softpipe can be listed here.
|
||||
* This query is not used for allocating window-system color buffers
|
||||
* (which would depend on the screen depth/bpp).
|
||||
*/
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_U_A8_R8_G8_B8:
|
||||
case PIPE_FORMAT_S_R16_G16_B16_A16:
|
||||
case PIPE_FORMAT_S8_Z24:
|
||||
case PIPE_FORMAT_U_S8:
|
||||
case PIPE_FORMAT_U_Z16:
|
||||
case PIPE_FORMAT_U_Z32:
|
||||
struct xmesa_softpipe_winsys *xmws = xmesa_softpipe_winsys(sws);
|
||||
|
||||
if (format == xmws->pixelformat) {
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
};
|
||||
}
|
||||
else {
|
||||
/* non-color / window surface format */
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_S_R16_G16_B16_A16:
|
||||
case PIPE_FORMAT_S8_Z24:
|
||||
case PIPE_FORMAT_U_S8:
|
||||
case PIPE_FORMAT_U_Z16:
|
||||
case PIPE_FORMAT_U_Z32:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to a softpipe_winsys object.
|
||||
* For Xlib, this is a singleton object.
|
||||
*/
|
||||
static struct softpipe_winsys *
|
||||
xmesa_get_softpipe_winsys(void)
|
||||
xmesa_get_softpipe_winsys(uint pixelformat)
|
||||
{
|
||||
static struct softpipe_winsys *spws = NULL;
|
||||
struct xmesa_softpipe_winsys *xmws
|
||||
= CALLOC_STRUCT(xmesa_softpipe_winsys);
|
||||
if (!xmws)
|
||||
return NULL;
|
||||
|
||||
if (!spws) {
|
||||
spws = CALLOC_STRUCT(softpipe_winsys);
|
||||
if (spws) {
|
||||
spws->is_format_supported = xmesa_is_format_supported;
|
||||
}
|
||||
}
|
||||
xmws->spws.is_format_supported = xmesa_is_format_supported;
|
||||
xmws->pixelformat = pixelformat;
|
||||
|
||||
return spws;
|
||||
return &xmws->spws;
|
||||
}
|
||||
|
||||
|
||||
struct pipe_context *
|
||||
xmesa_create_context(XMesaContext xmesa)
|
||||
xmesa_create_pipe_context(XMesaContext xmesa, uint pixelformat)
|
||||
{
|
||||
struct pipe_winsys *pws = xmesa_get_pipe_winsys();
|
||||
struct softpipe_winsys *spws = xmesa_get_softpipe_winsys();
|
||||
struct softpipe_winsys *spws = xmesa_get_softpipe_winsys(pixelformat);
|
||||
struct pipe_context *pipe;
|
||||
|
||||
return softpipe_create( pws, spws );
|
||||
pipe = softpipe_create( pws, spws );
|
||||
if (pipe)
|
||||
pipe->priv = xmesa;
|
||||
|
||||
return pipe;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,42 +32,15 @@
|
|||
#ifdef XFree86Server
|
||||
#include "xm_image.h"
|
||||
#endif
|
||||
#include "state_tracker/st_cb_fbo.h"
|
||||
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "state_tracker/st_public.h"
|
||||
#include "pipe/softpipe/sp_context.h"
|
||||
#include "pipe/softpipe/sp_surface.h"
|
||||
|
||||
|
||||
extern _glthread_Mutex _xmesa_lock;
|
||||
|
||||
extern XMesaBuffer XMesaBufferList;
|
||||
|
||||
/* for PF_8R8G8B24 pixel format */
|
||||
typedef struct {
|
||||
GLubyte b;
|
||||
GLubyte g;
|
||||
GLubyte r;
|
||||
} bgr_t;
|
||||
|
||||
|
||||
/** Framebuffer pixel formats */
|
||||
enum pixel_format {
|
||||
PF_Index, /**< Color Index mode */
|
||||
PF_Truecolor, /**< TrueColor or DirectColor, any depth */
|
||||
PF_Dither_True, /**< TrueColor with dithering */
|
||||
PF_8A8R8G8B, /**< 32-bit TrueColor: 8-A, 8-R, 8-G, 8-B bits */
|
||||
PF_8A8B8G8R, /**< 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R bits */
|
||||
PF_8R8G8B, /**< 32-bit TrueColor: 8-R, 8-G, 8-B bits */
|
||||
PF_8R8G8B24, /**< 24-bit TrueColor: 8-R, 8-G, 8-B bits */
|
||||
PF_5R6G5B, /**< 16-bit TrueColor: 5-R, 6-G, 5-B bits */
|
||||
PF_Dither, /**< Color-mapped RGB with dither */
|
||||
PF_Lookup, /**< Color-mapped RGB without dither */
|
||||
PF_1Bit, /**< monochrome dithering of RGB */
|
||||
PF_Grayscale, /**< Grayscale or StaticGray */
|
||||
PF_Dither_5R6G5B /**< 16-bit dithered TrueColor: 5-R, 6-G, 5-B */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Visual inforation, derived from GLvisual.
|
||||
|
|
@ -86,47 +59,17 @@ struct xmesa_visual {
|
|||
GLint BitsPerPixel; /* True bits per pixel for XImages */
|
||||
|
||||
GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
|
||||
|
||||
enum pixel_format dithered_pf; /* Pixel format when dithering */
|
||||
enum pixel_format undithered_pf;/* Pixel format when not dithering */
|
||||
|
||||
GLfloat RedGamma; /* Gamma values, 1.0 is default */
|
||||
GLfloat GreenGamma;
|
||||
GLfloat BlueGamma;
|
||||
|
||||
/* For PF_TRUECOLOR */
|
||||
GLint rshift, gshift, bshift;/* Pixel color component shifts */
|
||||
GLubyte Kernel[16]; /* Dither kernel */
|
||||
unsigned long RtoPixel[512]; /* RGB to pixel conversion */
|
||||
unsigned long GtoPixel[512];
|
||||
unsigned long BtoPixel[512];
|
||||
GLubyte PixelToR[256]; /* Pixel to RGB conversion */
|
||||
GLubyte PixelToG[256];
|
||||
GLubyte PixelToB[256];
|
||||
|
||||
/* For PF_1BIT */
|
||||
int bitFlip;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Context info, derived from GLcontext.
|
||||
* Context info, derived from st_context.
|
||||
* Basically corresponds to a GLXContext.
|
||||
*/
|
||||
struct xmesa_context {
|
||||
struct st_context *st;
|
||||
|
||||
XMesaVisual xm_visual; /* Describes the buffers */
|
||||
XMesaBuffer xm_buffer; /* current span/point/line/triangle buffer */
|
||||
|
||||
XMesaDisplay *display; /* == xm_visual->display */
|
||||
GLboolean swapbytes; /* Host byte order != display byte order? */
|
||||
GLboolean direct; /* Direct rendering context? */
|
||||
|
||||
enum pixel_format pixelformat;
|
||||
|
||||
GLubyte clearcolor[4]; /* current clearing color */
|
||||
unsigned long clearpixel; /* current clearing pixel value */
|
||||
XMesaVisual xm_visual; /** pixel format info */
|
||||
XMesaBuffer xm_buffer; /** current drawbuffer */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -141,46 +84,6 @@ typedef enum {
|
|||
} BufferType;
|
||||
|
||||
|
||||
/** Values for db_mode: */
|
||||
/*@{*/
|
||||
#define BACK_PIXMAP 1
|
||||
#define BACK_XIMAGE 2
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* An xmesa_renderbuffer represents the back or front color buffer.
|
||||
* For the front color buffer:
|
||||
* <drawable> is the X window
|
||||
* For the back color buffer:
|
||||
* Either <ximage> or <pixmap> will be used, never both.
|
||||
* In any case, <drawable> always equals <pixmap>.
|
||||
* For stand-alone Mesa, we could merge <drawable> and <pixmap> into one
|
||||
* field. We don't do that for the server-side GLcore module because
|
||||
* pixmaps and drawables are different and we'd need a bunch of casts.
|
||||
*/
|
||||
struct xmesa_renderbuffer
|
||||
{
|
||||
struct st_renderbuffer St; /**< Base class (XXX temporary?) */
|
||||
|
||||
XMesaBuffer Parent; /**< The XMesaBuffer this renderbuffer belongs to */
|
||||
XMesaDrawable drawable; /* Usually the X window ID */
|
||||
XMesaPixmap pixmap; /* Back color buffer */
|
||||
XMesaImage *ximage; /* The back buffer, if not using a Pixmap */
|
||||
|
||||
GLubyte *origin1; /* used for PIXEL_ADDR1 macro */
|
||||
GLint width1;
|
||||
GLushort *origin2; /* used for PIXEL_ADDR2 macro */
|
||||
GLint width2;
|
||||
GLubyte *origin3; /* used for PIXEL_ADDR3 macro */
|
||||
GLint width3;
|
||||
GLuint *origin4; /* used for PIXEL_ADDR4 macro */
|
||||
GLint width4;
|
||||
|
||||
GLint bottom; /* used for FLIP macro, equals height - 1 */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Framebuffer information, derived from.
|
||||
* Basically corresponds to a GLXDrawable.
|
||||
|
|
@ -190,22 +93,13 @@ struct xmesa_buffer {
|
|||
|
||||
GLboolean wasCurrent; /* was ever the current buffer? */
|
||||
XMesaVisual xm_visual; /* the X/Mesa visual */
|
||||
|
||||
XMesaDisplay *display;
|
||||
XMesaDrawable drawable; /* Usually the X window ID */
|
||||
XMesaColormap cmap; /* the X colormap */
|
||||
BufferType type; /* window, pixmap, pbuffer or glxwindow */
|
||||
|
||||
struct xmesa_renderbuffer *frontxrb; /* front color renderbuffer */
|
||||
struct xmesa_renderbuffer *backxrb; /* back color renderbuffer */
|
||||
|
||||
XMesaColormap cmap; /* the X colormap */
|
||||
|
||||
XMesaImage *tempImage;
|
||||
unsigned long selectedEvents;/* for pbuffers only */
|
||||
|
||||
GLint db_mode; /* 0 = single buffered */
|
||||
/* BACK_PIXMAP = use Pixmap for back buffer */
|
||||
/* BACK_XIMAGE = use XImage for back buffer */
|
||||
GLboolean swAlpha;
|
||||
|
||||
GLuint shm; /* X Shared Memory extension status: */
|
||||
/* 0 = not available */
|
||||
/* 1 = XImage support available */
|
||||
|
|
@ -214,33 +108,7 @@ struct xmesa_buffer {
|
|||
XShmSegmentInfo shminfo;
|
||||
#endif
|
||||
|
||||
XMesaImage *rowimage; /* Used for optimized span writing */
|
||||
XMesaPixmap stipple_pixmap; /* For polygon stippling */
|
||||
XMesaGC stipple_gc; /* For polygon stippling */
|
||||
|
||||
XMesaGC gc; /* scratch GC for span, line, tri drawing */
|
||||
XMesaGC cleargc; /* GC for clearing the color buffer */
|
||||
XMesaGC swapgc; /* GC for swapping the color buffers */
|
||||
|
||||
/* The following are here instead of in the XMesaVisual
|
||||
* because they depend on the window's colormap.
|
||||
*/
|
||||
|
||||
/* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
|
||||
unsigned long color_table[576]; /* RGB -> pixel value */
|
||||
|
||||
/* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
|
||||
GLubyte pixel_to_r[65536]; /* pixel value -> red */
|
||||
GLubyte pixel_to_g[65536]; /* pixel value -> green */
|
||||
GLubyte pixel_to_b[65536]; /* pixel value -> blue */
|
||||
|
||||
/* Used to do XAllocColor/XFreeColors accounting: */
|
||||
int num_alloced;
|
||||
#if defined(XFree86Server)
|
||||
Pixel alloced_colors[256];
|
||||
#else
|
||||
unsigned long alloced_colors[256];
|
||||
#endif
|
||||
|
||||
/* GLX_EXT_texture_from_pixmap */
|
||||
GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */
|
||||
|
|
@ -251,209 +119,23 @@ struct xmesa_buffer {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_TRUECOLOR:
|
||||
*/
|
||||
#define PACK_TRUECOLOR( PIXEL, R, G, B ) \
|
||||
PIXEL = xmesa->xm_visual->RtoPixel[R] \
|
||||
| xmesa->xm_visual->GtoPixel[G] \
|
||||
| xmesa->xm_visual->BtoPixel[B]; \
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_TRUEDITHER:
|
||||
*/
|
||||
#define PACK_TRUEDITHER( PIXEL, X, Y, R, G, B ) \
|
||||
{ \
|
||||
int d = xmesa->xm_visual->Kernel[((X)&3) | (((Y)&3)<<2)]; \
|
||||
PIXEL = xmesa->xm_visual->RtoPixel[(R)+d] \
|
||||
| xmesa->xm_visual->GtoPixel[(G)+d] \
|
||||
| xmesa->xm_visual->BtoPixel[(B)+d]; \
|
||||
/** cast wrapper */
|
||||
static INLINE XMesaContext
|
||||
xmesa_context(GLcontext *ctx)
|
||||
{
|
||||
return (XMesaContext) ctx->DriverCtx;
|
||||
}
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static INLINE XMesaBuffer
|
||||
xmesa_buffer(GLframebuffer *fb)
|
||||
{
|
||||
struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
|
||||
return (XMesaBuffer) st_framebuffer_private(stfb);
|
||||
}
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_8A8B8G8R:
|
||||
*/
|
||||
#define PACK_8A8B8G8R( R, G, B, A ) \
|
||||
( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
|
||||
|
||||
|
||||
/**
|
||||
* Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
|
||||
* shortcut.
|
||||
*/
|
||||
#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
|
||||
|
||||
#define PACK_8B8G8R8A( R, G, B, A ) \
|
||||
( ((B) << 24) | ((G) << 16) | ((R) << 8) | (A) )
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_8R8G8B:
|
||||
*/
|
||||
#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) )
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_5R6G5B:
|
||||
*/
|
||||
#define PACK_5R6G5B( R, G, B) ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_8A8R8G8B:
|
||||
*/
|
||||
#define PACK_8A8R8G8B( R, G, B, A ) \
|
||||
( ((A) << 24) | ((R) << 16) | ((G) << 8) | (B) )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_DITHER:
|
||||
*
|
||||
* Improved 8-bit RGB dithering code contributed by Bob Mercier
|
||||
* (mercier@hollywood.cinenet.net). Thanks Bob!
|
||||
*/
|
||||
#ifdef DITHER666
|
||||
# define DITH_R 6
|
||||
# define DITH_G 6
|
||||
# define DITH_B 6
|
||||
# define DITH_MIX(r,g,b) (((r) * DITH_G + (g)) * DITH_B + (b))
|
||||
#else
|
||||
# define DITH_R 5
|
||||
# define DITH_G 9
|
||||
# define DITH_B 5
|
||||
# define DITH_MIX(r,g,b) (((g) << 6) | ((b) << 3) | (r))
|
||||
#endif
|
||||
#define DITH_DX 4
|
||||
#define DITH_DY 4
|
||||
#define DITH_N (DITH_DX * DITH_DY)
|
||||
|
||||
#define _dither(C, c, d) (((unsigned)((DITH_N * (C - 1) + 1) * c + d)) >> 12)
|
||||
|
||||
#define MAXC 256
|
||||
extern const int xmesa_kernel8[DITH_DY * DITH_DX];
|
||||
|
||||
/* Dither for random X,Y */
|
||||
#define DITHER_SETUP \
|
||||
int __d; \
|
||||
unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table;
|
||||
|
||||
#define DITHER( X, Y, R, G, B ) \
|
||||
(__d = xmesa_kernel8[(((Y)&3)<<2) | ((X)&3)], \
|
||||
ctable[DITH_MIX(_dither(DITH_R, (R), __d), \
|
||||
_dither(DITH_G, (G), __d), \
|
||||
_dither(DITH_B, (B), __d))])
|
||||
|
||||
/* Dither for random X, fixed Y */
|
||||
#define XDITHER_SETUP(Y) \
|
||||
int __d; \
|
||||
unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table; \
|
||||
const int *kernel = &xmesa_kernel8[ ((Y)&3) << 2 ];
|
||||
|
||||
#define XDITHER( X, R, G, B ) \
|
||||
(__d = kernel[(X)&3], \
|
||||
ctable[DITH_MIX(_dither(DITH_R, (R), __d), \
|
||||
_dither(DITH_G, (G), __d), \
|
||||
_dither(DITH_B, (B), __d))])
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Dithering for flat-shaded triangles. Precompute all 16 possible
|
||||
* pixel values given the triangle's RGB color. Contributed by Martin Shenk.
|
||||
*/
|
||||
#define FLAT_DITHER_SETUP( R, G, B ) \
|
||||
GLushort ditherValues[16]; \
|
||||
{ \
|
||||
unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table; \
|
||||
int msdr = (DITH_N*((DITH_R)-1)+1) * (R); \
|
||||
int msdg = (DITH_N*((DITH_G)-1)+1) * (G); \
|
||||
int msdb = (DITH_N*((DITH_B)-1)+1) * (B); \
|
||||
int i; \
|
||||
for (i=0;i<16;i++) { \
|
||||
int k = xmesa_kernel8[i]; \
|
||||
int j = DITH_MIX( (msdr+k)>>12, (msdg+k)>>12, (msdb+k)>>12 );\
|
||||
ditherValues[i] = (GLushort) ctable[j]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FLAT_DITHER_ROW_SETUP(Y) \
|
||||
GLushort *ditherRow = ditherValues + ( ((Y)&3) << 2);
|
||||
|
||||
#define FLAT_DITHER(X) ditherRow[(X)&3]
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_LOOKUP:
|
||||
*/
|
||||
#define _dither_lookup(C, c) (((unsigned)((DITH_N * (C - 1) + 1) * c)) >> 12)
|
||||
|
||||
#define LOOKUP_SETUP \
|
||||
unsigned long *ctable = XMESA_BUFFER(ctx->DrawBuffer)->color_table
|
||||
|
||||
#define LOOKUP( R, G, B ) \
|
||||
ctable[DITH_MIX(_dither_lookup(DITH_R, (R)), \
|
||||
_dither_lookup(DITH_G, (G)), \
|
||||
_dither_lookup(DITH_B, (B)))]
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_1BIT:
|
||||
*/
|
||||
extern const int xmesa_kernel1[16];
|
||||
|
||||
#define SETUP_1BIT int bitFlip = xmesa->xm_visual->bitFlip
|
||||
#define DITHER_1BIT( X, Y, R, G, B ) \
|
||||
(( ((int)(R)+(int)(G)+(int)(B)) > xmesa_kernel1[(((Y)&3) << 2) | ((X)&3)] ) ^ bitFlip)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If pixelformat==PF_GRAYSCALE:
|
||||
*/
|
||||
#define GRAY_RGB( R, G, B ) XMESA_BUFFER(ctx->DrawBuffer)->color_table[((R) + (G) + (B))/3]
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts a GL window Y coord to an X window Y coord:
|
||||
*/
|
||||
#define YFLIP(XRB, Y) ((XRB)->bottom - (Y))
|
||||
|
||||
|
||||
/**
|
||||
* Return the address of a 1, 2 or 4-byte pixel in the buffer's XImage:
|
||||
* X==0 is left, Y==0 is bottom.
|
||||
*/
|
||||
#define PIXEL_ADDR1(XRB, X, Y) \
|
||||
( (XRB)->origin1 - (Y) * (XRB)->width1 + (X) )
|
||||
|
||||
#define PIXEL_ADDR2(XRB, X, Y) \
|
||||
( (XRB)->origin2 - (Y) * (XRB)->width2 + (X) )
|
||||
|
||||
#define PIXEL_ADDR3(XRB, X, Y) \
|
||||
( (bgr_t *) ( (XRB)->origin3 - (Y) * (XRB)->width3 + 3 * (X) ))
|
||||
|
||||
#define PIXEL_ADDR4(XRB, X, Y) \
|
||||
( (XRB)->origin4 - (Y) * (XRB)->width4 + (X) )
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* External functions:
|
||||
*/
|
||||
|
||||
extern struct xmesa_renderbuffer *
|
||||
xmesa_create_renderbuffer(struct pipe_winsys *winsys,
|
||||
GLuint name, XMesaVisual xmvis,
|
||||
GLboolean backBuffer);
|
||||
|
||||
extern void
|
||||
xmesa_delete_framebuffer(struct gl_framebuffer *fb);
|
||||
|
|
@ -461,115 +143,14 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb);
|
|||
extern XMesaBuffer
|
||||
xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis);
|
||||
|
||||
extern unsigned long
|
||||
xmesa_color_to_pixel( XMesaContext xmesa,
|
||||
GLubyte r, GLubyte g, GLubyte b, GLubyte a,
|
||||
GLuint pixelFormat );
|
||||
|
||||
extern void
|
||||
xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
|
||||
GLuint *width, GLuint *height);
|
||||
|
||||
extern void
|
||||
xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
|
||||
|
||||
|
||||
extern void
|
||||
xmesa_destroy_buffers_on_display(XMesaDisplay *dpy);
|
||||
|
||||
|
||||
/**
|
||||
* Using a function instead of an ordinary cast is safer.
|
||||
*/
|
||||
static INLINE struct xmesa_renderbuffer *
|
||||
xmesa_renderbuffer(struct gl_renderbuffer *rb)
|
||||
{
|
||||
return (struct xmesa_renderbuffer *) rb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to XMesaContext corresponding to a Mesa GLcontext.
|
||||
* Since we're using structure containment, it's just a cast!.
|
||||
* XXX should use inlined function for better type safety.
|
||||
*/
|
||||
static INLINE XMesaContext
|
||||
XMESA_CONTEXT(GLcontext *ctx)
|
||||
{
|
||||
return (XMesaContext) ctx->DriverCtx;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to XMesaBuffer corresponding to a Mesa GLframebuffer.
|
||||
* Since we're using structure containment, it's just a cast!.
|
||||
* XXX should use inlined function for better type safety.
|
||||
*/
|
||||
static INLINE XMesaBuffer
|
||||
XMESA_BUFFER(GLframebuffer *fb)
|
||||
{
|
||||
struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
|
||||
return (XMesaBuffer) st_framebuffer_private(stfb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct pipe_context;
|
||||
|
||||
struct xmesa_surface
|
||||
{
|
||||
struct pipe_surface surface;
|
||||
struct xmesa_renderbuffer *xrb;
|
||||
XMesaDisplay *display;
|
||||
BufferType type;
|
||||
XMesaDrawable drawable;
|
||||
XMesaImage *ximage;
|
||||
XMesaGC gc;
|
||||
};
|
||||
|
||||
|
||||
/** Cast wrapper */
|
||||
static INLINE struct xmesa_surface *
|
||||
xmesa_surface(struct pipe_surface *ps)
|
||||
{
|
||||
return (struct xmesa_surface *) ps;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, uint value);
|
||||
|
||||
extern struct pipe_context *
|
||||
xmesa_create_context(XMesaContext xm);
|
||||
|
||||
extern struct pipe_surface *
|
||||
xmesa_surface_alloc(struct pipe_context *pipe, GLuint format);
|
||||
|
||||
extern struct pipe_surface *
|
||||
xmesa_new_color_surface(struct pipe_winsys *winsys, GLuint format);
|
||||
|
||||
extern struct pipe_winsys *
|
||||
xmesa_get_pipe_winsys(void);
|
||||
|
||||
extern void
|
||||
xmesa_get_tile(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, void *p, int dst_stride);
|
||||
|
||||
extern void
|
||||
xmesa_put_tile(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, const void *p, int src_stride);
|
||||
|
||||
extern void
|
||||
xmesa_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, float *p);
|
||||
|
||||
extern void
|
||||
xmesa_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||
uint x, uint y, uint w, uint h, const float *p);
|
||||
|
||||
|
||||
extern struct pipe_surface *
|
||||
xmesa_create_front_surface(XMesaVisual vis, Window win);
|
||||
xmesa_create_pipe_context(XMesaContext xm, uint pixelformat);
|
||||
|
||||
static INLINE GLuint
|
||||
xmesa_buffer_width(XMesaBuffer b)
|
||||
|
|
@ -583,5 +164,7 @@ xmesa_buffer_height(XMesaBuffer b)
|
|||
return b->stfb->Base.Height;
|
||||
}
|
||||
|
||||
extern void
|
||||
xmesa_display_surface(XMesaBuffer b, const struct pipe_surface *surf);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -334,9 +334,7 @@ X11_DRIVER_SOURCES = \
|
|||
pipe/xlib/fakeglx.c \
|
||||
pipe/xlib/xfonts.c \
|
||||
pipe/xlib/xm_api.c \
|
||||
pipe/xlib/xm_buffer.c \
|
||||
pipe/xlib/xm_winsys.c \
|
||||
pipe/xlib/xm_surface.c
|
||||
pipe/xlib/xm_winsys.c
|
||||
|
||||
OSMESA_DRIVER_SOURCES = \
|
||||
drivers/osmesa/osmesa.c
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue