/** * Called via gl_framebuffer::Delete() method when this buffer * is _really_ being deleted. */ void xmesa_delete_framebuffer(struct gl_framebuffer *fb) { XMesaBuffer b = XMESA_BUFFER(fb); if (b->num_alloced > 0) { /* If no other buffer uses this X colormap then free the colors. */ if (!xmesa_find_buffer(b->display, b->cmap, b)) { XFreeColors(b->display, b->cmap, b->alloced_colors, b->num_alloced, 0); } } if (b->gc) XMesaFreeGC(b->display, b->gc); if (b->cleargc) XMesaFreeGC(b->display, b->cleargc); if (b->swapgc) XMesaFreeGC(b->display, b->swapgc); if (fb->Visual.doubleBufferMode) { /* free back ximage/pixmap/shmregion */ if (b->backxrb->ximage) { #if defined(USE_XSHM) 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->xm_visual->hpcr_clear_flag) { XMesaFreePixmap( b->display, b->xm_visual->hpcr_clear_pixmap ); XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); } } } if (b->rowimage) { free( b->rowimage->data ); b->rowimage->data = NULL; XMesaDestroyImage( b->rowimage ); } _mesa_free_framebuffer_data(fb); free(fb); }
/** * Called via ctx->Driver.UnmapRenderbuffer() */ void xmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) { XImage *ximage = xrb->ximage; if (!ximage) { /* this must be a pixmap/window renderbuffer */ assert(xrb->pixmap); assert(xrb->map_ximage); if (xrb->map_ximage) { if (xrb->map_mode & GL_MAP_WRITE_BIT) { /* put modified ximage data back into the pixmap/window */ int y2 = rb->Height - xrb->map_y - xrb->map_h; GC gc = XCreateGC(xrb->Parent->display, xrb->pixmap, 0, NULL); XPutImage(xrb->Parent->display, xrb->pixmap, /* dest */ gc, xrb->map_ximage, /* source */ 0, 0, /* src x, y */ xrb->map_x, y2, /* dest x, y */ xrb->map_w, xrb->map_h); /* size */ XFreeGC(xrb->Parent->display, gc); } XMesaDestroyImage(xrb->map_ximage); xrb->map_ximage = NULL; } } xrb->map_mode = 0x0; return; } /* otherwise, this is an ordinary malloc-based renderbuffer */ _swrast_unmap_soft_renderbuffer(ctx, rb); }
/** * Return the true number of bits per pixel for XImages. * For example, if we request a 24-bit deep visual we may actually need/get * 32bpp XImages. This function returns the appropriate bpp. * Input: dpy - the X display * visinfo - desribes the visual to be used for XImages * Return: true number of bits per pixel for XImages */ static int bits_per_pixel( XMesaVisual xmv ) { XMesaDisplay *dpy = xmv->display; XMesaVisualInfo visinfo = xmv->visinfo; XMesaImage *img; int bitsPerPixel; /* Create a temporary XImage */ img = XCreateImage( dpy, visinfo->visual, visinfo->depth, ZPixmap, 0, /*format, offset*/ malloc(8), /*data*/ 1, 1, /*width, height*/ 32, /*bitmap_pad*/ 0 /*bytes_per_line*/ ); assert(img); /* grab the bits/pixel value */ bitsPerPixel = img->bits_per_pixel; /* free the XImage */ free( img->data ); img->data = NULL; XMesaDestroyImage( img ); return bitsPerPixel; }
/** * Setup an off-screen pixmap or Ximage to use as the back buffer. * Input: b - the X/Mesa buffer */ static void alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) { if (b->db_mode == BACK_XIMAGE) { /* Deallocate the old backxrb->ximage, if any */ if (b->backxrb->ximage) { #if defined(USE_XSHM) 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; } if (width == 0 || height == 0) return; /* Allocate new back buffer */ if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) { /* Allocate a regular XImage for the back buffer. */ b->backxrb->ximage = XCreateImage(b->xm_visual->display, b->xm_visual->visinfo->visual, GET_VISUAL_DEPTH(b->xm_visual), ZPixmap, 0, /* format, offset */ NULL, width, height, 8, 0); /* pad, bytes_per_line */ 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) { /* Free the old back pixmap */ if (b->backxrb->pixmap) { XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap); b->backxrb->pixmap = 0; } if (width > 0 && height > 0) { /* Allocate new back pixmap */ b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display, b->frontxrb->drawable, width, height, GET_VISUAL_DEPTH(b->xm_visual)); } b->backxrb->ximage = NULL; b->backxrb->drawable = b->backxrb->pixmap; } }
PUBLIC void XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer, const int *attrib_list) { #if 0 GET_CURRENT_CONTEXT(ctx); const GLuint unit = ctx->Texture.CurrentUnit; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj; #endif struct gl_renderbuffer *rb; struct xmesa_renderbuffer *xrb; GLint b; XMesaImage *img = NULL; GLboolean freeImg = GL_FALSE; b = xbuffer_to_renderbuffer(buffer); if (b < 0) return; if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) return; /* BadMatch error */ rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; if (!rb) { /* invalid buffer */ return; } xrb = xmesa_renderbuffer(rb); #if 0 switch (drawable->TextureTarget) { case GLX_TEXTURE_1D_EXT: texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX]; break; case GLX_TEXTURE_2D_EXT: texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX]; break; case GLX_TEXTURE_RECTANGLE_EXT: texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX]; break; default: return; /* BadMatch error */ } #endif /* * The following is a quick and simple way to implement * BindTexImage. The better way is to write some new FetchTexel() * functions which would extract texels from XImages. We'd still * need to use GetImage when texturing from a Pixmap (front buffer) * but texturing from a back buffer (XImage) would avoid an image * copy. */ /* get XImage */ if (xrb->pixmap) { img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L, ZPixmap); freeImg = GL_TRUE; } else if (xrb->ximage) { img = xrb->ximage; } /* store the XImage as a new texture image */ if (img) { GLenum format, type, intFormat; if (img->bits_per_pixel == 32) { format = GL_BGRA; type = GL_UNSIGNED_BYTE; intFormat = GL_RGBA; } else if (img->bits_per_pixel == 24) { format = GL_BGR; type = GL_UNSIGNED_BYTE; intFormat = GL_RGB; } else if (img->bits_per_pixel == 16) { format = GL_BGR; type = GL_UNSIGNED_SHORT_5_6_5; intFormat = GL_RGB; } else { _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); return; } if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { intFormat = GL_RGBA; } else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { intFormat = GL_RGB; } _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, format, type, img->data); if (freeImg) { XMesaDestroyImage(img); } } }