📄 xm_span.c
字号:
/* * 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 "colormac.h"#include "context.h"#include "depth.h"#include "drawpix.h"#include "extensions.h"#include "macros.h"#include "imports.h"#include "mtypes.h"#include "state.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. */#ifndef XFree86Serverstatic 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;}#endif/* * Read a pixel from an X drawable. */static unsigned long read_pixel( XMesaDisplay *dpy, XMesaDrawable d, int x, int y ){ unsigned long p;#ifndef XFree86Server 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 ); }#else (*dpy->GetImage)(d, x, y, 1, 1, ZPixmap, ~0L, (pointer)&p);#endif 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 \ GLcontext *ctx, \ struct gl_renderbuffer *rb, \ GLuint n, GLint x, GLint y, \ const void *values, const GLubyte mask[]#define RGB_SPAN_ARGS \ GLcontext *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;i<n;i++,x++) { if (mask[i]) { unsigned long p; PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); XMesaSetForeground( dpy, gc, p ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { /* draw all pixels */ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; for (i=0;i<n;i++) { unsigned long p; PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); XMesaPutPixel( rowimg, i, 0, p ); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_TRUECOLOR pixels to a pixmap. */static void put_row_rgb_TRUECOLOR_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;i<n;i++,x++) { if (mask[i]) { unsigned long p; PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ); XMesaSetForeground( dpy, gc, p ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { /* draw all pixels */ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; for (i=0;i<n;i++) { unsigned long p; PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ); XMesaPutPixel( rowimg, i, 0, p ); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_TRUEDITHER pixels to a pixmap. */static void put_row_TRUEDITHER_pixmap( PUT_ROW_ARGS ){ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) 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;i<n;i++,x++) { if (mask[i]) { unsigned long p; PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); XMesaSetForeground( dpy, gc, p ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; for (i=0;i<n;i++) { unsigned long p; PACK_TRUEDITHER(p, x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); XMesaPutPixel( rowimg, i, 0, p ); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_TRUEDITHER pixels to a pixmap (no alpha). */static void put_row_rgb_TRUEDITHER_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;i<n;i++,x++) { if (mask[i]) { unsigned long p; PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); XMesaSetForeground( dpy, gc, p ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; for (i=0;i<n;i++) { unsigned long p; PACK_TRUEDITHER(p, x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); XMesaPutPixel( rowimg, i, 0, p ); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_8A8B8G8R pixels to a pixmap. */static void put_row_8A8B8G8R_pixmap( PUT_ROW_ARGS ){ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) 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;i<n;i++,x++) { if (mask[i]) { XMesaSetForeground( dpy, gc, PACK_8A8B8G8R(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP]) ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { /* draw all pixels */ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;i<n;i++) { *ptr4++ = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_8A8B8G8R pixels to a pixmap (no alpha). */static void put_row_rgb_8A8B8G8R_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;i<n;i++,x++) { if (mask[i]) { XMesaSetForeground( dpy, gc, PACK_8B8G8R(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { /* draw all pixels */ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;i<n;i++) { *ptr4++ = PACK_8B8G8R(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_8A8R8G8B pixels to a pixmap. */static void put_row_8A8R8G8B_pixmap( PUT_ROW_ARGS ){ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) 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;i<n;i++,x++) { if (mask[i]) { XMesaSetForeground( dpy, gc, PACK_8A8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP]) ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } } else { /* draw all pixels */ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage; register GLuint *ptr4 = (GLuint *) rowimg->data; for (i=0;i<n;i++) { *ptr4++ = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); } XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); }}/* * Write a span of PF_8A8R8G8B pixels to a pixmap (no alpha). */static void put_row_rgb_8A8R8G8B_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;i<n;i++,x++) { if (mask[i]) { XMesaSetForeground( dpy, gc, PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) ); XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y ); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -