mesa: replace gl_texture_format with gl_format
[mesa.git] / src / mesa / drivers / x11 / xm_dd.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.2
4 *
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file xm_dd.h
28 * General device driver functions for Xlib driver.
29 */
30
31 #include "glxheader.h"
32 #include "main/bufferobj.h"
33 #include "main/buffers.h"
34 #include "main/context.h"
35 #include "main/colormac.h"
36 #include "main/depth.h"
37 #include "main/drawpix.h"
38 #include "main/extensions.h"
39 #include "main/framebuffer.h"
40 #include "main/macros.h"
41 #include "main/image.h"
42 #include "main/imports.h"
43 #include "main/mtypes.h"
44 #include "main/state.h"
45 #include "main/texobj.h"
46 #include "main/teximage.h"
47 #include "main/texstore.h"
48 #include "main/texformat.h"
49 #include "swrast/swrast.h"
50 #include "swrast/s_context.h"
51 #include "swrast_setup/swrast_setup.h"
52 #include "tnl/tnl.h"
53 #include "tnl/t_context.h"
54 #include "drivers/common/meta.h"
55 #include "xmesaP.h"
56
57
58
59 /*
60 * Dithering kernels and lookup tables.
61 */
62
63 const int xmesa_kernel8[DITH_DY * DITH_DX] = {
64 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC,
65 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC,
66 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC,
67 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC,
68 };
69
70 const short xmesa_HPCR_DRGB[3][2][16] = {
71 {
72 { 16, -4, 1,-11, 14, -6, 3, -9, 15, -5, 2,-10, 13, -7, 4, -8},
73 {-15, 5, 0, 12,-13, 7, -2, 10,-14, 6, -1, 11,-12, 8, -3, 9}
74 },
75 {
76 {-11, 15, -7, 3, -8, 14, -4, 2,-10, 16, -6, 4, -9, 13, -5, 1},
77 { 12,-14, 8, -2, 9,-13, 5, -1, 11,-15, 7, -3, 10,-12, 6, 0}
78 },
79 {
80 { 6,-18, 26,-14, 2,-22, 30,-10, 8,-16, 28,-12, 4,-20, 32, -8},
81 { -4, 20,-24, 16, 0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
82 }
83 };
84
85 const int xmesa_kernel1[16] = {
86 0*47, 9*47, 4*47, 12*47, /* 47 = (255*3)/16 */
87 6*47, 2*47, 14*47, 8*47,
88 10*47, 1*47, 5*47, 11*47,
89 7*47, 13*47, 3*47, 15*47
90 };
91
92
93 static void
94 finish_or_flush( GLcontext *ctx )
95 {
96 #ifdef XFree86Server
97 /* NOT_NEEDED */
98 #else
99 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
100 if (xmesa) {
101 _glthread_LOCK_MUTEX(_xmesa_lock);
102 XSync( xmesa->display, False );
103 _glthread_UNLOCK_MUTEX(_xmesa_lock);
104 }
105 #endif
106 }
107
108
109 static void
110 clear_index( GLcontext *ctx, GLuint index )
111 {
112 if (ctx->DrawBuffer->Name == 0) {
113 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
114 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
115 xmesa->clearpixel = (unsigned long) index;
116 XMesaSetForeground( xmesa->display, xmbuf->cleargc, (unsigned long) index );
117 }
118 }
119
120
121 static void
122 clear_color( GLcontext *ctx, const GLfloat color[4] )
123 {
124 if (ctx->DrawBuffer->Name == 0) {
125 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
126 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
127
128 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
129 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
130 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
131 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
132 xmesa->clearpixel = xmesa_color_to_pixel( ctx,
133 xmesa->clearcolor[0],
134 xmesa->clearcolor[1],
135 xmesa->clearcolor[2],
136 xmesa->clearcolor[3],
137 xmesa->xm_visual->undithered_pf );
138 _glthread_LOCK_MUTEX(_xmesa_lock);
139 XMesaSetForeground( xmesa->display, xmbuf->cleargc,
140 xmesa->clearpixel );
141 _glthread_UNLOCK_MUTEX(_xmesa_lock);
142 }
143 }
144
145
146
147 /* Set index mask ala glIndexMask */
148 static void
149 index_mask( GLcontext *ctx, GLuint mask )
150 {
151 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
152 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
153 /* not sure this conditional is really needed */
154 if (xmbuf->backxrb && xmbuf->backxrb->pixmap) {
155 unsigned long m;
156 if (mask==0xffffffff) {
157 m = ((unsigned long)~0L);
158 }
159 else {
160 m = (unsigned long) mask;
161 }
162 XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
163 }
164 }
165
166
167 /* Implements glColorMask() */
168 static void
169 color_mask(GLcontext *ctx,
170 GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
171 {
172 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
173 XMesaBuffer xmbuf;
174 const int xclass = xmesa->xm_visual->mesa_visual.visualType;
175 (void) amask;
176
177 if (ctx->DrawBuffer->Name != 0)
178 return;
179
180 xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
181
182 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
183 unsigned long m;
184 if (rmask && gmask && bmask) {
185 m = ((unsigned long)~0L);
186 }
187 else {
188 m = 0;
189 if (rmask) m |= GET_REDMASK(xmesa->xm_visual);
190 if (gmask) m |= GET_GREENMASK(xmesa->xm_visual);
191 if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual);
192 }
193 XMesaSetPlaneMask( xmesa->display, xmbuf->cleargc, m );
194 }
195 }
196
197
198
199 /**********************************************************************/
200 /*** glClear implementations ***/
201 /**********************************************************************/
202
203
204 /**
205 * Clear the front or back color buffer, if it's implemented with a pixmap.
206 */
207 static void
208 clear_pixmap(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
209 GLint x, GLint y, GLint width, GLint height)
210 {
211 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
212 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
213
214 assert(xmbuf);
215 assert(xrb->pixmap);
216 assert(xmesa);
217 assert(xmesa->display);
218 assert(xrb->pixmap);
219 assert(xmbuf->cleargc);
220
221 XMesaFillRectangle( xmesa->display, xrb->pixmap, xmbuf->cleargc,
222 x, xrb->Base.Height - y - height,
223 width, height );
224 }
225
226
227 static void
228 clear_8bit_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
229 GLint x, GLint y, GLint width, GLint height )
230 {
231 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
232 GLint i;
233 for (i = 0; i < height; i++) {
234 GLubyte *ptr = PIXEL_ADDR1(xrb, x, y + i);
235 MEMSET( ptr, xmesa->clearpixel, width );
236 }
237 }
238
239
240 static void
241 clear_HPCR_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
242 GLint x, GLint y, GLint width, GLint height )
243 {
244 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
245 GLint i;
246 for (i = y; i < y + height; i++) {
247 GLubyte *ptr = PIXEL_ADDR1( xrb, x, i );
248 int j;
249 const GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
250 if (i & 1) {
251 sptr += 16;
252 }
253 for (j = x; j < x + width; j++) {
254 *ptr = sptr[j&15];
255 ptr++;
256 }
257 }
258 }
259
260
261 static void
262 clear_16bit_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
263 GLint x, GLint y, GLint width, GLint height)
264 {
265 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
266 GLuint pixel = (GLuint) xmesa->clearpixel;
267 GLint i, j;
268
269 if (xmesa->swapbytes) {
270 pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
271 }
272
273 for (j = 0; j < height; j++) {
274 GLushort *ptr2 = PIXEL_ADDR2(xrb, x, y + j);
275 for (i = 0; i < width; i++) {
276 ptr2[i] = pixel;
277 }
278 }
279 }
280
281
282 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
283 static void
284 clear_24bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
285 GLint x, GLint y, GLint width, GLint height)
286 {
287 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
288 const GLubyte r = xmesa->clearcolor[0];
289 const GLubyte g = xmesa->clearcolor[1];
290 const GLubyte b = xmesa->clearcolor[2];
291
292 if (r == g && g == b) {
293 /* same value for all three components (gray) */
294 GLint j;
295 for (j = 0; j < height; j++) {
296 bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
297 MEMSET(ptr3, r, 3 * width);
298 }
299 }
300 else {
301 /* non-gray clear color */
302 GLint i, j;
303 for (j = 0; j < height; j++) {
304 bgr_t *ptr3 = PIXEL_ADDR3(xrb, x, y + j);
305 for (i = 0; i < width; i++) {
306 ptr3->r = r;
307 ptr3->g = g;
308 ptr3->b = b;
309 ptr3++;
310 }
311 }
312 }
313 }
314
315
316 static void
317 clear_32bit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
318 GLint x, GLint y, GLint width, GLint height)
319 {
320 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
321 register GLuint pixel = (GLuint) xmesa->clearpixel;
322
323 if (!xrb->ximage)
324 return;
325
326 if (xmesa->swapbytes) {
327 pixel = ((pixel >> 24) & 0x000000ff)
328 | ((pixel >> 8) & 0x0000ff00)
329 | ((pixel << 8) & 0x00ff0000)
330 | ((pixel << 24) & 0xff000000);
331 }
332
333 if (width == xrb->Base.Width && height == xrb->Base.Height) {
334 /* clearing whole buffer */
335 const GLuint n = xrb->Base.Width * xrb->Base.Height;
336 GLuint *ptr4 = (GLuint *) xrb->ximage->data;
337 if (pixel == 0) {
338 /* common case */
339 _mesa_memset(ptr4, pixel, 4 * n);
340 }
341 else {
342 GLuint i;
343 for (i = 0; i < n; i++)
344 ptr4[i] = pixel;
345 }
346 }
347 else {
348 /* clearing scissored region */
349 GLint i, j;
350 for (j = 0; j < height; j++) {
351 GLuint *ptr4 = PIXEL_ADDR4(xrb, x, y + j);
352 for (i = 0; i < width; i++) {
353 ptr4[i] = pixel;
354 }
355 }
356 }
357 }
358
359
360 static void
361 clear_nbit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
362 GLint x, GLint y, GLint width, GLint height)
363 {
364 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
365 XMesaImage *img = xrb->ximage;
366 GLint i, j;
367
368 /* TODO: optimize this */
369 y = YFLIP(xrb, y);
370 for (j = 0; j < height; j++) {
371 for (i = 0; i < width; i++) {
372 XMesaPutPixel(img, x+i, y-j, xmesa->clearpixel);
373 }
374 }
375 }
376
377
378
379 static void
380 clear_buffers(GLcontext *ctx, GLbitfield buffers)
381 {
382 if (ctx->DrawBuffer->Name == 0) {
383 /* this is a window system framebuffer */
384 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
385 XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
386 const GLint x = ctx->DrawBuffer->_Xmin;
387 const GLint y = ctx->DrawBuffer->_Ymin;
388 const GLint width = ctx->DrawBuffer->_Xmax - x;
389 const GLint height = ctx->DrawBuffer->_Ymax - y;
390
391 /* we can't handle color or index masking */
392 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
393 if (buffers & BUFFER_BIT_FRONT_LEFT) {
394 /* clear front color buffer */
395 struct gl_renderbuffer *frontRb
396 = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
397 if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
398 /* renderbuffer is not wrapped - great! */
399 b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
400 buffers &= ~BUFFER_BIT_FRONT_LEFT;
401 }
402 else {
403 /* we can't directly clear an alpha-wrapped color buffer */
404 }
405 }
406 if (buffers & BUFFER_BIT_BACK_LEFT) {
407 /* clear back color buffer */
408 struct gl_renderbuffer *backRb
409 = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
410 if (b->backxrb == xmesa_renderbuffer(backRb)) {
411 /* renderbuffer is not wrapped - great! */
412 b->backxrb->clearFunc(ctx, b->backxrb, x, y, width, height);
413 buffers &= ~BUFFER_BIT_BACK_LEFT;
414 }
415 }
416 }
417 }
418 if (buffers)
419 _swrast_Clear(ctx, buffers);
420 }
421
422
423 #ifndef XFree86Server
424 /* XXX these functions haven't been tested in the Xserver environment */
425
426
427 /**
428 * Check if we can do an optimized glDrawPixels into an 8R8G8B visual.
429 */
430 static GLboolean
431 can_do_DrawPixels_8R8G8B(GLcontext *ctx, GLenum format, GLenum type)
432 {
433 if (format == GL_BGRA &&
434 type == GL_UNSIGNED_BYTE &&
435 ctx->DrawBuffer &&
436 ctx->DrawBuffer->Name == 0 &&
437 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
438 ctx->Pixel.ZoomY == 1.0 &&
439 ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
440 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
441
442 if (swrast->NewState)
443 _swrast_validate_derived( ctx );
444
445 if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
446 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
447 if (rb) {
448 struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb->Wrapped);
449 if (xrb &&
450 xrb->pixmap && /* drawing to pixmap or window */
451 xrb->Base.AlphaBits == 0) {
452 return GL_TRUE;
453 }
454 }
455 }
456 }
457 return GL_FALSE;
458 }
459
460
461 /**
462 * This function implements glDrawPixels() with an XPutImage call when
463 * drawing to the front buffer (X Window drawable).
464 * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
465 */
466 static void
467 xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
468 GLint x, GLint y, GLsizei width, GLsizei height,
469 GLenum format, GLenum type,
470 const struct gl_pixelstore_attrib *unpack,
471 const GLvoid *pixels )
472 {
473 if (can_do_DrawPixels_8R8G8B(ctx, format, type)) {
474 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
475 struct gl_pixelstore_attrib clippedUnpack = *unpack;
476 int dstX = x;
477 int dstY = y;
478 int w = width;
479 int h = height;
480
481 if (swrast->NewState)
482 _swrast_validate_derived( ctx );
483
484 if (unpack->BufferObj->Name) {
485 /* unpack from PBO */
486 GLubyte *buf;
487 if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
488 format, type, pixels)) {
489 _mesa_error(ctx, GL_INVALID_OPERATION,
490 "glDrawPixels(invalid PBO access)");
491 return;
492 }
493 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
494 GL_PIXEL_UNPACK_BUFFER_EXT,
495 GL_READ_ONLY_ARB,
496 unpack->BufferObj);
497 if (!buf) {
498 /* buffer is already mapped - that's an error */
499 _mesa_error(ctx, GL_INVALID_OPERATION,
500 "glDrawPixels(PBO is mapped)");
501 return;
502 }
503 pixels = ADD_POINTERS(buf, pixels);
504 }
505
506 if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
507 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
508 XMesaDisplay *dpy = xmesa->xm_visual->display;
509 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
510 const XMesaGC gc = xmbuf->cleargc; /* effected by glColorMask */
511 struct xmesa_renderbuffer *xrb
512 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
513 const int srcX = clippedUnpack.SkipPixels;
514 const int srcY = clippedUnpack.SkipRows;
515 const int rowLength = clippedUnpack.RowLength;
516 XMesaImage ximage;
517
518 ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
519 ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
520 ASSERT(dpy);
521 ASSERT(gc);
522
523 /* This is a little tricky since all coordinates up to now have
524 * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
525 * so we have to carefully compute the Y coordinates/addresses here.
526 */
527 MEMSET(&ximage, 0, sizeof(XMesaImage));
528 ximage.width = width;
529 ximage.height = height;
530 ximage.format = ZPixmap;
531 ximage.data = (char *) pixels
532 + ((srcY + h - 1) * rowLength + srcX) * 4;
533 ximage.byte_order = LSBFirst;
534 ximage.bitmap_unit = 32;
535 ximage.bitmap_bit_order = LSBFirst;
536 ximage.bitmap_pad = 32;
537 ximage.depth = 32;
538 ximage.bits_per_pixel = 32;
539 ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
540 /* it seems we don't need to set the ximage.red/green/blue_mask fields */
541 /* flip Y axis for dest position */
542 dstY = YFLIP(xrb, dstY) - h + 1;
543 XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
544 }
545
546 if (unpack->BufferObj->Name) {
547 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
548 unpack->BufferObj);
549 }
550 }
551 else {
552 /* software fallback */
553 _swrast_DrawPixels(ctx, x, y, width, height,
554 format, type, unpack, pixels);
555 }
556 }
557
558
559
560 /**
561 * Check if we can do an optimized glDrawPixels into an 5R6G5B visual.
562 */
563 static GLboolean
564 can_do_DrawPixels_5R6G5B(GLcontext *ctx, GLenum format, GLenum type)
565 {
566 if (format == GL_RGB &&
567 type == GL_UNSIGNED_SHORT_5_6_5 &&
568 !ctx->Color.DitherFlag && /* no dithering */
569 ctx->DrawBuffer &&
570 ctx->DrawBuffer->Name == 0 &&
571 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
572 ctx->Pixel.ZoomY == 1.0 &&
573 ctx->_ImageTransferState == 0 /* no color tables, scale/bias, etc */) {
574 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
575
576 if (swrast->NewState)
577 _swrast_validate_derived( ctx );
578
579 if ((swrast->_RasterMask & ~CLIP_BIT) == 0) /* no blend, z-test, etc */ {
580 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
581 if (rb) {
582 struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb->Wrapped);
583 if (xrb &&
584 xrb->pixmap && /* drawing to pixmap or window */
585 xrb->Base.AlphaBits == 0) {
586 return GL_TRUE;
587 }
588 }
589 }
590 }
591 return GL_FALSE;
592 }
593
594
595 /**
596 * This function implements glDrawPixels() with an XPutImage call when
597 * drawing to the front buffer (X Window drawable). The image format
598 * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
599 * match the PF_5R6G5B pixel format.
600 */
601 static void
602 xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
603 GLint x, GLint y, GLsizei width, GLsizei height,
604 GLenum format, GLenum type,
605 const struct gl_pixelstore_attrib *unpack,
606 const GLvoid *pixels )
607 {
608 if (can_do_DrawPixels_5R6G5B(ctx, format, type)) {
609 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
610 struct gl_pixelstore_attrib clippedUnpack = *unpack;
611 int dstX = x;
612 int dstY = y;
613 int w = width;
614 int h = height;
615
616 if (swrast->NewState)
617 _swrast_validate_derived( ctx );
618
619 if (unpack->BufferObj->Name) {
620 /* unpack from PBO */
621 GLubyte *buf;
622 if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
623 format, type, pixels)) {
624 _mesa_error(ctx, GL_INVALID_OPERATION,
625 "glDrawPixels(invalid PBO access)");
626 return;
627 }
628 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx,
629 GL_PIXEL_UNPACK_BUFFER_EXT,
630 GL_READ_ONLY_ARB,
631 unpack->BufferObj);
632 if (!buf) {
633 /* buffer is already mapped - that's an error */
634 _mesa_error(ctx, GL_INVALID_OPERATION,
635 "glDrawPixels(PBO is mapped)");
636 return;
637 }
638 pixels = ADD_POINTERS(buf, pixels);
639 }
640
641 if (_mesa_clip_drawpixels(ctx, &dstX, &dstY, &w, &h, &clippedUnpack)) {
642 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
643 XMesaDisplay *dpy = xmesa->xm_visual->display;
644 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
645 const XMesaGC gc = xmbuf->cleargc; /* effected by glColorMask */
646 struct xmesa_renderbuffer *xrb
647 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
648 const int srcX = clippedUnpack.SkipPixels;
649 const int srcY = clippedUnpack.SkipRows;
650 const int rowLength = clippedUnpack.RowLength;
651 XMesaImage ximage;
652
653 ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
654 ASSERT(dpy);
655 ASSERT(gc);
656
657 /* This is a little tricky since all coordinates up to now have
658 * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
659 * so we have to carefully compute the Y coordinates/addresses here.
660 */
661 MEMSET(&ximage, 0, sizeof(XMesaImage));
662 ximage.width = width;
663 ximage.height = height;
664 ximage.format = ZPixmap;
665 ximage.data = (char *) pixels
666 + ((srcY + h - 1) * rowLength + srcX) * 2;
667 ximage.byte_order = LSBFirst;
668 ximage.bitmap_unit = 16;
669 ximage.bitmap_bit_order = LSBFirst;
670 ximage.bitmap_pad = 16;
671 ximage.depth = 16;
672 ximage.bits_per_pixel = 16;
673 ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
674 /* it seems we don't need to set the ximage.red/green/blue_mask fields */
675 /* flip Y axis for dest position */
676 dstY = YFLIP(xrb, dstY) - h + 1;
677 XPutImage(dpy, xrb->pixmap, gc, &ximage, 0, 0, dstX, dstY, w, h);
678 }
679
680 if (unpack->BufferObj->Name) {
681 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
682 unpack->BufferObj);
683 }
684 }
685 else {
686 /* software fallback */
687 _swrast_DrawPixels(ctx, x, y, width, height,
688 format, type, unpack, pixels);
689 }
690 }
691
692
693 /**
694 * Determine if we can do an optimized glCopyPixels.
695 */
696 static GLboolean
697 can_do_CopyPixels(GLcontext *ctx, GLenum type)
698 {
699 if (type == GL_COLOR &&
700 ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
701 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
702 ctx->Pixel.ZoomY == 1.0 &&
703 ctx->Color.DrawBuffer[0] == GL_FRONT && /* copy to front buf */
704 ctx->Pixel.ReadBuffer == GL_FRONT && /* copy from front buf */
705 ctx->ReadBuffer->_ColorReadBuffer &&
706 ctx->DrawBuffer->_ColorDrawBuffers[0]) {
707 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
708
709 if (swrast->NewState)
710 _swrast_validate_derived( ctx );
711
712 if ((swrast->_RasterMask & ~CLIP_BIT) == 0x0 &&
713 ctx->ReadBuffer &&
714 ctx->ReadBuffer->_ColorReadBuffer &&
715 ctx->DrawBuffer &&
716 ctx->DrawBuffer->_ColorDrawBuffers[0]) {
717 struct xmesa_renderbuffer *srcXrb
718 = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
719 struct xmesa_renderbuffer *dstXrb
720 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
721 if (srcXrb->pixmap && dstXrb->pixmap) {
722 return GL_TRUE;
723 }
724 }
725 }
726 return GL_FALSE;
727 }
728
729
730 /**
731 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
732 * for the color buffer. Don't support zooming, pixel transfer, etc.
733 * We do support copying from one window to another, ala glXMakeCurrentRead.
734 */
735 static void
736 xmesa_CopyPixels( GLcontext *ctx,
737 GLint srcx, GLint srcy, GLsizei width, GLsizei height,
738 GLint destx, GLint desty, GLenum type )
739 {
740 if (can_do_CopyPixels(ctx, type)) {
741 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
742 XMesaDisplay *dpy = xmesa->xm_visual->display;
743 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
744 const XMesaGC gc = xmbuf->cleargc; /* effected by glColorMask */
745 struct xmesa_renderbuffer *srcXrb
746 = xmesa_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer->Wrapped);
747 struct xmesa_renderbuffer *dstXrb
748 = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]->Wrapped);
749
750 ASSERT(dpy);
751 ASSERT(gc);
752
753 /* Note: we don't do any special clipping work here. We could,
754 * but X will do it for us.
755 */
756 srcy = YFLIP(srcXrb, srcy) - height + 1;
757 desty = YFLIP(dstXrb, desty) - height + 1;
758 XCopyArea(dpy, srcXrb->pixmap, dstXrb->pixmap, gc,
759 srcx, srcy, width, height, destx, desty);
760 }
761 else {
762 _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
763 }
764 }
765
766 #endif /* XFree86Server */
767
768
769
770 /*
771 * Every driver should implement a GetString function in order to
772 * return a meaningful GL_RENDERER string.
773 */
774 static const GLubyte *
775 get_string( GLcontext *ctx, GLenum name )
776 {
777 (void) ctx;
778 switch (name) {
779 case GL_RENDERER:
780 #ifdef XFree86Server
781 return (const GLubyte *) "Mesa GLX Indirect";
782 #else
783 return (const GLubyte *) "Mesa X11";
784 #endif
785 case GL_VENDOR:
786 #ifdef XFree86Server
787 return (const GLubyte *) "Mesa project: www.mesa3d.org";
788 #else
789 return NULL;
790 #endif
791 default:
792 return NULL;
793 }
794 }
795
796
797 /*
798 * We implement the glEnable function only because we care about
799 * dither enable/disable.
800 */
801 static void
802 enable( GLcontext *ctx, GLenum pname, GLboolean state )
803 {
804 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
805
806 switch (pname) {
807 case GL_DITHER:
808 if (state)
809 xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
810 else
811 xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
812 break;
813 default:
814 ; /* silence compiler warning */
815 }
816 }
817
818
819 static void
820 clear_color_HPCR_ximage( GLcontext *ctx, const GLfloat color[4] )
821 {
822 int i;
823 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
824
825 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
826 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
827 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
828 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
829
830 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
831 /* black is black */
832 MEMSET( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 ,
833 sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern));
834 }
835 else {
836 /* build clear pattern */
837 for (i=0; i<16; i++) {
838 xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] =
839 DITHER_HPCR(i, 0,
840 xmesa->clearcolor[0],
841 xmesa->clearcolor[1],
842 xmesa->clearcolor[2]);
843 xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i] =
844 DITHER_HPCR(i, 1,
845 xmesa->clearcolor[0],
846 xmesa->clearcolor[1],
847 xmesa->clearcolor[2]);
848 }
849 }
850 }
851
852
853 static void
854 clear_color_HPCR_pixmap( GLcontext *ctx, const GLfloat color[4] )
855 {
856 int i;
857 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
858
859 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
860 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
861 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
862 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
863
864 if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
865 /* black is black */
866 for (i=0; i<16; i++) {
867 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, 0);
868 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, 0);
869 }
870 }
871 else {
872 for (i=0; i<16; i++) {
873 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0,
874 DITHER_HPCR(i, 0,
875 xmesa->clearcolor[0],
876 xmesa->clearcolor[1],
877 xmesa->clearcolor[2]));
878 XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1,
879 DITHER_HPCR(i, 1,
880 xmesa->clearcolor[0],
881 xmesa->clearcolor[1],
882 xmesa->clearcolor[2]));
883 }
884 }
885 /* change tile pixmap content */
886 XMesaPutImage(xmesa->display,
887 (XMesaDrawable)xmesa->xm_visual->hpcr_clear_pixmap,
888 XMESA_BUFFER(ctx->DrawBuffer)->cleargc,
889 xmesa->xm_visual->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
890 }
891
892
893 /**
894 * Called when the driver should update its state, based on the new_state
895 * flags.
896 */
897 void
898 xmesa_update_state( GLcontext *ctx, GLbitfield new_state )
899 {
900 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
901
902 /* Propagate statechange information to swrast and swrast_setup
903 * modules. The X11 driver has no internal GL-dependent state.
904 */
905 _swrast_InvalidateState( ctx, new_state );
906 _tnl_InvalidateState( ctx, new_state );
907 _vbo_InvalidateState( ctx, new_state );
908 _swsetup_InvalidateState( ctx, new_state );
909
910 if (ctx->DrawBuffer->Name != 0)
911 return;
912
913 /*
914 * GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
915 * renderbuffer span/clear funcs.
916 * Check _NEW_COLOR to detect dither enable/disable.
917 */
918 if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
919 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
920 struct xmesa_renderbuffer *front_xrb, *back_xrb;
921
922 front_xrb = xmbuf->frontxrb;
923 if (front_xrb) {
924 xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat,
925 xmesa->xm_visual->BitsPerPixel);
926 front_xrb->clearFunc = clear_pixmap;
927 }
928
929 back_xrb = xmbuf->backxrb;
930 if (back_xrb) {
931 xmesa_set_renderbuffer_funcs(back_xrb, xmesa->pixelformat,
932 xmesa->xm_visual->BitsPerPixel);
933 if (xmbuf->backxrb->pixmap) {
934 back_xrb->clearFunc = clear_pixmap;
935 }
936 else {
937 switch (xmesa->xm_visual->BitsPerPixel) {
938 case 8:
939 if (xmesa->xm_visual->hpcr_clear_flag) {
940 back_xrb->clearFunc = clear_HPCR_ximage;
941 }
942 else {
943 back_xrb->clearFunc = clear_8bit_ximage;
944 }
945 break;
946 case 16:
947 back_xrb->clearFunc = clear_16bit_ximage;
948 break;
949 case 24:
950 back_xrb->clearFunc = clear_24bit_ximage;
951 break;
952 case 32:
953 back_xrb->clearFunc = clear_32bit_ximage;
954 break;
955 default:
956 back_xrb->clearFunc = clear_nbit_ximage;
957 break;
958 }
959 }
960 }
961 }
962
963 if (xmesa->xm_visual->hpcr_clear_flag) {
964 /* this depends on whether we're drawing to the front or back buffer */
965 /* XXX FIX THIS! */
966 #if 0
967 if (pixmap) {
968 ctx->Driver.ClearColor = clear_color_HPCR_pixmap;
969 }
970 else {
971 ctx->Driver.ClearColor = clear_color_HPCR_ximage;
972 }
973 #else
974 (void) clear_color_HPCR_pixmap;
975 (void) clear_color_HPCR_ximage;
976 #endif
977 }
978 }
979
980
981
982 /**
983 * Called via ctx->Driver.TestProxyTeximage(). Normally, we'd just use
984 * the _mesa_test_proxy_teximage() fallback function, but we're going to
985 * special-case the 3D texture case to allow textures up to 512x512x32
986 * texels.
987 */
988 static GLboolean
989 test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
990 GLint internalFormat, GLenum format, GLenum type,
991 GLint width, GLint height, GLint depth, GLint border)
992 {
993 if (target == GL_PROXY_TEXTURE_3D) {
994 /* special case for 3D textures */
995 if (width * height * depth > 512 * 512 * 64 ||
996 width < 2 * border ||
997 (!ctx->Extensions.ARB_texture_non_power_of_two &&
998 _mesa_bitcount(width - 2 * border) != 1) ||
999 height < 2 * border ||
1000 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1001 _mesa_bitcount(height - 2 * border) != 1) ||
1002 depth < 2 * border ||
1003 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1004 _mesa_bitcount(depth - 2 * border) != 1)) {
1005 /* Bad size, or too many texels */
1006 return GL_FALSE;
1007 }
1008 return GL_TRUE;
1009 }
1010 else {
1011 /* use the fallback routine for 1D, 2D, cube and rect targets */
1012 return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
1013 format, type, width, height, depth,
1014 border);
1015 }
1016 }
1017
1018
1019 /**
1020 * In SW, we don't really compress GL_COMPRESSED_RGB[A] textures!
1021 */
1022 static gl_format
1023 choose_tex_format( GLcontext *ctx, GLint internalFormat,
1024 GLenum format, GLenum type )
1025 {
1026 switch (internalFormat) {
1027 case GL_COMPRESSED_RGB_ARB:
1028 return MESA_FORMAT_RGB;
1029 case GL_COMPRESSED_RGBA_ARB:
1030 return MESA_FORMAT_RGBA;
1031 default:
1032 return _mesa_choose_tex_format(ctx, internalFormat, format, type);
1033 }
1034 }
1035
1036
1037 /**
1038 * Called by glViewport.
1039 * This is a good time for us to poll the current X window size and adjust
1040 * our renderbuffers to match the current window size.
1041 * Remember, we have no opportunity to respond to conventional
1042 * X Resize/StructureNotify events since the X driver has no event loop.
1043 * Thus, we poll.
1044 * Note that this trick isn't fool-proof. If the application never calls
1045 * glViewport, our notion of the current window size may be incorrect.
1046 * That problem led to the GLX_MESA_resize_buffers extension.
1047 */
1048 static void
1049 xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
1050 {
1051 XMesaContext xmctx = XMESA_CONTEXT(ctx);
1052 XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
1053 XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
1054 xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
1055 xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
1056 (void) x;
1057 (void) y;
1058 (void) w;
1059 (void) h;
1060 }
1061
1062
1063 #if ENABLE_EXT_timer_query
1064
1065 /*
1066 * The GL_EXT_timer_query extension is not enabled for the XServer
1067 * indirect renderer. Not sure about how/if wrapping of gettimeofday()
1068 * is done, etc.
1069 */
1070
1071 struct xmesa_query_object
1072 {
1073 struct gl_query_object Base;
1074 struct timeval StartTime;
1075 };
1076
1077
1078 static struct gl_query_object *
1079 xmesa_new_query_object(GLcontext *ctx, GLuint id)
1080 {
1081 struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
1082 if (q) {
1083 q->Base.Id = id;
1084 q->Base.Ready = GL_TRUE;
1085 }
1086 return &q->Base;
1087 }
1088
1089
1090 static void
1091 xmesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
1092 {
1093 if (q->Target == GL_TIME_ELAPSED_EXT) {
1094 struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
1095 (void) gettimeofday(&xq->StartTime, NULL);
1096 }
1097 }
1098
1099
1100 /**
1101 * Return the difference between the two given times in microseconds.
1102 */
1103 #ifdef __VMS
1104 #define suseconds_t unsigned int
1105 #endif
1106 static GLuint64EXT
1107 time_diff(const struct timeval *t0, const struct timeval *t1)
1108 {
1109 GLuint64EXT seconds0 = t0->tv_sec & 0xff; /* 0 .. 255 seconds */
1110 GLuint64EXT seconds1 = t1->tv_sec & 0xff; /* 0 .. 255 seconds */
1111 GLuint64EXT nanosec0 = (seconds0 * 1000000 + t0->tv_usec) * 1000;
1112 GLuint64EXT nanosec1 = (seconds1 * 1000000 + t1->tv_usec) * 1000;
1113 return nanosec1 - nanosec0;
1114 }
1115
1116
1117 static void
1118 xmesa_end_query(GLcontext *ctx, struct gl_query_object *q)
1119 {
1120 if (q->Target == GL_TIME_ELAPSED_EXT) {
1121 struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
1122 struct timeval endTime;
1123 (void) gettimeofday(&endTime, NULL);
1124 /* result is in nanoseconds! */
1125 q->Result = time_diff(&xq->StartTime, &endTime);
1126 }
1127 q->Ready = GL_TRUE;
1128 }
1129
1130 #endif /* ENABLE_timer_query */
1131
1132
1133 /**
1134 * Initialize the device driver function table with the functions
1135 * we implement in this driver.
1136 */
1137 void
1138 xmesa_init_driver_functions( XMesaVisual xmvisual,
1139 struct dd_function_table *driver )
1140 {
1141 driver->GetString = get_string;
1142 driver->UpdateState = xmesa_update_state;
1143 driver->GetBufferSize = NULL; /* OBSOLETE */
1144 driver->Flush = finish_or_flush;
1145 driver->Finish = finish_or_flush;
1146 driver->ClearIndex = clear_index;
1147 driver->ClearColor = clear_color;
1148 driver->IndexMask = index_mask;
1149 driver->ColorMask = color_mask;
1150 driver->Enable = enable;
1151 driver->Viewport = xmesa_viewport;
1152 if (TEST_META_FUNCS) {
1153 driver->Clear = _mesa_meta_Clear;
1154 driver->CopyPixels = _mesa_meta_CopyPixels;
1155 driver->BlitFramebuffer = _mesa_meta_BlitFramebuffer;
1156 driver->DrawPixels = _mesa_meta_DrawPixels;
1157 driver->Bitmap = _mesa_meta_Bitmap;
1158 }
1159 else {
1160 driver->Clear = clear_buffers;
1161 #ifndef XFree86Server
1162 driver->CopyPixels = xmesa_CopyPixels;
1163 if (xmvisual->undithered_pf == PF_8R8G8B &&
1164 xmvisual->dithered_pf == PF_8R8G8B &&
1165 xmvisual->BitsPerPixel == 32) {
1166 driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
1167 }
1168 else if (xmvisual->undithered_pf == PF_5R6G5B) {
1169 driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
1170 }
1171 #endif
1172 }
1173 driver->TestProxyTexImage = test_proxy_teximage;
1174 #if ENABLE_EXT_texure_compression_s3tc
1175 driver->ChooseTextureFormat = choose_tex_format;
1176 #else
1177 (void) choose_tex_format;
1178 #endif
1179
1180 #if ENABLE_EXT_timer_query
1181 driver->NewQueryObject = xmesa_new_query_object;
1182 driver->BeginQuery = xmesa_begin_query;
1183 driver->EndQuery = xmesa_end_query;
1184 #endif
1185 }
1186
1187
1188 #define XMESA_NEW_POINT (_NEW_POINT | \
1189 _NEW_RENDERMODE | \
1190 _SWRAST_NEW_RASTERMASK)
1191
1192 #define XMESA_NEW_LINE (_NEW_LINE | \
1193 _NEW_TEXTURE | \
1194 _NEW_LIGHT | \
1195 _NEW_DEPTH | \
1196 _NEW_RENDERMODE | \
1197 _SWRAST_NEW_RASTERMASK)
1198
1199 #define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1200 _NEW_TEXTURE | \
1201 _NEW_LIGHT | \
1202 _NEW_DEPTH | \
1203 _NEW_RENDERMODE | \
1204 _SWRAST_NEW_RASTERMASK)
1205
1206
1207 /**
1208 * Extend the software rasterizer with our line/point/triangle
1209 * functions.
1210 * Called during context creation only.
1211 */
1212 void xmesa_register_swrast_functions( GLcontext *ctx )
1213 {
1214 SWcontext *swrast = SWRAST_CONTEXT( ctx );
1215
1216 swrast->choose_point = xmesa_choose_point;
1217 swrast->choose_line = xmesa_choose_line;
1218 swrast->choose_triangle = xmesa_choose_triangle;
1219
1220 /* XXX these lines have no net effect. Remove??? */
1221 swrast->InvalidatePointMask |= XMESA_NEW_POINT;
1222 swrast->InvalidateLineMask |= XMESA_NEW_LINE;
1223 swrast->InvalidateTriangleMask |= XMESA_NEW_TRIANGLE;
1224 }