#include "glxheader.h"
#include "GL/xmesa.h"
#include "xmesaP.h"
#include "imports.h"
#include "renderbuffer.h"
#ifndef XFree86Server
static volatile int mesaXErrorFlag = 0;
static int
mesaHandleXError(XMesaDisplay *dpy, XErrorEvent *event)
{
(void) dpy;
(void) event;
mesaXErrorFlag = 1;
return 0;
}
#endif
#ifndef XFree86Server
static GLboolean
alloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height)
{
#ifdef USE_XSHM
GC gc;
int (*old_handler)(XMesaDisplay *, XErrorEvent *);
if (width == 0 || height == 0) {
return GL_FALSE;
}
b->backxrb->ximage = XShmCreateImage(b->xm_visual->display,
b->xm_visual->visinfo->visual,
b->xm_visual->visinfo->depth,
ZPixmap, NULL, &b->shminfo,
width, height);
if (b->backxrb->ximage == NULL) {
_mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n");
b->shm = 0;
return GL_FALSE;
}
b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line
* b->backxrb->ximage->height, IPC_CREAT|0777);
if (b->shminfo.shmid < 0) {
_mesa_warning(NULL, "shmget failed while allocating back buffer.\n");
XDestroyImage(b->backxrb->ximage);
b->backxrb->ximage = NULL;
_mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n");
b->shm = 0;
return GL_FALSE;
}
b->shminfo.shmaddr = b->backxrb->ximage->data
= (char*)shmat(b->shminfo.shmid, 0, 0);
if (b->shminfo.shmaddr == (char *) -1) {
_mesa_warning(NULL, "shmat() failed while allocating back buffer.\n");
XDestroyImage(b->backxrb->ximage);
shmctl(b->shminfo.shmid, IPC_RMID, 0);
b->backxrb->ximage = NULL;
_mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n");
b->shm = 0;
return GL_FALSE;
}
b->shminfo.readOnly = False;
mesaXErrorFlag = 0;
old_handler = XSetErrorHandler(mesaHandleXError);
XShmAttach(b->xm_visual->display, &b->shminfo);
XSync(b->xm_visual->display, False);
if (mesaXErrorFlag) {
XFlush(b->xm_visual->display);
mesaXErrorFlag = 0;
XDestroyImage(b->backxrb->ximage);
shmdt(b->shminfo.shmaddr);
shmctl(b->shminfo.shmid, IPC_RMID, 0);
b->backxrb->ximage = NULL;
b->shm = 0;
(void) XSetErrorHandler(old_handler);
return GL_FALSE;
}
shmctl(b->shminfo.shmid, IPC_RMID, 0);
gc = XCreateGC(b->xm_visual->display, b->frontxrb->drawable, 0, NULL);
XShmPutImage(b->xm_visual->display, b->frontxrb->drawable, gc,
b->backxrb->ximage, 0, 0, 0, 0, 1, 1 , False);
XSync(b->xm_visual->display, False);
XFreeGC(b->xm_visual->display, gc);
(void) XSetErrorHandler(old_handler);
if (mesaXErrorFlag) {
XFlush(b->xm_visual->display);
mesaXErrorFlag = 0;
XDestroyImage(b->backxrb->ximage);
shmdt(b->shminfo.shmaddr);
shmctl(b->shminfo.shmid, IPC_RMID, 0);
b->backxrb->ximage = NULL;
b->shm = 0;
return GL_FALSE;
}
return GL_TRUE;
#else
return GL_FALSE;
#endif
}
#endif
static void
alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
{
if (width == 0 || height == 0)
return;
if (b->db_mode == BACK_XIMAGE) {
if (b->backxrb->ximage) {
#if defined(USE_XSHM) && !defined(XFree86Server)
if (b->shm) {
XShmDetach(b->xm_visual->display, &b->shminfo);
XDestroyImage(b->backxrb->ximage);
shmdt(b->shminfo.shmaddr);
}
else
#endif
XMesaDestroyImage(b->backxrb->ximage);
b->backxrb->ximage = NULL;
}
#ifdef XFree86Server
b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
width, height, NULL);
{
#else
if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) {
b->backxrb->ximage = XCreateImage(b->xm_visual->display,
b->xm_visual->visinfo->visual,
GET_VISUAL_DEPTH(b->xm_visual),
ZPixmap, 0,
NULL,
width, height,
8, 0);
#endif
if (!b->backxrb->ximage) {
_mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n");
return;
}
b->backxrb->ximage->data = (char *) MALLOC(b->backxrb->ximage->height
* b->backxrb->ximage->bytes_per_line);
if (!b->backxrb->ximage->data) {
_mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n");
XMesaDestroyImage(b->backxrb->ximage);
b->backxrb->ximage = NULL;
}
}
b->backxrb->pixmap = None;
}
else if (b->db_mode == BACK_PIXMAP) {
if (!width)
width = 1;
if (!height)
height = 1;
if (b->backxrb->pixmap) {
XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap);
}
b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display,
b->frontxrb->drawable,
width, height,
GET_VISUAL_DEPTH(b->xm_visual));
b->backxrb->ximage = NULL;
}
}
static void
xmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
{
_mesa_free(rb);
}
static GLboolean
xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
xrb->origin1 = NULL;
xrb->origin2 = NULL;
xrb->origin4 = NULL;
xrb->bottom = height - 1;
rb->Width = width;
rb->Height = height;
rb->InternalFormat = internalFormat;
return GL_TRUE;
}
static GLboolean
xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
assert(xrb->Parent);
alloc_back_buffer(xrb->Parent, width, height);
(void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height);
if (xrb->ximage) {
xrb->width1 = xrb->ximage->bytes_per_line;
xrb->origin1 = (GLubyte *) xrb->ximage->data + xrb->width1 * (height - 1);
xrb->width2 = xrb->ximage->bytes_per_line / 2;
xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1);
xrb->width3 = xrb->ximage->bytes_per_line;
xrb->origin3 = (GLubyte *) xrb->ximage->data + xrb->width3 * (height - 1);
xrb->width4 = xrb->ximage->width;
xrb->origin4 = (GLuint *) xrb->ximage->data + xrb->width4 * (height - 1);
}
else {
}
return GL_TRUE;
}
struct xmesa_renderbuffer *
xmesa_new_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual,
GLboolean backBuffer)
{
struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer);
if (xrb) {
GLuint name = 0;
_mesa_init_renderbuffer(&xrb->Base, name);
xrb->Base.Delete = xmesa_delete_renderbuffer;
if (backBuffer)
xrb->Base.AllocStorage = xmesa_alloc_back_storage;
else
xrb->Base.AllocStorage = xmesa_alloc_front_storage;
if (visual->rgbMode) {
xrb->Base.InternalFormat = GL_RGBA;
xrb->Base._BaseFormat = GL_RGBA;
xrb->Base.DataType = GL_UNSIGNED_BYTE;
xrb->Base.RedBits = visual->redBits;
xrb->Base.GreenBits = visual->greenBits;
xrb->Base.BlueBits = visual->blueBits;
xrb->Base.AlphaBits = visual->alphaBits;
}
else {
xrb->Base.InternalFormat = GL_COLOR_INDEX;
xrb->Base._BaseFormat = GL_COLOR_INDEX;
xrb->Base.DataType = GL_UNSIGNED_INT;
xrb->Base.IndexBits = visual->indexBits;
}
}
return xrb;
}