1e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/*
2e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Mesa 3-D graphics library
3d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Version:  6.5.2
4e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul *
5d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul *
7e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
8e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * copy of this software and associated documentation files (the "Software"),
9e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * to deal in the Software without restriction, including without limitation
10e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and/or sell copies of the Software, and to permit persons to whom the
12e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Software is furnished to do so, subject to the following conditions:
13e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul *
14e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The above copyright notice and this permission notice shall be included
15e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * in all copies or substantial portions of the Software.
16e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul *
17e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */
24e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
25e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
26d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/**
27d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * \file xm_buffer.h
28d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Framebuffer and renderbuffer-related functions.
29d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */
30d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
31d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
32e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul#include "glxheader.h"
33e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul#include "xmesaP.h"
34374e7fd6cc95d3d91629a6e1c951d77e8a29c31cBrian Paul#include "main/imports.h"
3545e76d2665b38ba3787548310efc59e969124c01Brian Paul#include "main/formats.h"
36374e7fd6cc95d3d91629a6e1c951d77e8a29c31cBrian Paul#include "main/framebuffer.h"
37374e7fd6cc95d3d91629a6e1c951d77e8a29c31cBrian Paul#include "main/renderbuffer.h"
38d0dc75c000d5af92648c7de901756400672b8447Brian Paul#include "swrast/s_renderbuffer.h"
39e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
40e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
4132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul#define XMESA_RENDERBUFFER 0x1234
4232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
4332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
441ccef926be46dce3b6b5c76e812e2fae4e205ce7Adam Jackson#if defined(USE_XSHM)
45d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic volatile int mesaXErrorFlag = 0;
46d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
47d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/**
48d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Catches potential Xlib errors.
49d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */
50d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic int
51d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian PaulmesaHandleXError(XMesaDisplay *dpy, XErrorEvent *event)
52d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul{
53d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   (void) dpy;
54d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   (void) event;
55d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   mesaXErrorFlag = 1;
56d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   return 0;
57d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul}
58d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
59d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/**
60d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
61d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Return:  GL_TRUE if success, GL_FALSE if error
62d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */
63d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic GLboolean
64d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulalloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height)
65d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul{
66d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   /*
67d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul    * We have to do a _lot_ of error checking here to be sure we can
68d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul    * really use the XSHM extension.  It seems different servers trigger
69d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul    * errors at different points if the extension won't work.  Therefore
70d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul    * we have to be very careful...
71d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul    */
72d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   GC gc;
73d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   int (*old_handler)(XMesaDisplay *, XErrorEvent *);
74d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
75d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (width == 0 || height == 0) {
76d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      /* this will be true the first time we're called on 'b' */
77d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      return GL_FALSE;
78d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
79d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
80d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   b->backxrb->ximage = XShmCreateImage(b->xm_visual->display,
81d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                        b->xm_visual->visinfo->visual,
82d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                        b->xm_visual->visinfo->depth,
83d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                        ZPixmap, NULL, &b->shminfo,
84d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                        width, height);
85d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (b->backxrb->ximage == NULL) {
86d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n");
87d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->shm = 0;
88d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      return GL_FALSE;
89d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
90d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
91d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line
92d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul			     * b->backxrb->ximage->height, IPC_CREAT|0777);
93d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (b->shminfo.shmid < 0) {
94d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      _mesa_warning(NULL, "shmget failed while allocating back buffer.\n");
95d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      XDestroyImage(b->backxrb->ximage);
96d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->backxrb->ximage = NULL;
97d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n");
98d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->shm = 0;
99d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      return GL_FALSE;
100d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
101d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
102d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   b->shminfo.shmaddr = b->backxrb->ximage->data
103d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                      = (char*)shmat(b->shminfo.shmid, 0, 0);
104d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (b->shminfo.shmaddr == (char *) -1) {
105d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      _mesa_warning(NULL, "shmat() failed while allocating back buffer.\n");
106d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      XDestroyImage(b->backxrb->ximage);
107d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      shmctl(b->shminfo.shmid, IPC_RMID, 0);
108d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->backxrb->ximage = NULL;
109d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n");
110d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->shm = 0;
111d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      return GL_FALSE;
112d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
113d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
114d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   b->shminfo.readOnly = False;
115d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   mesaXErrorFlag = 0;
116d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   old_handler = XSetErrorHandler(mesaHandleXError);
117d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   /* This may trigger the X protocol error we're ready to catch: */
118d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   XShmAttach(b->xm_visual->display, &b->shminfo);
119d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   XSync(b->xm_visual->display, False);
120d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
121d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (mesaXErrorFlag) {
122d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      /* we are on a remote display, this error is normal, don't print it */
123d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      XFlush(b->xm_visual->display);
124d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      mesaXErrorFlag = 0;
125d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      XDestroyImage(b->backxrb->ximage);
126d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      shmdt(b->shminfo.shmaddr);
127d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      shmctl(b->shminfo.shmid, IPC_RMID, 0);
128d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->backxrb->ximage = NULL;
129d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->shm = 0;
130d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      (void) XSetErrorHandler(old_handler);
131d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      return GL_FALSE;
132d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
133d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
134d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   shmctl(b->shminfo.shmid, IPC_RMID, 0); /* nobody else needs it */
135d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
136d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   /* Finally, try an XShmPutImage to be really sure the extension works */
137d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   gc = XCreateGC(b->xm_visual->display, b->frontxrb->drawable, 0, NULL);
138d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   XShmPutImage(b->xm_visual->display, b->frontxrb->drawable, gc,
139d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul		 b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False);
140d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   XSync(b->xm_visual->display, False);
141d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   XFreeGC(b->xm_visual->display, gc);
142d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   (void) XSetErrorHandler(old_handler);
143d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (mesaXErrorFlag) {
144d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      XFlush(b->xm_visual->display);
145d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      mesaXErrorFlag = 0;
146d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      XDestroyImage(b->backxrb->ximage);
147d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      shmdt(b->shminfo.shmaddr);
148d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      shmctl(b->shminfo.shmid, IPC_RMID, 0);
149d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->backxrb->ximage = NULL;
150d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->shm = 0;
151d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      return GL_FALSE;
152d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
153d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
154d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   return GL_TRUE;
1557439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis}
156d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#else
1577439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzisstatic GLboolean
1587439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzisalloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height)
1597439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis{
160d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   /* Can't compile XSHM support */
161d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   return GL_FALSE;
162d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul}
163d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#endif
164d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
165d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
166d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
167d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/**
168d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Setup an off-screen pixmap or Ximage to use as the back buffer.
169d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Input:  b - the X/Mesa buffer
170d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */
171d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic void
172d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulalloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
173d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul{
174d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   if (b->db_mode == BACK_XIMAGE) {
175d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      /* Deallocate the old backxrb->ximage, if any */
176d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      if (b->backxrb->ximage) {
1771ccef926be46dce3b6b5c76e812e2fae4e205ce7Adam Jackson#if defined(USE_XSHM)
178d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 if (b->shm) {
179d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	    XShmDetach(b->xm_visual->display, &b->shminfo);
180d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	    XDestroyImage(b->backxrb->ximage);
181d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	    shmdt(b->shminfo.shmaddr);
182d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 }
183d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 else
184d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#endif
185d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	   XMesaDestroyImage(b->backxrb->ximage);
186d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 b->backxrb->ximage = NULL;
187d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      }
188d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
189e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      if (width == 0 || height == 0)
190e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian         return;
191e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian
192d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      /* Allocate new back buffer */
193d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) {
194d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 /* Allocate a regular XImage for the back buffer. */
195d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 b->backxrb->ximage = XCreateImage(b->xm_visual->display,
196d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                      b->xm_visual->visinfo->visual,
197d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                      GET_VISUAL_DEPTH(b->xm_visual),
198d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul				      ZPixmap, 0,   /* format, offset */
199d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul				      NULL,
200d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                      width, height,
201d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul				      8, 0);  /* pad, bytes_per_line */
202d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 if (!b->backxrb->ximage) {
203d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	    _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n");
204d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul            return;
205d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul	 }
206d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul         b->backxrb->ximage->data = (char *) MALLOC(b->backxrb->ximage->height
207d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul                                        * b->backxrb->ximage->bytes_per_line);
208d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul         if (!b->backxrb->ximage->data) {
209d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul            _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n");
210d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul            XMesaDestroyImage(b->backxrb->ximage);
211d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul            b->backxrb->ximage = NULL;
212d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul         }
213d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      }
214d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->backxrb->pixmap = None;
215d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
216d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   else if (b->db_mode == BACK_PIXMAP) {
217d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      /* Free the old back pixmap */
218d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      if (b->backxrb->pixmap) {
219e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian         XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap);
220e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian         b->backxrb->pixmap = 0;
221d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      }
222e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian
223e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      if (width > 0 && height > 0) {
224e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian         /* Allocate new back pixmap */
225e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian         b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display,
226e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian                                                b->frontxrb->drawable,
227e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian                                                width, height,
228e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian                                                GET_VISUAL_DEPTH(b->xm_visual));
229e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      }
230e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian
231d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul      b->backxrb->ximage = NULL;
23222bac2a1a0d315172f815cb8a516bfe198b0a6f3Brian Paul      b->backxrb->drawable = b->backxrb->pixmap;
233d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   }
234d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul}
235d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
236d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
237e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstatic void
2389d4ab9a663d4088ec553edaae0eeafb746d2490dBrian Paulxmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
239e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{
240d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul   /* XXX Note: the ximage or Pixmap attached to this renderbuffer
241d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul    * should probably get freed here, but that's currently done in
242d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul    * XMesaDestroyBuffer().
243d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul    */
24432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(rb);
245e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul}
246e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
247e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
248e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/**
249692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul * Reallocate renderbuffer storage for front color buffer.
250e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian * Called via gl_renderbuffer::AllocStorage()
251e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */
252e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstatic GLboolean
253f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergxmesa_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
254692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul                          GLenum internalFormat, GLuint width, GLuint height)
255e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{
256444cd293fd69d1848b2c55f75674d563e0582fbaBrian Paul   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
257e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
258692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   /* just clear these to be sure we don't accidentally use them */
259692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   xrb->origin2 = NULL;
260e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian   xrb->origin3 = NULL;
261692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   xrb->origin4 = NULL;
262692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
263692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   /* for the FLIP macro: */
264692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   xrb->bottom = height - 1;
265692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
266692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   rb->Width = width;
267692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   rb->Height = height;
268692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   rb->InternalFormat = internalFormat;
269692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
270692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   return GL_TRUE;
271692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul}
272692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
273692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
274692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul/**
275692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul * Reallocate renderbuffer storage for back color buffer.
276e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian * Called via gl_renderbuffer::AllocStorage()
277692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul */
278692147ebf7f09d56a7de1659de2449478da4d1baBrian Paulstatic GLboolean
279f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergxmesa_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
280692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul                         GLenum internalFormat, GLuint width, GLuint height)
281692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul{
282444cd293fd69d1848b2c55f75674d563e0582fbaBrian Paul   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
283692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
284d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   /* reallocate the back buffer XImage or Pixmap */
285d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   assert(xrb->Parent);
286d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   alloc_back_buffer(xrb->Parent, width, height);
287d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul
288692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   /* same as front buffer */
289d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul   /* XXX why is this here? */
290692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   (void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height);
291692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul
292692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul   /* plus... */
293e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   if (xrb->ximage) {
294e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* Needed by PIXELADDR2 macro */
295e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      xrb->width2 = xrb->ximage->bytes_per_line / 2;
296e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1);
297e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
298e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* Needed by PIXELADDR3 macro */
299e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      xrb->width3 = xrb->ximage->bytes_per_line;
300e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      xrb->origin3 = (GLubyte *) xrb->ximage->data + xrb->width3 * (height - 1);
301e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
302e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* Needed by PIXELADDR4 macro */
303e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      xrb->width4 = xrb->ximage->width;
304e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      xrb->origin4 = (GLuint *) xrb->ximage->data + xrb->width4 * (height - 1);
305e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   }
306e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   else {
307e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      /* out of memory or buffer size is 0 x 0 */
308bc63b226bcc94f109906bccce26d47509f28d177Brian Paul      xrb->width2 = xrb->width3 = xrb->width4 = 0;
309e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      xrb->origin2 = NULL;
310e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      xrb->origin3 = NULL;
311e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian      xrb->origin4 = NULL;
312e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   }
313e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
314e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   return GL_TRUE;
315e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul}
316e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
317e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
31832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul/**
31932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul * Used for allocating front/back renderbuffers for an X window.
32032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul */
321e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstruct xmesa_renderbuffer *
32232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paulxmesa_new_renderbuffer(struct gl_context *ctx, GLuint name,
32332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                       const struct xmesa_visual *xmvis,
324692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul                       GLboolean backBuffer)
325e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{
326e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer);
327e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   if (xrb) {
328e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint name = 0;
329d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul      _mesa_init_renderbuffer(&xrb->Base.Base, name);
330e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
331d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul      xrb->Base.Base.Delete = xmesa_delete_renderbuffer;
332692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul      if (backBuffer)
333d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.AllocStorage = xmesa_alloc_back_storage;
334692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul      else
335d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.AllocStorage = xmesa_alloc_front_storage;
336e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
337d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul      xrb->Base.Base.InternalFormat = GL_RGBA;
338d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul      xrb->Base.Base._BaseFormat = GL_RGBA;
339d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul      xrb->Base.Base.ClassID = XMESA_RENDERBUFFER;
34032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
34132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      switch (xmvis->undithered_pf) {
34232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      case PF_8R8G8B:
34332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         /* This will really only happen for pixmaps.  We'll access the
34432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul          * pixmap via a temporary XImage which will be 32bpp.
34532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul          */
346d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.Format = MESA_FORMAT_XRGB8888;
34732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         break;
34832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      case PF_8A8R8G8B:
349d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.Format = MESA_FORMAT_ARGB8888;
35032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         break;
35132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      case PF_8A8B8G8R:
352d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.Format = MESA_FORMAT_RGBA8888_REV;
35332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         break;
35432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      case PF_5R6G5B:
355d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.Format = MESA_FORMAT_RGB565;
35632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         break;
35732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      default:
35832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         _mesa_warning(ctx, "Bad pixel format in xmesa_new_renderbuffer");
359d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul         xrb->Base.Base.Format = MESA_FORMAT_ARGB8888;
36032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         break;
36132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      }
36232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
363676d0accf5cc43e86057b14cfb8bba9316932582Brian Paul      /* only need to set Red/Green/EtcBits fields for user-created RBs */
364e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   }
365e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   return xrb;
366e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul}
367e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
368e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
369928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian/**
370928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian * Called via gl_framebuffer::Delete() method when this buffer
37159e56ee3e5c8f9aa9ec74e1817065a7ae14012eaBrian * is _really_ being deleted.
372928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian */
373928a70e4354d4884e2918ec67ddc6d8baf942c8aBrianvoid
374928a70e4354d4884e2918ec67ddc6d8baf942c8aBrianxmesa_delete_framebuffer(struct gl_framebuffer *fb)
375928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian{
376928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   XMesaBuffer b = XMESA_BUFFER(fb);
377e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
378928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   if (b->num_alloced > 0) {
379928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      /* If no other buffer uses this X colormap then free the colors. */
380928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      if (!xmesa_find_buffer(b->display, b->cmap, b)) {
381928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian         XFreeColors(b->display, b->cmap,
382928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian                     b->alloced_colors, b->num_alloced, 0);
383928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      }
384928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   }
385928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian
386928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   if (b->gc)
387e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian      XMesaFreeGC(b->display, b->gc);
388928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   if (b->cleargc)
389e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian      XMesaFreeGC(b->display, b->cleargc);
390928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   if (b->swapgc)
391e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian      XMesaFreeGC(b->display, b->swapgc);
392928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian
393e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian   if (fb->Visual.doubleBufferMode) {
394928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      /* free back ximage/pixmap/shmregion */
395928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      if (b->backxrb->ximage) {
3961ccef926be46dce3b6b5c76e812e2fae4e205ce7Adam Jackson#if defined(USE_XSHM)
397928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian         if (b->shm) {
398e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian            XShmDetach( b->display, &b->shminfo );
399928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian            XDestroyImage( b->backxrb->ximage );
400928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian            shmdt( b->shminfo.shmaddr );
401928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian         }
402928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian         else
403928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian#endif
404928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian            XMesaDestroyImage( b->backxrb->ximage );
405928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian         b->backxrb->ximage = NULL;
406928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      }
407928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      if (b->backxrb->pixmap) {
408e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian         XMesaFreePixmap( b->display, b->backxrb->pixmap );
409928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian      }
410928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   }
411928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian
412928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian   _mesa_free_framebuffer_data(fb);
41332f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(fb);
414928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian}
41532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
41632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
41732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul/**
41832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul * Called via ctx->Driver.MapRenderbuffer()
41932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul */
42032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paulvoid
42132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paulxmesa_MapRenderbuffer(struct gl_context *ctx,
42232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                      struct gl_renderbuffer *rb,
42332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                      GLuint x, GLuint y, GLuint w, GLuint h,
42432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                      GLbitfield mode,
42532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                      GLubyte **mapOut, GLint *rowStrideOut)
42632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul{
42732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
42832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
429d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul   if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) {
43032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      XImage *ximage = xrb->ximage;
43132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
43232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      assert(!xrb->map_mode); /* only a single mapping allowed */
43332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
43432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      xrb->map_mode = mode;
43532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      xrb->map_x = x;
43632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      xrb->map_y = y;
43732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      xrb->map_w = w;
43832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      xrb->map_h = h;
43932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
44032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      if (ximage) {
44132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         int y2 = rb->Height - y - 1;
44232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
44332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         *mapOut = (GLubyte *) ximage->data
44432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            + y2 * ximage->bytes_per_line
44532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            + x * ximage->bits_per_pixel / 8;
44632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      }
44732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      else {
44832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         /* this must be a pixmap/window renderbuffer */
449a73e9207da188a65af50da279f1436566c4a8418Brian Paul         int (*old_handler)(XMesaDisplay *, XErrorEvent *);
45032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         int y2 = rb->Height - y - h;
45132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
45232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         assert(xrb->pixmap);
45332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
454a73e9207da188a65af50da279f1436566c4a8418Brian Paul         /* Install error handler for XGetImage() in case the the window
455a73e9207da188a65af50da279f1436566c4a8418Brian Paul          * isn't mapped.  If we fail we'll create a temporary XImage.
456a73e9207da188a65af50da279f1436566c4a8418Brian Paul          */
457a73e9207da188a65af50da279f1436566c4a8418Brian Paul         mesaXErrorFlag = 0;
458a73e9207da188a65af50da279f1436566c4a8418Brian Paul         old_handler = XSetErrorHandler(mesaHandleXError);
459a73e9207da188a65af50da279f1436566c4a8418Brian Paul
46032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         /* read pixel data out of the pixmap/window into an XImage */
46132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         ximage = XGetImage(xrb->Parent->display,
46232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                            xrb->pixmap, x, y2, w, h,
46332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                            AllPlanes, ZPixmap);
464a73e9207da188a65af50da279f1436566c4a8418Brian Paul
465a73e9207da188a65af50da279f1436566c4a8418Brian Paul         XSetErrorHandler(old_handler);
466a73e9207da188a65af50da279f1436566c4a8418Brian Paul
467a73e9207da188a65af50da279f1436566c4a8418Brian Paul         if (mesaXErrorFlag) {
468a73e9207da188a65af50da279f1436566c4a8418Brian Paul            /* create new, temporary XImage */
469a73e9207da188a65af50da279f1436566c4a8418Brian Paul            int bytes_per_line =
470a73e9207da188a65af50da279f1436566c4a8418Brian Paul               _mesa_format_row_stride(xrb->Base.Base.Format,
471a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                       xrb->Base.Base.Width);
472a73e9207da188a65af50da279f1436566c4a8418Brian Paul            char *image = (char *) malloc(bytes_per_line *
473a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                          xrb->Base.Base.Height);
474a73e9207da188a65af50da279f1436566c4a8418Brian Paul            ximage = XCreateImage(xrb->Parent->display,
475a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  xrb->Parent->xm_visual->visinfo->visual,
476a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  xrb->Parent->xm_visual->visinfo->depth,
477a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  ZPixmap, /* format */
478a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  0, /* offset */
479a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  image, /* data */
480a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  xrb->Base.Base.Width,
481a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  xrb->Base.Base.Height,
482a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  8, /* pad */
483a73e9207da188a65af50da279f1436566c4a8418Brian Paul                                  bytes_per_line);
484a73e9207da188a65af50da279f1436566c4a8418Brian Paul         }
485a73e9207da188a65af50da279f1436566c4a8418Brian Paul
48632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         if (!ximage) {
48732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            *mapOut = NULL;
48832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            *rowStrideOut = 0;
48932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            return;
49032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         }
49132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
49232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         xrb->map_ximage = ximage;
49332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
49432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         /* the first row of the OpenGL image is last row of the XImage */
49532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         *mapOut = (GLubyte *) ximage->data
49632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            + (h - 1) * ximage->bytes_per_line;
49732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      }
49832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
49932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      /* We return a negative stride here since XImage data is upside down
50032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul       * with respect to OpenGL images.
50132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul       */
50232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      *rowStrideOut = -ximage->bytes_per_line;
50332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      return;
50432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul   }
50532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
50632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul   /* otherwise, this is an ordinary malloc-based renderbuffer */
507d0dc75c000d5af92648c7de901756400672b8447Brian Paul   _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
508d0dc75c000d5af92648c7de901756400672b8447Brian Paul                                 mapOut, rowStrideOut);
50932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul}
51032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
51132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
51232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul/**
51332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul * Called via ctx->Driver.UnmapRenderbuffer()
51432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul */
51532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paulvoid
51632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paulxmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
51732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul{
51832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
51932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
520d16e71eeb47d1e67930f6e86a80dc926468224d9Brian Paul   if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) {
52132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      XImage *ximage = xrb->ximage;
52232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
52332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      if (!ximage) {
52432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         /* this must be a pixmap/window renderbuffer */
52532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         assert(xrb->pixmap);
52632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         assert(xrb->map_ximage);
52732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         if (xrb->map_ximage) {
52832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            if (xrb->map_mode & GL_MAP_WRITE_BIT) {
52932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul               /* put modified ximage data back into the pixmap/window */
53032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul               int y2 = rb->Height - xrb->map_y - xrb->map_h;
53132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul               GC gc = XCreateGC(xrb->Parent->display, xrb->pixmap, 0, NULL);
53232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
53332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul               XPutImage(xrb->Parent->display,
53432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                         xrb->pixmap,              /* dest */
53532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                         gc,
53632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                         xrb->map_ximage,          /* source */
53732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                         0, 0,                     /* src x, y */
53832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                         xrb->map_x, y2,           /* dest x, y */
53932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul                         xrb->map_w, xrb->map_h);  /* size */
54032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
54132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul               XFreeGC(xrb->Parent->display, gc);
54232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            }
54332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            XMesaDestroyImage(xrb->map_ximage);
54432c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul            xrb->map_ximage = NULL;
54532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul         }
54632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      }
54732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
54832c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      xrb->map_mode = 0x0;
54932c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
55032c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul      return;
55132c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul   }
55232c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
55332c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul   /* otherwise, this is an ordinary malloc-based renderbuffer */
554d0dc75c000d5af92648c7de901756400672b8447Brian Paul   _swrast_unmap_soft_renderbuffer(ctx, rb);
55532c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul}
55632c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
55732c3957991bd0e1df744d866943a8c47b2757c9eBrian Paul
558