+ }
+ }
+
+ _mesa_free_framebuffer_data(fb);
+ free(fb);
+}
+
+
+/**
+ * Called via ctx->Driver.MapRenderbuffer()
+ */
+void
+xmesa_MapRenderbuffer(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint x, GLuint y, GLuint w, GLuint h,
+ GLbitfield mode,
+ GLubyte **mapOut, GLint *rowStrideOut,
+ bool flip_y)
+{
+ struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+
+ if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) {
+ XImage *ximage = xrb->ximage;
+
+ assert(!xrb->map_mode); /* only a single mapping allowed */
+
+ xrb->map_mode = mode;
+ xrb->map_x = x;
+ xrb->map_y = y;
+ xrb->map_w = w;
+ xrb->map_h = h;
+
+ if (ximage) {
+ int y2 = rb->Height - y - 1;
+
+ *mapOut = (GLubyte *) ximage->data
+ + y2 * ximage->bytes_per_line
+ + x * ximage->bits_per_pixel / 8;
+ }
+ else {
+ /* this must be a pixmap/window renderbuffer */
+ int (*old_handler)(XMesaDisplay *, XErrorEvent *);
+ int y2 = rb->Height - y - h;
+
+ assert(xrb->pixmap);
+
+ /* Install error handler for XGetImage() in case the window
+ * isn't mapped. If we fail we'll create a temporary XImage.
+ */
+ mesaXErrorFlag = 0;
+ old_handler = XSetErrorHandler(mesaHandleXError);
+
+ /* read pixel data out of the pixmap/window into an XImage */
+ ximage = XGetImage(xrb->Parent->display,
+ xrb->pixmap, x, y2, w, h,
+ AllPlanes, ZPixmap);
+
+ XSetErrorHandler(old_handler);
+
+ if (mesaXErrorFlag) {
+ /* create new, temporary XImage */
+ int bytes_per_line =
+ _mesa_format_row_stride(xrb->Base.Base.Format,
+ xrb->Base.Base.Width);
+ char *image = malloc(bytes_per_line *
+ xrb->Base.Base.Height);
+ ximage = XCreateImage(xrb->Parent->display,
+ xrb->Parent->xm_visual->visinfo->visual,
+ xrb->Parent->xm_visual->visinfo->depth,
+ ZPixmap, /* format */
+ 0, /* offset */
+ image, /* data */
+ xrb->Base.Base.Width,
+ xrb->Base.Base.Height,
+ 8, /* pad */
+ bytes_per_line);
+ }
+
+ if (!ximage) {
+ *mapOut = NULL;
+ *rowStrideOut = 0;
+ return;