X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fx11%2Fxm_buffer.c;h=9e16726535c130991b4389e706cbf969fbab72a5;hp=bf386292895ceb09a6e6beeab2eea4b9f96d3310;hb=e5339fe4a47c242693962c9f90bbab8b74935cba;hpb=48302e9b309c7ce218de2e522c91bdc87e61cdbc diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c index bf386292895..9e16726535c 100644 --- a/src/mesa/drivers/x11/xm_buffer.c +++ b/src/mesa/drivers/x11/xm_buffer.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 6.5.2 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * @@ -17,9 +16,10 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ @@ -31,13 +31,18 @@ #include "glxheader.h" #include "xmesaP.h" -#include "main/imports.h" +#include "main/errors.h" +#include "util/imports.h" #include "main/formats.h" #include "main/framebuffer.h" #include "main/renderbuffer.h" +#include "swrast/s_renderbuffer.h" -#if defined(USE_XSHM) && !defined(XFree86Server) +#define XMESA_RENDERBUFFER 0x1234 + + +#if defined(USE_XSHM) static volatile int mesaXErrorFlag = 0; /** @@ -84,8 +89,9 @@ alloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height) return GL_FALSE; } + /* 0600 = user read+write */ b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line - * b->backxrb->ximage->height, IPC_CREAT|0777); + * b->backxrb->ximage->height, IPC_CREAT | 0600); if (b->shminfo.shmid < 0) { _mesa_warning(NULL, "shmget failed while allocating back buffer.\n"); XDestroyImage(b->backxrb->ximage); @@ -170,7 +176,7 @@ 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) && !defined(XFree86Server) +#if defined(USE_XSHM) if (b->shm) { XShmDetach(b->xm_visual->display, &b->shminfo); XDestroyImage(b->backxrb->ximage); @@ -188,10 +194,6 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) /* Allocate new back buffer */ if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) { /* Allocate a regular XImage for the back buffer. */ -#ifdef XFree86Server - b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel, - width, height, NULL); -#else b->backxrb->ximage = XCreateImage(b->xm_visual->display, b->xm_visual->visinfo->visual, GET_VISUAL_DEPTH(b->xm_visual), @@ -199,12 +201,11 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) NULL, width, height, 8, 0); /* pad, bytes_per_line */ -#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->data = 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"); @@ -236,13 +237,13 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) static void -xmesa_delete_renderbuffer(struct gl_renderbuffer *rb) +xmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { /* XXX Note: the ximage or Pixmap attached to this renderbuffer * should probably get freed here, but that's currently done in * XMesaDestroyBuffer(). */ - _mesa_free(rb); + free(rb); } @@ -251,13 +252,12 @@ xmesa_delete_renderbuffer(struct gl_renderbuffer *rb) * Called via gl_renderbuffer::AllocStorage() */ static GLboolean -xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, +xmesa_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); /* just clear these to be sure we don't accidentally use them */ - xrb->origin1 = NULL; xrb->origin2 = NULL; xrb->origin3 = NULL; xrb->origin4 = NULL; @@ -278,7 +278,7 @@ xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, * Called via gl_renderbuffer::AllocStorage() */ static GLboolean -xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, +xmesa_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); @@ -293,10 +293,6 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, /* plus... */ if (xrb->ximage) { - /* Needed by PIXELADDR1 macro */ - xrb->width1 = xrb->ximage->bytes_per_line; - xrb->origin1 = (GLubyte *) xrb->ximage->data + xrb->width1 * (height - 1); - /* Needed by PIXELADDR2 macro */ xrb->width2 = xrb->ximage->bytes_per_line / 2; xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1); @@ -311,8 +307,7 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, } else { /* out of memory or buffer size is 0 x 0 */ - xrb->width1 = xrb->width2 = xrb->width3 = xrb->width4 = 0; - xrb->origin1 = NULL; + xrb->width2 = xrb->width3 = xrb->width4 = 0; xrb->origin2 = NULL; xrb->origin3 = NULL; xrb->origin4 = NULL; @@ -322,33 +317,51 @@ xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, } +/** + * Used for allocating front/back renderbuffers for an X window. + */ struct xmesa_renderbuffer * -xmesa_new_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual, +xmesa_new_renderbuffer(struct gl_context *ctx, GLuint name, + const struct xmesa_visual *xmvis, GLboolean backBuffer) { struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer); if (xrb) { GLuint name = 0; - _mesa_init_renderbuffer(&xrb->Base, name); + _mesa_init_renderbuffer(&xrb->Base.Base, name); - xrb->Base.Delete = xmesa_delete_renderbuffer; + xrb->Base.Base.Delete = xmesa_delete_renderbuffer; if (backBuffer) - xrb->Base.AllocStorage = xmesa_alloc_back_storage; + xrb->Base.Base.AllocStorage = xmesa_alloc_back_storage; else - xrb->Base.AllocStorage = xmesa_alloc_front_storage; - - if (visual->rgbMode) { - xrb->Base.InternalFormat = GL_RGBA; - xrb->Base.Format = MESA_FORMAT_RGBA8888; - xrb->Base._BaseFormat = GL_RGBA; - xrb->Base.DataType = GL_UNSIGNED_BYTE; - } - else { - xrb->Base.InternalFormat = GL_COLOR_INDEX; - xrb->Base.Format = MESA_FORMAT_CI8; - xrb->Base._BaseFormat = GL_COLOR_INDEX; - xrb->Base.DataType = GL_UNSIGNED_INT; + xrb->Base.Base.AllocStorage = xmesa_alloc_front_storage; + + xrb->Base.Base.InternalFormat = GL_RGBA; + xrb->Base.Base._BaseFormat = GL_RGBA; + xrb->Base.Base.ClassID = XMESA_RENDERBUFFER; + + switch (xmvis->undithered_pf) { + case PF_8R8G8B: + /* This will really only happen for pixmaps. We'll access the + * pixmap via a temporary XImage which will be 32bpp. + */ + xrb->Base.Base.Format = MESA_FORMAT_B8G8R8X8_UNORM; + break; + case PF_8A8R8G8B: + xrb->Base.Base.Format = MESA_FORMAT_B8G8R8A8_UNORM; + break; + case PF_8A8B8G8R: + xrb->Base.Base.Format = MESA_FORMAT_R8G8B8A8_UNORM; + break; + case PF_5R6G5B: + xrb->Base.Base.Format = MESA_FORMAT_B5G6R5_UNORM; + break; + default: + _mesa_warning(ctx, "Bad pixel format in xmesa_new_renderbuffer"); + xrb->Base.Base.Format = MESA_FORMAT_B8G8R8A8_UNORM; + break; } + /* only need to set Red/Green/EtcBits fields for user-created RBs */ } return xrb; @@ -367,16 +380,8 @@ xmesa_delete_framebuffer(struct gl_framebuffer *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)) { -#ifdef XFree86Server - int client = 0; - if (b->frontxrb->drawable) - client = CLIENT_ID(b->frontxrb->drawable->id); - (void)FreeColors(b->cmap, client, - b->num_alloced, b->alloced_colors, 0); -#else XFreeColors(b->display, b->cmap, b->alloced_colors, b->num_alloced, 0); -#endif } } @@ -390,7 +395,7 @@ 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 defined(USE_XSHM) if (b->shm) { XShmDetach( b->display, &b->shminfo ); XDestroyImage( b->backxrb->ximage ); @@ -403,20 +408,153 @@ xmesa_delete_framebuffer(struct gl_framebuffer *fb) } 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 ); + } + } + + _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; } + + xrb->map_ximage = ximage; + + /* the first row of the OpenGL image is last row of the XImage */ + *mapOut = (GLubyte *) ximage->data + + (h - 1) * ximage->bytes_per_line; } + + /* We return a negative stride here since XImage data is upside down + * with respect to OpenGL images. + */ + *rowStrideOut = -ximage->bytes_per_line; + return; } - if (b->rowimage) { - _mesa_free( b->rowimage->data ); - b->rowimage->data = NULL; - XMesaDestroyImage( b->rowimage ); + /* otherwise, this is an ordinary malloc-based renderbuffer */ + _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode, + mapOut, rowStrideOut, false); +} + + +/** + * 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; } - _mesa_free_framebuffer_data(fb); - _mesa_free(fb); + /* otherwise, this is an ordinary malloc-based renderbuffer */ + _swrast_unmap_soft_renderbuffer(ctx, rb); } + +