summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/x11/xm_dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/x11/xm_dd.c')
-rw-r--r--src/mesa/drivers/x11/xm_dd.c1006
1 files changed, 1006 insertions, 0 deletions
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
new file mode 100644
index 00000000000..271cb13f083
--- /dev/null
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -0,0 +1,1006 @@
+/* $Id: xm_dd.c,v 1.1 2000/09/07 15:40:30 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.3
+ *
+ * Copyright (C) 1999-2000 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 "context.h"
+#include "drawpix.h"
+#include "mem.h"
+#include "state.h"
+#include "depth.h"
+#include "macros.h"
+#include "vb.h"
+#include "types.h"
+#include "xmesaP.h"
+#include "extensions.h"
+
+
+/*
+ * Return the size (width,height of the current color buffer.
+ * This function should be called by the glViewport function because
+ * glViewport is often called when the window gets resized. We need to
+ * update some X/Mesa stuff when that happens.
+ * Output: width - width of buffer in pixels.
+ * height - height of buffer in pixels.
+ */
+static void
+get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ unsigned int winwidth, winheight;
+#ifndef XFree86Server
+ Window root;
+ int winx, winy;
+ unsigned int bw, d;
+
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XGetGeometry( xmesa->display, xmesa->xm_buffer->frontbuffer, &root,
+ &winx, &winy, &winwidth, &winheight, &bw, &d );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+#else
+
+ winwidth = xmesa->xm_buffer->frontbuffer->width;
+ winheight = xmesa->xm_buffer->frontbuffer->height;
+#endif
+
+ *width = winwidth;
+ *height = winheight;
+
+ if ( winwidth!=xmesa->xm_buffer->width
+ || winheight!=xmesa->xm_buffer->height) {
+ xmesa->xm_buffer->width = winwidth;
+ xmesa->xm_buffer->height = winheight;
+ xmesa_alloc_back_buffer( xmesa->xm_buffer );
+ }
+
+ /* Needed by FLIP macro */
+ xmesa->xm_buffer->bottom = (int) winheight - 1;
+
+ if (xmesa->xm_buffer->backimage) {
+ /* Needed by PIXELADDR1 macro */
+ xmesa->xm_buffer->ximage_width1
+ = xmesa->xm_buffer->backimage->bytes_per_line;
+ xmesa->xm_buffer->ximage_origin1
+ = (GLubyte *) xmesa->xm_buffer->backimage->data
+ + xmesa->xm_buffer->ximage_width1 * (winheight-1);
+
+ /* Needed by PIXELADDR2 macro */
+ xmesa->xm_buffer->ximage_width2
+ = xmesa->xm_buffer->backimage->bytes_per_line / 2;
+ xmesa->xm_buffer->ximage_origin2
+ = (GLushort *) xmesa->xm_buffer->backimage->data
+ + xmesa->xm_buffer->ximage_width2 * (winheight-1);
+
+ /* Needed by PIXELADDR3 macro */
+ xmesa->xm_buffer->ximage_width3
+ = xmesa->xm_buffer->backimage->bytes_per_line;
+ xmesa->xm_buffer->ximage_origin3
+ = (GLubyte *) xmesa->xm_buffer->backimage->data
+ + xmesa->xm_buffer->ximage_width3 * (winheight-1);
+
+ /* Needed by PIXELADDR4 macro */
+ xmesa->xm_buffer->ximage_width4 = xmesa->xm_buffer->backimage->width;
+ xmesa->xm_buffer->ximage_origin4
+ = (GLuint *) xmesa->xm_buffer->backimage->data
+ + xmesa->xm_buffer->ximage_width4 * (winheight-1);
+ }
+}
+
+
+static void
+finish( GLcontext *ctx )
+{
+#ifdef XFree86Server
+ /* NOT_NEEDED */
+#else
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (xmesa) {
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XSync( xmesa->display, False );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+ }
+#endif
+}
+
+
+static void
+flush( GLcontext *ctx )
+{
+#ifdef XFree86Server
+ /* NOT_NEEDED */
+#else
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (xmesa) {
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XFlush( xmesa->display );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+ }
+#endif
+}
+
+
+#if 0
+static GLboolean
+set_buffer( GLcontext *ctx, GLenum mode )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (mode == GL_FRONT_LEFT) {
+ /* read/write front buffer */
+ xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
+ ctx->NewState |= NEW_RASTER_OPS;
+ gl_update_state(ctx);
+ return GL_TRUE;
+ }
+ else if (mode==GL_BACK_LEFT && xmesa->xm_buffer->db_state) {
+ /* read/write back buffer */
+ if (xmesa->xm_buffer->backpixmap) {
+ xmesa->xm_buffer->buffer =
+ (XMesaDrawable)xmesa->xm_buffer->backpixmap;
+ }
+ else if (xmesa->xm_buffer->backimage) {
+ xmesa->xm_buffer->buffer = None;
+ }
+ else {
+ /* just in case there wasn't enough memory for back buffer */
+ xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
+ }
+ ctx->NewState |= NEW_RASTER_OPS;
+ gl_update_state(ctx);
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+#endif
+
+
+static GLboolean
+set_draw_buffer( GLcontext *ctx, GLenum mode )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (mode == GL_FRONT_LEFT) {
+ /* write to front buffer */
+ xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
+ xmesa_update_span_funcs(ctx);
+ return GL_TRUE;
+ }
+ else if (mode==GL_BACK_LEFT && xmesa->xm_buffer->db_state) {
+ /* write to back buffer */
+ if (xmesa->xm_buffer->backpixmap) {
+ xmesa->xm_buffer->buffer =
+ (XMesaDrawable)xmesa->xm_buffer->backpixmap;
+ }
+ else if (xmesa->xm_buffer->backimage) {
+ xmesa->xm_buffer->buffer = None;
+ }
+ else {
+ /* just in case there wasn't enough memory for back buffer */
+ xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
+ }
+ xmesa_update_span_funcs(ctx);
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+static void
+set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
+{
+ XMesaBuffer target;
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+
+ if (buffer == ctx->DrawBuffer) {
+ target = xmesa->xm_buffer;
+ xmesa->use_read_buffer = GL_FALSE;
+ }
+ else {
+ ASSERT(buffer == ctx->ReadBuffer);
+ target = xmesa->xm_read_buffer;
+ xmesa->use_read_buffer = GL_TRUE;
+ }
+
+ if (mode == GL_FRONT_LEFT) {
+ target->buffer = target->frontbuffer;
+ xmesa_update_span_funcs(ctx);
+ }
+ else if (mode==GL_BACK_LEFT && xmesa->xm_read_buffer->db_state) {
+ if (target->backpixmap) {
+ target->buffer = (XMesaDrawable)xmesa->xm_buffer->backpixmap;
+ }
+ else if (target->backimage) {
+ target->buffer = None;
+ }
+ else {
+ /* just in case there wasn't enough memory for back buffer */
+ target->buffer = target->frontbuffer;
+ }
+ xmesa_update_span_funcs(ctx);
+ }
+ else {
+ gl_problem(ctx, "invalid buffer in set_read_buffer() in xmesa2.c");
+ }
+}
+
+
+
+static void
+clear_index( GLcontext *ctx, GLuint index )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ xmesa->clearpixel = (unsigned long) index;
+ XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
+ (unsigned long) index );
+}
+
+
+static void
+clear_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ xmesa->clearcolor[0] = r;
+ xmesa->clearcolor[1] = g;
+ xmesa->clearcolor[2] = b;
+ xmesa->clearcolor[3] = a;
+ xmesa->clearpixel = xmesa_color_to_pixel( xmesa, r, g, b, a,
+ xmesa->xm_visual->undithered_pf );
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
+ xmesa->clearpixel );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+}
+
+
+
+/* Set current color index */
+static void
+set_index( GLcontext *ctx, GLuint index )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ unsigned long p = (unsigned long) index;
+ xmesa->pixel = p;
+ XMesaSetForeground( xmesa->display, xmesa->xm_buffer->gc1, p );
+}
+
+
+
+/* Set current drawing color */
+static void
+set_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ xmesa->red = r;
+ xmesa->green = g;
+ xmesa->blue = b;
+ xmesa->alpha = a;
+ xmesa->pixel = xmesa_color_to_pixel( xmesa, r, g, b, a, xmesa->pixelformat );;
+ XMesaSetForeground( xmesa->display, xmesa->xm_buffer->gc1, xmesa->pixel );
+}
+
+
+
+/* Set index mask ala glIndexMask */
+static void
+index_mask( GLcontext *ctx, GLuint mask )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (xmesa->xm_buffer->buffer != XIMAGE) {
+ unsigned long m;
+ if (mask==0xffffffff) {
+ m = ((unsigned long)~0L);
+ }
+ else {
+ m = (unsigned long) mask;
+ }
+ XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
+ }
+}
+
+
+/* Implements glColorMask() */
+static void
+color_mask(GLcontext *ctx,
+ GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ int xclass = GET_VISUAL_CLASS(xmesa->xm_visual);
+ (void) amask;
+
+ if (xmesa->xm_buffer->buffer != XIMAGE
+ && (xclass == TrueColor || xclass == DirectColor)) {
+ unsigned long m;
+ if (rmask && gmask && bmask) {
+ m = ((unsigned long)~0L);
+ }
+ else {
+ m = 0;
+ if (rmask) m |= GET_REDMASK(xmesa->xm_visual);
+ if (gmask) m |= GET_GREENMASK(xmesa->xm_visual);
+ if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual);
+ }
+ XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
+ }
+}
+
+
+/*
+ * Enable/disable dithering
+ */
+static void
+dither( GLcontext *ctx, GLboolean enable )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (enable) {
+ xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
+ }
+ else {
+ xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
+ }
+}
+
+
+
+/**********************************************************************/
+/*** glClear implementations ***/
+/**********************************************************************/
+
+
+static void
+clear_front_pixmap( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (all) {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
+ xmesa->xm_buffer->cleargc,
+ 0, 0,
+ xmesa->xm_buffer->width+1,
+ xmesa->xm_buffer->height+1 );
+ }
+ else {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
+ xmesa->xm_buffer->cleargc,
+ x, xmesa->xm_buffer->height - y - height,
+ width, height );
+ }
+}
+
+
+static void
+clear_back_pixmap( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (all) {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
+ xmesa->xm_buffer->cleargc,
+ 0, 0,
+ xmesa->xm_buffer->width+1,
+ xmesa->xm_buffer->height+1 );
+ }
+ else {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
+ xmesa->xm_buffer->cleargc,
+ x, xmesa->xm_buffer->height - y - height,
+ width, height );
+ }
+}
+
+
+static void
+clear_8bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (all) {
+ size_t n = xmesa->xm_buffer->backimage->bytes_per_line
+ * xmesa->xm_buffer->backimage->height;
+ MEMSET( xmesa->xm_buffer->backimage->data, xmesa->clearpixel, n );
+ }
+ else {
+ GLint i;
+ for (i=0;i<height;i++) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y+i );
+ MEMSET( ptr, xmesa->clearpixel, width );
+ }
+ }
+}
+
+
+static void
+clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (all) {
+ GLint i, c16 = (xmesa->xm_buffer->backimage->bytes_per_line>>4)<<4;
+ GLubyte *ptr = (GLubyte *)xmesa->xm_buffer->backimage->data;
+ for (i=0; i<xmesa->xm_buffer->backimage->height; i++) {
+ GLint j;
+ GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
+ if (i&1) {
+ sptr += 16;
+ }
+ for (j=0; j<c16; j+=16) {
+ ptr[0] = sptr[0];
+ ptr[1] = sptr[1];
+ ptr[2] = sptr[2];
+ ptr[3] = sptr[3];
+ ptr[4] = sptr[4];
+ ptr[5] = sptr[5];
+ ptr[6] = sptr[6];
+ ptr[7] = sptr[7];
+ ptr[8] = sptr[8];
+ ptr[9] = sptr[9];
+ ptr[10] = sptr[10];
+ ptr[11] = sptr[11];
+ ptr[12] = sptr[12];
+ ptr[13] = sptr[13];
+ ptr[14] = sptr[14];
+ ptr[15] = sptr[15];
+ ptr += 16;
+ }
+ for (; j<xmesa->xm_buffer->backimage->bytes_per_line; j++) {
+ *ptr = sptr[j&15];
+ ptr++;
+ }
+ }
+ }
+ else {
+ GLint i;
+ for (i=y; i<y+height; i++) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, i );
+ int j;
+ GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
+ if (i&1) {
+ sptr += 16;
+ }
+ for (j=x; j<x+width; j++) {
+ *ptr = sptr[j&15];
+ ptr++;
+ }
+ }
+ }
+}
+
+
+static void
+clear_16bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ register GLuint pixel = (GLuint) xmesa->clearpixel;
+ if (xmesa->swapbytes) {
+ pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
+ }
+ if (all) {
+ register GLuint n;
+ register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
+ if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
+ /* low and high bytes are equal so use memset() */
+ n = xmesa->xm_buffer->backimage->bytes_per_line
+ * xmesa->xm_buffer->height;
+ MEMSET( ptr4, pixel & 0xff, n );
+ }
+ else {
+ pixel = pixel | (pixel<<16);
+ n = xmesa->xm_buffer->backimage->bytes_per_line
+ * xmesa->xm_buffer->height / 4;
+ do {
+ *ptr4++ = pixel;
+ n--;
+ } while (n!=0);
+
+ if ((xmesa->xm_buffer->backimage->bytes_per_line *
+ xmesa->xm_buffer->height) & 0x2)
+ *(GLushort *)ptr4 = pixel & 0xffff;
+ }
+ }
+ else {
+ register int i, j;
+ for (j=0;j<height;j++) {
+ register GLushort *ptr2 = PIXELADDR2( xmesa->xm_buffer, x, y+j );
+ for (i=0;i<width;i++) {
+ *ptr2++ = pixel;
+ }
+ }
+ }
+}
+
+
+/* Optimized code provided by Nozomi Ytow <[email protected]> */
+static void
+clear_24bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ const GLubyte r = xmesa->clearcolor[0];
+ const GLubyte g = xmesa->clearcolor[1];
+ const GLubyte b = xmesa->clearcolor[2];
+ register GLuint clearPixel;
+ if (xmesa->swapbytes) {
+ clearPixel = (b << 16) | (g << 8) | r;
+ }
+ else {
+ clearPixel = (r << 16) | (g << 8) | b;
+ }
+
+ if (all) {
+ if (r==g && g==b) {
+ /* same value for all three components (gray) */
+ const GLint w3 = xmesa->xm_buffer->width * 3;
+ const GLint h = xmesa->xm_buffer->height;
+ GLint i;
+ for (i = 0; i < h; i++) {
+ bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
+ MEMSET(ptr3, r, w3);
+ }
+ }
+ else {
+ /* the usual case */
+ const GLint w = xmesa->xm_buffer->width;
+ const GLint h = xmesa->xm_buffer->height;
+ GLint i, j;
+ for (i = 0; i < h; i++) {
+ bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
+ for (j = 0; j < w; j++) {
+ ptr3->r = r;
+ ptr3->g = g;
+ ptr3->b = b;
+ ptr3++;
+ }
+ }
+#if 0 /* this code doesn't work for all window widths */
+ register GLuint *ptr4 = (GLuint *) ptr3;
+ register GLuint px;
+ GLuint pixel4[3];
+ register GLuint *p = pixel4;
+ pixel4[0] = clearPixel | (clearPixel << 24);
+ pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
+ pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
+ switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
+ case 0:
+ break;
+ case 1:
+ px = *ptr4 & 0x00ffffff;
+ px |= pixel4[0] & 0xff000000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffff0000;
+ px |= pixel4[2] & 0x0000ffff;
+ *ptr4 = px;
+ if (0 == --n)
+ break;
+ case 2:
+ px = *ptr4 & 0x0000fffff;
+ px |= pixel4[1] & 0xffff0000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffffff00;
+ px |= pixel4[2] & 0x000000ff;
+ *ptr4 = px;
+ if (0 == --n)
+ break;
+ case 3:
+ px = *ptr4 & 0x000000ff;
+ px |= pixel4[2] & 0xffffff00;
+ *ptr4++ = px;
+ --n;
+ break;
+ }
+ while (n > 3) {
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ n -= 4;
+ }
+ switch (n) {
+ case 3:
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffffff00;
+ px |= clearPixel & 0xff;
+ *ptr4 = px;
+ break;
+ case 2:
+ p = pixel4;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffff0000;
+ px |= *p & 0xffff;
+ *ptr4 = px;
+ break;
+ case 1:
+ px = *ptr4 & 0xff000000;
+ px |= *p & 0xffffff;
+ *ptr4 = px;
+ break;
+ case 0:
+ break;
+ }
+#endif
+ }
+ }
+ else {
+ /* only clear subrect of color buffer */
+ if (r==g && g==b) {
+ /* same value for all three components (gray) */
+ GLint j;
+ for (j=0;j<height;j++) {
+ bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
+ MEMSET(ptr3, r, 3 * width);
+ }
+ }
+ else {
+ /* non-gray clear color */
+ GLint i, j;
+ for (j = 0; j < height; j++) {
+ bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
+ for (i = 0; i < width; i++) {
+ ptr3->r = r;
+ ptr3->g = g;
+ ptr3->b = b;
+ ptr3++;
+ }
+ }
+#if 0 /* this code might not always (seems ptr3 always == ptr4) */
+ GLint j;
+ GLuint pixel4[3];
+ pixel4[0] = clearPixel | (clearPixel << 24);
+ pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
+ pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
+ for (j=0;j<height;j++) {
+ bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
+ register GLuint *ptr4 = (GLuint *)ptr3;
+ register GLuint *p, px;
+ GLuint w = width;
+ switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
+ case 0:
+ break;
+ case 1:
+ px = *ptr4 & 0x00ffffff;
+ px |= pixel4[0] & 0xff000000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffff0000;
+ px |= pixel4[2] & 0x0000ffff;
+ *ptr4 = px;
+ if (0 == --w)
+ break;
+ case 2:
+ px = *ptr4 & 0x0000fffff;
+ px |= pixel4[1] & 0xffff0000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffffff00;
+ px |= pixel4[2] & 0x000000ff;
+ *ptr4 = px;
+ if (0 == --w)
+ break;
+ case 3:
+ px = *ptr4 & 0x000000ff;
+ px |= pixel4[2] & 0xffffff00;
+ *ptr4++ = px;
+ --w;
+ break;
+ }
+ while (w > 3){
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ w -= 4;
+ }
+ switch (w) {
+ case 3:
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffffff00;
+ px |= *p & 0xff;
+ *ptr4 = px;
+ break;
+ case 2:
+ p = pixel4;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffff0000;
+ px |= *p & 0xffff;
+ *ptr4 = px;
+ break;
+ case 1:
+ px = *ptr4 & 0xff000000;
+ px |= pixel4[0] & 0xffffff;
+ *ptr4 = px;
+ break;
+ case 0:
+ break;
+ }
+ }
+#endif
+ }
+ }
+}
+
+
+static void
+clear_32bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ if (all) {
+ register GLint n = xmesa->xm_buffer->width * xmesa->xm_buffer->height;
+ register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
+ register GLuint pixel = (GLuint) xmesa->clearpixel;
+ if (xmesa->swapbytes) {
+ pixel = ((pixel >> 24) & 0x000000ff)
+ | ((pixel >> 8) & 0x0000ff00)
+ | ((pixel << 8) & 0x00ff0000)
+ | ((pixel << 24) & 0xff000000);
+ }
+ if (pixel==0) {
+ MEMSET( ptr4, pixel, 4*n );
+ }
+ else {
+ do {
+ *ptr4++ = pixel;
+ n--;
+ } while (n!=0);
+ }
+ }
+ else {
+ register int i, j;
+ register GLuint pixel = (GLuint) xmesa->clearpixel;
+ for (j=0;j<height;j++) {
+ register GLuint *ptr4 = PIXELADDR4( xmesa->xm_buffer, x, y+j );
+ for (i=0;i<width;i++) {
+ *ptr4++ = pixel;
+ }
+ }
+ }
+}
+
+
+static void
+clear_nbit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ if (all) {
+ register int i, j;
+ width = xmesa->xm_buffer->width;
+ height = xmesa->xm_buffer->height;
+ for (j=0;j<height;j++) {
+ for (i=0;i<width;i++) {
+ XMesaPutPixel( img, i, j, xmesa->clearpixel );
+ }
+ }
+ }
+ else {
+ /* TODO: optimize this */
+ register int i, j;
+ y = FLIP(xmesa->xm_buffer, y);
+ for (j=0;j<height;j++) {
+ for (i=0;i<width;i++) {
+ XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
+ }
+ }
+ }
+}
+
+
+
+static GLbitfield
+clear_buffers( GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ /* we can't handle color or index masking */
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ if (*colorMask != 0xffffffff || ctx->Color.IndexMask != 0xffffffff)
+ return mask;
+ }
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ ASSERT(xmesa->xm_buffer->front_clear_func);
+ (*xmesa->xm_buffer->front_clear_func)( ctx, all, x, y, width, height );
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ ASSERT(xmesa->xm_buffer->back_clear_func);
+ (*xmesa->xm_buffer->back_clear_func)( ctx, all, x, y, width, height );
+ }
+ return mask & (~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
+}
+
+
+
+#ifndef XFree86Server
+/*
+ * This function implements glDrawPixels() with an XPutImage call when
+ * drawing to the front buffer (X Window drawable).
+ * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
+ * XXX top/bottom edge clipping is broken!
+ */
+static GLboolean
+drawpixels_8R8G8B( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc1;
+ assert(dpy);
+ assert(buffer);
+ assert(gc);
+
+ /* XXX also check for pixel scale/bias/lookup/zooming! */
+ if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) {
+ int dstX = x;
+ int dstY = y;
+ int w = width;
+ int h = height;
+ int srcX = unpack->SkipPixels;
+ int srcY = unpack->SkipRows;
+ if (_mesa_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
+ XMesaImage ximage;
+ MEMSET(&ximage, 0, sizeof(XMesaImage));
+ ximage.width = width;
+ ximage.height = height;
+ ximage.format = ZPixmap;
+ ximage.data = (char *) pixels + (height - 1) * width * 4;
+ ximage.byte_order = LSBFirst;
+ ximage.bitmap_unit = 32;
+ ximage.bitmap_bit_order = LSBFirst;
+ ximage.bitmap_pad = 32;
+ ximage.depth = 24;
+ ximage.bytes_per_line = -width * 4;
+ ximage.bits_per_pixel = 32;
+ ximage.red_mask = 0xff0000;
+ ximage.green_mask = 0x00ff00;
+ ximage.blue_mask = 0x0000ff;
+ dstY = FLIP(xmesa->xm_buffer,dstY) - height + 1;
+ XPutImage(dpy, buffer, gc, &ximage, srcX, srcY, dstX, dstY, w, h);
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+#endif
+
+
+
+static const GLubyte *
+get_string( GLcontext *ctx, GLenum name )
+{
+ (void) ctx;
+ switch (name) {
+ case GL_RENDERER:
+#ifdef XFree86Server
+ return (const GLubyte *) "Mesa GLX Indirect";
+#else
+ return (const GLubyte *) "Mesa X11";
+#endif
+ case GL_VENDOR:
+#ifdef XFree86Server
+ return (const GLubyte *) "VA Linux Systems, Inc.";
+#else
+ return NULL;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+
+/*
+ * Initialize all the DD.* function pointers depending on the color
+ * buffer configuration. This is mainly called by XMesaMakeCurrent.
+ */
+void
+xmesa_update_state( GLcontext *ctx )
+{
+ XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
+ /*int depth=GET_VISUAL_DEPTH(xmesa->xm_visual);*/
+
+ (void) DitherValues; /* silenced unused var warning */
+#ifndef XFree86Server
+ (void) drawpixels_8R8G8B;
+#endif
+
+ /*
+ * Always the same:
+ */
+ ctx->Driver.GetString = get_string;
+ ctx->Driver.UpdateState = xmesa_update_state;
+ ctx->Driver.GetBufferSize = get_buffer_size;
+ ctx->Driver.Flush = flush;
+ ctx->Driver.Finish = finish;
+
+ ctx->Driver.RenderStart = 0;
+ ctx->Driver.RenderFinish = 0;
+
+ ctx->Driver.SetDrawBuffer = set_draw_buffer;
+ ctx->Driver.SetReadBuffer = set_read_buffer;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear_buffers;
+ ctx->Driver.IndexMask = index_mask;
+ ctx->Driver.ColorMask = color_mask;
+ ctx->Driver.Dither = dither;
+
+ ctx->Driver.PointsFunc = xmesa_get_points_func( ctx );
+ ctx->Driver.LineFunc = xmesa_get_line_func( ctx );
+ ctx->Driver.TriangleFunc = xmesa_get_triangle_func( ctx );
+
+/* ctx->Driver.TriangleCaps = DD_TRI_CULL; */
+
+ /* setup pointers to front and back buffer clear functions */
+ /* XXX this bit of code could be moved to a one-time init */
+ xmesa->xm_buffer->front_clear_func = clear_front_pixmap;
+ if (xmesa->xm_buffer->backpixmap != XIMAGE) {
+ /* back buffer is a pixmap */
+ xmesa->xm_buffer->back_clear_func = clear_back_pixmap;
+ }
+ else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
+ /* Do this on Crays */
+ xmesa->xm_buffer->back_clear_func = clear_nbit_ximage;
+ }
+ else {
+ /* Do this on most machines */
+ switch (xmesa->xm_visual->BitsPerPixel) {
+ case 8:
+ if (xmesa->xm_visual->hpcr_clear_flag) {
+ xmesa->xm_buffer->back_clear_func = clear_HPCR_ximage;
+ }
+ else {
+ xmesa->xm_buffer->back_clear_func = clear_8bit_ximage;
+ }
+ break;
+ case 16:
+ xmesa->xm_buffer->back_clear_func = clear_16bit_ximage;
+ break;
+ case 24:
+ xmesa->xm_buffer->back_clear_func = clear_24bit_ximage;
+ break;
+ case 32:
+ xmesa->xm_buffer->back_clear_func = clear_32bit_ximage;
+ break;
+ default:
+ xmesa->xm_buffer->back_clear_func = clear_nbit_ximage;
+ break;
+ }
+ }
+
+ xmesa_update_span_funcs(ctx);
+}