/* * Mesa 3-D graphics library * Version: 6.3 * * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * 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. */ #include "glxheader.h" #include "main/context.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" #include "xmesaP.h" #include "swrast/swrast.h" /* * The following functions are used to trap XGetImage() calls which * generate BadMatch errors if the drawable isn't mapped. */ static int caught_xgetimage_error = 0; static int (*old_xerror_handler)( XMesaDisplay *dpy, XErrorEvent *ev ); static unsigned long xgetimage_serial; /* * This is the error handler which will be called if XGetImage fails. */ static int xgetimage_error_handler( XMesaDisplay *dpy, XErrorEvent *ev ) { if (ev->serial==xgetimage_serial && ev->error_code==BadMatch) { /* caught the expected error */ caught_xgetimage_error = 0; } else { /* call the original X error handler, if any. otherwise ignore */ if (old_xerror_handler) { (*old_xerror_handler)( dpy, ev ); } } return 0; } /* * Call this right before XGetImage to setup error trap. */ static void catch_xgetimage_errors( XMesaDisplay *dpy ) { xgetimage_serial = NextRequest( dpy ); old_xerror_handler = XSetErrorHandler( xgetimage_error_handler ); caught_xgetimage_error = 0; } /* * Call this right after XGetImage to check if an error occured. */ static int check_xgetimage_errors( void ) { /* restore old handler */ (void) XSetErrorHandler( old_xerror_handler ); /* return 0=no error, 1=error caught */ return caught_xgetimage_error; } /* * Read a pixel from an X drawable. */ static unsigned long read_pixel( XMesaDisplay *dpy, XMesaDrawable d, int x, int y ) { unsigned long p; XMesaImage *pixel = NULL; int error; catch_xgetimage_errors( dpy ); pixel = XGetImage( dpy, d, x, y, 1, 1, AllPlanes, ZPixmap ); error = check_xgetimage_errors(); if (pixel && !error) { p = XMesaGetPixel( pixel, 0, 0 ); } else { p = 0; } if (pixel) { XMesaDestroyImage( pixel ); } return p; } /* * The Mesa library needs to be able to draw pixels in a number of ways: * 1. RGB vs Color Index * 2. as horizontal spans (polygons, images) vs random locations (points, * lines) * 3. different color per-pixel or same color for all pixels * * Furthermore, the X driver needs to support rendering to 3 possible * "buffers", usually one, but sometimes two at a time: * 1. The front buffer as an X window * 2. The back buffer as a Pixmap * 3. The back buffer as an XImage * * Finally, if the back buffer is an XImage, we can avoid using XPutPixel and * optimize common cases such as 24-bit and 8-bit modes. * * By multiplication, there's at least 48 possible combinations of the above. * * Below are implementations of the most commonly used combinations. They are * accessed through function pointers which get initialized here and are used * directly from the Mesa library. The 8 function pointers directly correspond * to the first 3 cases listed above. * * * The function naming convention is: * * [put|get]_[mono]_[row|values]_[format]_[pixmap|ximage] * * New functions optimized for specific cases can be added without too much * trouble. An example might be the 24-bit TrueColor mode 8A8R8G8B which is * found on IBM RS/6000 X servers. */ /**********************************************************************/ /*** Write COLOR SPAN functions ***/ /**********************************************************************/ #define PUT_ROW_ARGS \ struct gl_context *ctx, \ struct gl_renderbuffer *rb, \ GLuint n, GLint x, GLint y, \ const void *values, const GLubyte mask[] #define RGB_SPAN_ARGS \ struct gl_context *ctx, \ struct gl_renderbuffer *rb, \ GLuint n, GLint x, GLint y, \ const void *values, const GLubyte mask[] #define GET_XRB(XRB) \ struct xmesa_renderbuffer *XRB = xmesa_renderbuffer(rb) /* * Write a span of PF_TRUECOLOR pixels to a pixmap. */ static void put_row_TRUECOLOR_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); GET_XRB(xrb); XMesaDisplay *dpy = XMESA_BUFFER(ctx->DrawBuffer)->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; GLuint *ptr4 = (GLuint *) rowimg->data; *ptr4 = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, 1, 1 ); #endif } } } else { /* draw all pixels */ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; y = YFLIP(xrb, y); if (mask) { register GLuint i; for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; register GLuint pixel; static const GLuint shift[4] = {0, 8, 16, 24}; register GLuint i = 0; int w = n; while (w > 3) { pixel = rgba[i][BCOMP] /* << shift[0]*/; pixel |= rgba[i][GCOMP] << shift[1]; pixel |= rgba[i++][RCOMP] << shift[2]; pixel |= rgba[i][BCOMP] << shift[3]; *ptr4++ = pixel; pixel = rgba[i][GCOMP] /* << shift[0]*/; pixel |= rgba[i++][RCOMP] << shift[1]; pixel |= rgba[i][BCOMP] << shift[2]; pixel |= rgba[i][GCOMP] << shift[3]; *ptr4++ = pixel; pixel = rgba[i++][RCOMP]/* << shift[0]*/; pixel |= rgba[i][BCOMP] << shift[1]; pixel |= rgba[i][GCOMP] << shift[2]; pixel |= rgba[i++][RCOMP] << shift[3]; *ptr4++ = pixel; w -= 4; } switch (w) { case 3: pixel = 0; pixel |= rgba[i][BCOMP] /*<< shift[0]*/; pixel |= rgba[i][GCOMP] << shift[1]; pixel |= rgba[i++][RCOMP] << shift[2]; pixel |= rgba[i][BCOMP] << shift[3]; *ptr4++ = pixel; pixel = 0; pixel |= rgba[i][GCOMP] /*<< shift[0]*/; pixel |= rgba[i++][RCOMP] << shift[1]; pixel |= rgba[i][BCOMP] << shift[2]; pixel |= rgba[i][GCOMP] << shift[3]; *ptr4++ = pixel; pixel = 0xffffff00 & *ptr4; pixel |= rgba[i][RCOMP] /*<< shift[0]*/; *ptr4 = pixel; break; case 2: pixel = 0; pixel |= rgba[i][BCOMP] /*<< shift[0]*/; pixel |= rgba[i][GCOMP] << shift[1]; pixel |= rgba[i++][RCOMP] << shift[2]; pixel |= rgba[i][BCOMP] << shift[3]; *ptr4++ = pixel; pixel = 0xffff0000 & *ptr4; pixel |= rgba[i][GCOMP] /*<< shift[0]*/; pixel |= rgba[i][RCOMP] << shift[1]; *ptr4 = pixel; break; case 1: pixel = 0xff000000 & *ptr4; pixel |= rgba[i][BCOMP] /*<< shift[0]*/; pixel |= rgba[i][GCOMP] << shift[1]; pixel |= rgba[i][RCOMP] << shift[2]; *ptr4 = pixel; break; case 0: break; } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); } } /* * Write a span of PF_8R8G8B pixels to a pixmap (no alpha). */ static void put_row_rgb_8R8G8B_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; y = YFLIP(xrb, y); if (mask) { register GLuint i; for (i=0;iDrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; register GLuint pixel; static const GLuint shift[4] = {0, 8, 16, 24}; unsigned w = n; register GLuint i = 0; while (w > 3) { pixel = 0; pixel |= rgb[i][BCOMP]/* << shift[0]*/; pixel |= rgb[i][GCOMP] << shift[1]; pixel |= rgb[i++][RCOMP] << shift[2]; pixel |= rgb[i][BCOMP] <xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLushort *ptr2 = (GLushort *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLushort *ptr2 = (GLushort *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLushort *ptr2 = (GLushort *) rowimg->data; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iDrawBuffer)->rowimage; register GLushort *ptr2 = (GLushort *) rowimg->data; for (i=0;iximage; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iximage; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iximage; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;iximage; register GLuint i; y = YFLIP(xrb, y); if (mask) { for (i=0;i 3) { pixel = rgba[i][BCOMP]; pixel |= rgba[i][GCOMP] << 8; pixel |= rgba[i++][RCOMP] << 16; pixel |= rgba[i][BCOMP] << 24; *ptr4++ = pixel; pixel = rgba[i][GCOMP]; pixel |= rgba[i++][RCOMP] << 8; pixel |= rgba[i][BCOMP] << 16; pixel |= rgba[i][GCOMP] << 24; *ptr4++ = pixel; pixel = rgba[i++][RCOMP]; pixel |= rgba[i][BCOMP] << 8; pixel |= rgba[i][GCOMP] << 16; pixel |= rgba[i++][RCOMP] << 24; *ptr4++ = pixel; w -= 4; } switch (w) { case 0: break; case 1: pixel = *ptr4 & 0xff000000; pixel |= rgba[i][BCOMP]; pixel |= rgba[i][GCOMP] << 8; pixel |= rgba[i][RCOMP] << 16; *ptr4 = pixel; break; case 2: pixel = rgba[i][BCOMP]; pixel |= rgba[i][GCOMP] << 8; pixel |= rgba[i++][RCOMP] << 16; pixel |= rgba[i][BCOMP] << 24; *ptr4++ = pixel; pixel = *ptr4 & 0xffff0000; pixel |= rgba[i][GCOMP]; pixel |= rgba[i][RCOMP] << 8; *ptr4 = pixel; break; case 3: pixel = rgba[i][BCOMP]; pixel |= rgba[i][GCOMP] << 8; pixel |= rgba[i++][RCOMP] << 16; pixel |= rgba[i][BCOMP] << 24; *ptr4++ = pixel; pixel = rgba[i][GCOMP]; pixel |= rgba[i++][RCOMP] << 8; pixel |= rgba[i][BCOMP] << 16; pixel |= rgba[i][GCOMP] << 24; *ptr4++ = pixel; pixel = *ptr4 & 0xffffff00; pixel |= rgba[i][RCOMP]; *ptr4 = pixel; break; } } } /* * Write a span of PF_8R8G8B-format pixels to an ximage (no alpha). */ static void put_row_rgb_8R8G8B_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); if (mask) { for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; for (i=0;iximage; register GLuint i; for (i=0;iximage; register GLuint i; for (i=0;ir = rgba[i][RCOMP]; ptr->g = rgba[i][GCOMP]; ptr->b = rgba[i][BCOMP]; } } } /* * Write an array of PF_5R6G5B pixels to an ximage. */ static void put_values_5R6G5B_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; GET_XRB(xrb); register GLuint i; for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); register GLuint i; XMesaSetForeground( xmesa->display, gc, pixel ); y = YFLIP(xrb, y); /* New code contributed by Jeff Epler and cleaned up by Keith * Whitwell. */ for (i = 0; i < n; ) { GLuint start = i; /* Identify and emit contiguous rendered pixels */ while (i < n && (!mask || mask[i])) i++; if (start < i) XMesaFillRectangle( dpy, buffer, gc, (int)(x+start), (int) y, (int)(i-start), 1); /* Eat up non-rendered pixels */ while (i < n && !mask[i]) i++; } } /* * Write a span of PF_TRUEDITHER pixels to a pixmap. */ static void put_mono_row_TRUEDITHER_pixmap( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLuint i; int yy = YFLIP(xrb, y); for (i=0;iximage; register GLuint i; const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); y = YFLIP(xrb, y); for (i=0;iximage; const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; GLuint i; y = YFLIP(xrb, y); for (i=0;ipixelformat); ptr = PIXEL_ADDR4(xrb, x, y ); for (i=0;ipixelformat); ptr = PIXEL_ADDR4(xrb, x, y ); for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); XMesaSetForeground( xmesa->display, gc, pixel ); for (i=0;ixm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; register GLuint i; const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; for (i=0;iximage; register GLuint i; const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); for (i=0;iximage; register GLuint i; const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; for (i=0;ir = r; ptr->g = g; ptr->b = b; } } } /* * Write an array of identical PF_DITHER_5R6G5B pixels to an XImage. */ static void put_mono_values_DITHER_5R6G5B_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLuint i; for (i=0;iDrawBuffer); Window rootWin = RootWindow(xmesa->display, 0); Window child; GLint screenWidth = WidthOfScreen(DefaultScreenOfDisplay(xmesa->display)); GLint dx, dy; if (source->type == PBUFFER || source->type == PIXMAP) return 0; XTranslateCoordinates(xmesa->display, pixmap, rootWin, *x, *y, &dx, &dy, &child); if (dx >= screenWidth) { /* totally clipped on right */ return -1; } if (dx < 0) { /* clipped on left */ GLint clip = -dx; if (clip >= (GLint) *n) return -1; /* totally clipped on left */ *x += clip; *n -= clip; dx = 0; return clip; } if ((GLint) (dx + *n) > screenWidth) { /* clipped on right */ GLint clip = dx + *n - screenWidth; *n -= clip; } return 0; } /* * Read a horizontal span of color pixels. */ static void get_row_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, void *values) { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); GET_XRB(xrb); if (xrb->pixmap) { /* Read from Pixmap or Window */ XMesaImage *span = NULL; int error; int k; y = YFLIP(xrb, y); k = clip_for_xgetimage(ctx, xrb->pixmap, &n, &x, &y); if (k < 0) return; rgba += k; catch_xgetimage_errors( xmesa->display ); span = XGetImage( xmesa->display, xrb->pixmap, x, y, n, 1, AllPlanes, ZPixmap ); error = check_xgetimage_errors(); if (span && !error) { switch (xmesa->pixelformat) { case PF_Truecolor: case PF_Dither_True: { const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; unsigned long rMask = GET_REDMASK(xmesa->xm_visual); unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); GLint rShift = xmesa->xm_visual->rshift; GLint gShift = xmesa->xm_visual->gshift; GLint bShift = xmesa->xm_visual->bshift; GLuint i; for (i=0;i> rShift]; rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; rgba[i][ACOMP] = 255; } } break; case PF_5R6G5B: case PF_Dither_5R6G5B: { const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; GLuint i; for (i=0;i> 8) & 0xf8); rgba[i][GCOMP] = ((p >> 3) & 0xfc); rgba[i][BCOMP] = ((p << 3) & 0xff); */ rgba[i][RCOMP] = pixelToR[p >> 11]; rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f]; rgba[i][BCOMP] = pixelToB[p & 0x1f]; rgba[i][ACOMP] = 255; } } break; case PF_8A8B8G8R: { const GLuint *ptr4 = (GLuint *) span->data; GLuint i; for (i=0;i> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff); rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); } } break; case PF_8A8R8G8B: { const GLuint *ptr4 = (GLuint *) span->data; GLuint i; for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); } } break; case PF_8R8G8B: { const GLuint *ptr4 = (GLuint *) span->data; GLuint i; for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); rgba[i][ACOMP] = 255; } } break; case PF_8R8G8B24: { const bgr_t *ptr3 = (bgr_t *) span->data; GLuint i; for (i=0;iximage) { /* Read from XImage back buffer */ switch (xmesa->pixelformat) { case PF_Truecolor: case PF_Dither_True: { const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; unsigned long rMask = GET_REDMASK(xmesa->xm_visual); unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); GLint rShift = xmesa->xm_visual->rshift; GLint gShift = xmesa->xm_visual->gshift; GLint bShift = xmesa->xm_visual->bshift; XMesaImage *img = xrb->ximage; GLuint i; y = YFLIP(xrb, y); for (i=0;i> rShift]; rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; rgba[i][ACOMP] = 255; } } break; case PF_5R6G5B: case PF_Dither_5R6G5B: { const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; const GLushort *ptr2 = PIXEL_ADDR2(xrb, x, y); GLuint i; #if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */ const GLuint *ptr4 = (const GLuint *) ptr2; GLuint extraPixel = (n & 1); n -= extraPixel; for (i = 0; i < n; i += 2) { const GLuint p = *ptr4++; const GLuint p0 = p & 0xffff; const GLuint p1 = p >> 16; /* fast, but not quite accurate rgba[i][RCOMP] = ((p >> 8) & 0xf8); rgba[i][GCOMP] = ((p >> 3) & 0xfc); rgba[i][BCOMP] = ((p << 3) & 0xff); */ rgba[i][RCOMP] = pixelToR[p0 >> 11]; rgba[i][GCOMP] = pixelToG[(p0 >> 5) & 0x3f]; rgba[i][BCOMP] = pixelToB[p0 & 0x1f]; rgba[i][ACOMP] = 255; rgba[i+1][RCOMP] = pixelToR[p1 >> 11]; rgba[i+1][GCOMP] = pixelToG[(p1 >> 5) & 0x3f]; rgba[i+1][BCOMP] = pixelToB[p1 & 0x1f]; rgba[i+1][ACOMP] = 255; } if (extraPixel) { GLushort p = ptr2[n]; rgba[n][RCOMP] = pixelToR[p >> 11]; rgba[n][GCOMP] = pixelToG[(p >> 5) & 0x3f]; rgba[n][BCOMP] = pixelToB[p & 0x1f]; rgba[n][ACOMP] = 255; } #else for (i = 0; i < n; i++) { const GLushort p = ptr2[i]; rgba[i][RCOMP] = pixelToR[p >> 11]; rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f]; rgba[i][BCOMP] = pixelToB[p & 0x1f]; rgba[i][ACOMP] = 255; } #endif } break; case PF_8A8B8G8R: { const GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y); GLuint i; for (i=0;i> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff); rgba[i][ACOMP] = (GLint) ((p4 >> 24) & 0xff); } } break; case PF_8A8R8G8B: { const GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y); GLuint i; for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); rgba[i][ACOMP] = (GLint) ((p4 >> 24) & 0xff); } } break; case PF_8R8G8B: { const GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y); GLuint i; for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); rgba[i][ACOMP] = 255; } } break; case PF_8R8G8B24: { const bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y); GLuint i; for (i=0;ixm_visual->display; register GLuint i; if (xrb->pixmap) { XMesaDrawable buffer = xrb->drawable; switch (xmesa->pixelformat) { case PF_Truecolor: case PF_Dither_True: case PF_5R6G5B: case PF_Dither_5R6G5B: { unsigned long rMask = GET_REDMASK(xmesa->xm_visual); unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); GLubyte *pixelToR = xmesa->xm_visual->PixelToR; GLubyte *pixelToG = xmesa->xm_visual->PixelToG; GLubyte *pixelToB = xmesa->xm_visual->PixelToB; GLint rShift = xmesa->xm_visual->rshift; GLint gShift = xmesa->xm_visual->gshift; GLint bShift = xmesa->xm_visual->bshift; for (i=0;i> rShift]; rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; rgba[i][ACOMP] = 255; } } break; case PF_8A8B8G8R: for (i=0;i> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ((p >> 16) & 0xff); rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff); } break; case PF_8A8R8G8B: for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p & 0xff); rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff); } break; case PF_8R8G8B: for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p & 0xff); rgba[i][ACOMP] = 255; } break; case PF_8R8G8B24: for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p & 0xff); rgba[i][ACOMP] = 255; } break; default: _mesa_problem(NULL,"Problem in DD.read_color_pixels (1)"); return; } } else if (xrb->ximage) { /* Read from XImage back buffer */ switch (xmesa->pixelformat) { case PF_Truecolor: case PF_Dither_True: case PF_5R6G5B: case PF_Dither_5R6G5B: { unsigned long rMask = GET_REDMASK(xmesa->xm_visual); unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); GLubyte *pixelToR = xmesa->xm_visual->PixelToR; GLubyte *pixelToG = xmesa->xm_visual->PixelToG; GLubyte *pixelToB = xmesa->xm_visual->PixelToB; GLint rShift = xmesa->xm_visual->rshift; GLint gShift = xmesa->xm_visual->gshift; GLint bShift = xmesa->xm_visual->bshift; XMesaImage *img = xrb->ximage; for (i=0;i> rShift]; rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; rgba[i][ACOMP] = 255; } } break; case PF_8A8B8G8R: for (i=0;i> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff); rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); } break; case PF_8A8R8G8B: for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); } break; case PF_8R8G8B: for (i=0;i> 16) & 0xff); rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); rgba[i][ACOMP] = 255; } break; case PF_8R8G8B24: for (i=0;ir; rgba[i][GCOMP] = ptr3->g; rgba[i][BCOMP] = ptr3->b; rgba[i][ACOMP] = 255; } break; default: _mesa_problem(NULL,"Problem in DD.read_color_pixels (1)"); return; } } } /** * Initialize the renderbuffer's PutRow, GetRow, etc. functions. * This would generally only need to be called once when the renderbuffer * is created. However, we can change pixel formats on the fly if dithering * is enabled/disabled. Therefore, we may call this more often than that. */ void xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb, enum pixel_format pixelformat, GLint depth) { const GLboolean pixmap = xrb->pixmap ? GL_TRUE : GL_FALSE; switch (pixelformat) { case PF_Truecolor: if (pixmap) { xrb->Base.PutRow = put_row_TRUECOLOR_pixmap; xrb->Base.PutRowRGB = put_row_rgb_TRUECOLOR_pixmap; xrb->Base.PutMonoRow = put_mono_row_pixmap; xrb->Base.PutValues = put_values_TRUECOLOR_pixmap; xrb->Base.PutMonoValues = put_mono_values_pixmap; } else { xrb->Base.PutRow = put_row_TRUECOLOR_ximage; xrb->Base.PutRowRGB = put_row_rgb_TRUECOLOR_ximage; xrb->Base.PutMonoRow = put_mono_row_ximage; xrb->Base.PutValues = put_values_TRUECOLOR_ximage; xrb->Base.PutMonoValues = put_mono_values_ximage; } break; case PF_Dither_True: if (pixmap) { xrb->Base.PutRow = put_row_TRUEDITHER_pixmap; xrb->Base.PutRowRGB = put_row_rgb_TRUEDITHER_pixmap; xrb->Base.PutMonoRow = put_mono_row_TRUEDITHER_pixmap; xrb->Base.PutValues = put_values_TRUEDITHER_pixmap; xrb->Base.PutMonoValues = put_mono_values_TRUEDITHER_pixmap; } else { xrb->Base.PutRow = put_row_TRUEDITHER_ximage; xrb->Base.PutRowRGB = put_row_rgb_TRUEDITHER_ximage; xrb->Base.PutMonoRow = put_mono_row_TRUEDITHER_ximage; xrb->Base.PutValues = put_values_TRUEDITHER_ximage; xrb->Base.PutMonoValues = put_mono_values_TRUEDITHER_ximage; } break; case PF_8A8B8G8R: if (pixmap) { xrb->Base.PutRow = put_row_8A8B8G8R_pixmap; xrb->Base.PutRowRGB = put_row_rgb_8A8B8G8R_pixmap; xrb->Base.PutMonoRow = put_mono_row_pixmap; xrb->Base.PutValues = put_values_8A8B8G8R_pixmap; xrb->Base.PutMonoValues = put_mono_values_pixmap; } else { xrb->Base.PutRow = put_row_8A8B8G8R_ximage; xrb->Base.PutRowRGB = put_row_rgb_8A8B8G8R_ximage; xrb->Base.PutMonoRow = put_mono_row_8A8B8G8R_ximage; xrb->Base.PutValues = put_values_8A8B8G8R_ximage; xrb->Base.PutMonoValues = put_mono_values_8A8B8G8R_ximage; } break; case PF_8A8R8G8B: if (pixmap) { xrb->Base.PutRow = put_row_8A8R8G8B_pixmap; xrb->Base.PutRowRGB = put_row_rgb_8A8R8G8B_pixmap; xrb->Base.PutMonoRow = put_mono_row_pixmap; xrb->Base.PutValues = put_values_8A8R8G8B_pixmap; xrb->Base.PutMonoValues = put_mono_values_pixmap; } else { xrb->Base.PutRow = put_row_8A8R8G8B_ximage; xrb->Base.PutRowRGB = put_row_rgb_8A8R8G8B_ximage; xrb->Base.PutMonoRow = put_mono_row_8A8R8G8B_ximage; xrb->Base.PutValues = put_values_8A8R8G8B_ximage; xrb->Base.PutMonoValues = put_mono_values_8A8R8G8B_ximage; } break; case PF_8R8G8B: if (pixmap) { xrb->Base.PutRow = put_row_8R8G8B_pixmap; xrb->Base.PutRowRGB = put_row_rgb_8R8G8B_pixmap; xrb->Base.PutMonoRow = put_mono_row_pixmap; xrb->Base.PutValues = put_values_8R8G8B_pixmap; xrb->Base.PutMonoValues = put_mono_values_pixmap; } else { xrb->Base.PutRow = put_row_8R8G8B_ximage; xrb->Base.PutRowRGB = put_row_rgb_8R8G8B_ximage; xrb->Base.PutMonoRow = put_mono_row_8R8G8B_ximage; xrb->Base.PutValues = put_values_8R8G8B_ximage; xrb->Base.PutMonoValues = put_mono_values_8R8G8B_ximage; } break; case PF_8R8G8B24: if (pixmap) { xrb->Base.PutRow = put_row_8R8G8B24_pixmap; xrb->Base.PutRowRGB = put_row_rgb_8R8G8B24_pixmap; xrb->Base.PutMonoRow = put_mono_row_pixmap; xrb->Base.PutValues = put_values_8R8G8B24_pixmap; xrb->Base.PutMonoValues = put_mono_values_pixmap; } else { xrb->Base.PutRow = put_row_8R8G8B24_ximage; xrb->Base.PutRowRGB = put_row_rgb_8R8G8B24_ximage; xrb->Base.PutMonoRow = put_mono_row_8R8G8B24_ximage; xrb->Base.PutValues = put_values_8R8G8B24_ximage; xrb->Base.PutMonoValues = put_mono_values_8R8G8B24_ximage; } break; case PF_5R6G5B: if (pixmap) { xrb->Base.PutRow = put_row_5R6G5B_pixmap; xrb->Base.PutRowRGB = put_row_rgb_5R6G5B_pixmap; xrb->Base.PutMonoRow = put_mono_row_pixmap; xrb->Base.PutValues = put_values_5R6G5B_pixmap; xrb->Base.PutMonoValues = put_mono_values_pixmap; } else { xrb->Base.PutRow = put_row_5R6G5B_ximage; xrb->Base.PutRowRGB = put_row_rgb_5R6G5B_ximage; xrb->Base.PutMonoRow = put_mono_row_ximage; xrb->Base.PutValues = put_values_5R6G5B_ximage; xrb->Base.PutMonoValues = put_mono_values_ximage; } break; case PF_Dither_5R6G5B: if (pixmap) { xrb->Base.PutRow = put_row_DITHER_5R6G5B_pixmap; xrb->Base.PutRowRGB = put_row_rgb_DITHER_5R6G5B_pixmap; xrb->Base.PutMonoRow = put_mono_row_TRUEDITHER_pixmap; xrb->Base.PutValues = put_values_DITHER_5R6G5B_pixmap; xrb->Base.PutMonoValues = put_mono_values_TRUEDITHER_pixmap; } else { xrb->Base.PutRow = put_row_DITHER_5R6G5B_ximage; xrb->Base.PutRowRGB = put_row_rgb_DITHER_5R6G5B_ximage; xrb->Base.PutMonoRow = put_mono_row_DITHER_5R6G5B_ximage; xrb->Base.PutValues = put_values_DITHER_5R6G5B_ximage; xrb->Base.PutMonoValues = put_mono_values_DITHER_5R6G5B_ximage; } break; default: _mesa_problem(NULL, "Bad pixel format in xmesa_update_state (1)"); return; } /* Get functions */ xrb->Base.GetRow = get_row_rgba; xrb->Base.GetValues = get_values_rgba; }