0d29481e321dd54d3c7f37ac13d4aa2144232040
[mesa.git] / src / mesa / drivers / x11 / xm_dd.c
1 /* $Id: xm_dd.c,v 1.42 2003/01/16 19:10:46 alanh Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.0.3
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26 /* $XFree86: xc/extras/Mesa/src/X/xm_dd.c,v 1.2 2002/02/26 23:37:31 tsi Exp $ */
27
28 #include "glxheader.h"
29 #include "context.h"
30 #include "colormac.h"
31 #include "depth.h"
32 #include "drawpix.h"
33 #include "extensions.h"
34 #include "macros.h"
35 #include "imports.h"
36 #include "mtypes.h"
37 #include "state.h"
38 #include "texstore.h"
39 #include "texformat.h"
40 #include "xmesaP.h"
41 #include "array_cache/acache.h"
42 #include "swrast/s_context.h"
43 #include "swrast/swrast.h"
44 #include "swrast/s_alphabuf.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/tnl.h"
47 #include "tnl/t_context.h"
48 #include "tnl/t_pipeline.h"
49
50
51 /*
52 * Return the size (width, height) of the X window for the given GLframebuffer.
53 * Output: width - width of buffer in pixels.
54 * height - height of buffer in pixels.
55 */
56 static void
57 get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
58 {
59 /* We can do this cast because the first field in the XMesaBuffer
60 * struct is a GLframebuffer struct. If this weren't true, we'd
61 * need a pointer from the GLframebuffer to the XMesaBuffer.
62 */
63 const XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
64 unsigned int winwidth, winheight;
65 #ifdef XFree86Server
66 /* XFree86 GLX renderer */
67 if (xmBuffer->frontbuffer->width > MAX_WIDTH ||
68 xmBuffer->frontbuffer->height > MAX_HEIGHT) {
69 winwidth = buffer->Width;
70 winheight = buffer->Height;
71 } else {
72 winwidth = xmBuffer->frontbuffer->width;
73 winheight = xmBuffer->frontbuffer->height;
74 }
75 #else
76 Window root;
77 int winx, winy;
78 unsigned int bw, d;
79
80 _glthread_LOCK_MUTEX(_xmesa_lock);
81 XSync(xmBuffer->xm_visual->display, 0); /* added for Chromium */
82 XGetGeometry( xmBuffer->xm_visual->display, xmBuffer->frontbuffer, &root,
83 &winx, &winy, &winwidth, &winheight, &bw, &d );
84 _glthread_UNLOCK_MUTEX(_xmesa_lock);
85 #endif
86
87 (void)kernel8; /* Muffle compiler */
88
89 *width = winwidth;
90 *height = winheight;
91 }
92
93
94 static void
95 finish( GLcontext *ctx )
96 {
97 #ifdef XFree86Server
98 /* NOT_NEEDED */
99 #else
100 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
101 if (xmesa) {
102 _glthread_LOCK_MUTEX(_xmesa_lock);
103 XSync( xmesa->display, False );
104 _glthread_UNLOCK_MUTEX(_xmesa_lock);
105 }
106 #endif
107 }
108
109
110 static void
111 flush( GLcontext *ctx )
112 {
113 #ifdef XFree86Server
114 /* NOT_NEEDED */
115 #else
116 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
117 if (xmesa) {
118 _glthread_LOCK_MUTEX(_xmesa_lock);
119 XFlush( xmesa->display );
120 _glthread_UNLOCK_MUTEX(_xmesa_lock);
121 }
122 #endif
123 }
124
125
126
127 /*
128 * This chooses the color buffer for reading and writing spans, points,
129 * lines, and triangles.
130 */
131 static void
132 set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
133 {
134 /* We can make this cast since the XMesaBuffer wraps GLframebuffer.
135 * GLframebuffer is the first member in a XMesaBuffer struct.
136 */
137 XMesaBuffer target = (XMesaBuffer) buffer;
138 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
139
140 /* This assignment tells the span/point/line/triangle functions
141 * which XMesaBuffer to use.
142 */
143 xmesa->xm_buffer = target;
144
145 /*
146 * Now determine front vs back color buffer.
147 */
148 if (bufferBit == FRONT_LEFT_BIT) {
149 target->buffer = target->frontbuffer;
150 }
151 else if (bufferBit == BACK_LEFT_BIT) {
152 ASSERT(target->db_state);
153 if (target->backpixmap) {
154 /* back buffer is a pixmape */
155 target->buffer = target->backpixmap; /* incompatible types? */
156 }
157 else if (target->backimage) {
158 /* back buffer is an XImage */
159 target->buffer = None;
160 }
161 else {
162 /* No back buffer!!!! Must be out of memory, use front buffer */
163 target->buffer = target->frontbuffer;
164 }
165 }
166 else {
167 _mesa_problem(ctx, "invalid buffer 0x%x in set_buffer() in xm_dd.c");
168 return;
169 }
170 xmesa_update_span_funcs(ctx);
171 }
172
173
174
175 static void
176 clear_index( GLcontext *ctx, GLuint index )
177 {
178 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
179 xmesa->clearpixel = (unsigned long) index;
180 XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc,
181 (unsigned long) index );
182 }
183
184
185 static void
186 clear_color( GLcontext *ctx, const GLfloat color[4] )
187 {
188 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
189 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
190 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
191 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
192 CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
193 xmesa->clearpixel = xmesa_color_to_pixel( xmesa,
194 xmesa->clearcolor[0],
195 xmesa->clearcolor[1],
196 xmesa->clearcolor[2],
197 xmesa->clearcolor[3],
198 xmesa->xm_visual->undithered_pf );
199 _glthread_LOCK_MUTEX(_xmesa_lock);
200 XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc,
201 xmesa->clearpixel );
202 _glthread_UNLOCK_MUTEX(_xmesa_lock);
203 }
204
205
206
207 /* Set index mask ala glIndexMask */
208 static void
209 index_mask( GLcontext *ctx, GLuint mask )
210 {
211 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
212 if (xmesa->xm_draw_buffer->buffer != XIMAGE) {
213 unsigned long m;
214 if (mask==0xffffffff) {
215 m = ((unsigned long)~0L);
216 }
217 else {
218 m = (unsigned long) mask;
219 }
220 XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m );
221 XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m );
222 }
223 }
224
225
226 /* Implements glColorMask() */
227 static void
228 color_mask(GLcontext *ctx,
229 GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
230 {
231 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
232 int xclass = GET_VISUAL_CLASS(xmesa->xm_visual);
233 (void) amask;
234
235 if (xclass == TrueColor || xclass == DirectColor) {
236 unsigned long m;
237 if (rmask && gmask && bmask) {
238 m = ((unsigned long)~0L);
239 }
240 else {
241 m = 0;
242 if (rmask) m |= GET_REDMASK(xmesa->xm_visual);
243 if (gmask) m |= GET_GREENMASK(xmesa->xm_visual);
244 if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual);
245 }
246 XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m );
247 }
248 }
249
250
251
252 /**********************************************************************/
253 /*** glClear implementations ***/
254 /**********************************************************************/
255
256
257 static void
258 clear_front_pixmap( GLcontext *ctx, GLboolean all,
259 GLint x, GLint y, GLint width, GLint height )
260 {
261 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
262 if (all) {
263 XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer,
264 xmesa->xm_draw_buffer->cleargc,
265 0, 0,
266 xmesa->xm_draw_buffer->width+1,
267 xmesa->xm_draw_buffer->height+1 );
268 }
269 else {
270 XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer,
271 xmesa->xm_draw_buffer->cleargc,
272 x, xmesa->xm_draw_buffer->height - y - height,
273 width, height );
274 }
275 }
276
277
278 static void
279 clear_back_pixmap( GLcontext *ctx, GLboolean all,
280 GLint x, GLint y, GLint width, GLint height )
281 {
282 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
283 if (all) {
284 XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap,
285 xmesa->xm_draw_buffer->cleargc,
286 0, 0,
287 xmesa->xm_draw_buffer->width+1,
288 xmesa->xm_draw_buffer->height+1 );
289 }
290 else {
291 XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap,
292 xmesa->xm_draw_buffer->cleargc,
293 x, xmesa->xm_draw_buffer->height - y - height,
294 width, height );
295 }
296 }
297
298
299 static void
300 clear_8bit_ximage( GLcontext *ctx, GLboolean all,
301 GLint x, GLint y, GLint width, GLint height )
302 {
303 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
304 if (all) {
305 size_t n = xmesa->xm_draw_buffer->backimage->bytes_per_line
306 * xmesa->xm_draw_buffer->backimage->height;
307 MEMSET( xmesa->xm_draw_buffer->backimage->data, xmesa->clearpixel, n );
308 }
309 else {
310 GLint i;
311 for (i=0;i<height;i++) {
312 GLubyte *ptr = PIXELADDR1( xmesa->xm_draw_buffer, x, y+i );
313 MEMSET( ptr, xmesa->clearpixel, width );
314 }
315 }
316 }
317
318
319 static void
320 clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
321 GLint x, GLint y, GLint width, GLint height )
322 {
323 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
324 if (all) {
325 GLint i, c16 = (xmesa->xm_draw_buffer->backimage->bytes_per_line>>4)<<4;
326 GLubyte *ptr = (GLubyte *)xmesa->xm_draw_buffer->backimage->data;
327 for (i=0; i<xmesa->xm_draw_buffer->backimage->height; i++) {
328 GLint j;
329 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
330 if (i&1) {
331 sptr += 16;
332 }
333 for (j=0; j<c16; j+=16) {
334 ptr[0] = sptr[0];
335 ptr[1] = sptr[1];
336 ptr[2] = sptr[2];
337 ptr[3] = sptr[3];
338 ptr[4] = sptr[4];
339 ptr[5] = sptr[5];
340 ptr[6] = sptr[6];
341 ptr[7] = sptr[7];
342 ptr[8] = sptr[8];
343 ptr[9] = sptr[9];
344 ptr[10] = sptr[10];
345 ptr[11] = sptr[11];
346 ptr[12] = sptr[12];
347 ptr[13] = sptr[13];
348 ptr[14] = sptr[14];
349 ptr[15] = sptr[15];
350 ptr += 16;
351 }
352 for (; j<xmesa->xm_draw_buffer->backimage->bytes_per_line; j++) {
353 *ptr = sptr[j&15];
354 ptr++;
355 }
356 }
357 }
358 else {
359 GLint i;
360 for (i=y; i<y+height; i++) {
361 GLubyte *ptr = PIXELADDR1( xmesa->xm_draw_buffer, x, i );
362 int j;
363 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
364 if (i&1) {
365 sptr += 16;
366 }
367 for (j=x; j<x+width; j++) {
368 *ptr = sptr[j&15];
369 ptr++;
370 }
371 }
372 }
373 }
374
375
376 static void
377 clear_16bit_ximage( GLcontext *ctx, GLboolean all,
378 GLint x, GLint y, GLint width, GLint height )
379 {
380 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
381 register GLuint pixel = (GLuint) xmesa->clearpixel;
382 if (xmesa->swapbytes) {
383 pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
384 }
385 if (all) {
386 register GLuint n;
387 register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
388 if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
389 /* low and high bytes are equal so use memset() */
390 n = xmesa->xm_draw_buffer->backimage->bytes_per_line
391 * xmesa->xm_draw_buffer->height;
392 MEMSET( ptr4, pixel & 0xff, n );
393 }
394 else {
395 pixel = pixel | (pixel<<16);
396 n = xmesa->xm_draw_buffer->backimage->bytes_per_line
397 * xmesa->xm_draw_buffer->height / 4;
398 do {
399 *ptr4++ = pixel;
400 n--;
401 } while (n!=0);
402
403 if ((xmesa->xm_draw_buffer->backimage->bytes_per_line *
404 xmesa->xm_draw_buffer->height) & 0x2)
405 *(GLushort *)ptr4 = pixel & 0xffff;
406 }
407 }
408 else {
409 register int i, j;
410 for (j=0;j<height;j++) {
411 register GLushort *ptr2 = PIXELADDR2( xmesa->xm_draw_buffer, x, y+j );
412 for (i=0;i<width;i++) {
413 *ptr2++ = pixel;
414 }
415 }
416 }
417 }
418
419
420 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
421 static void
422 clear_24bit_ximage( GLcontext *ctx, GLboolean all,
423 GLint x, GLint y, GLint width, GLint height )
424 {
425 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
426 const GLubyte r = xmesa->clearcolor[0];
427 const GLubyte g = xmesa->clearcolor[1];
428 const GLubyte b = xmesa->clearcolor[2];
429 register GLuint clearPixel;
430 if (xmesa->swapbytes) {
431 clearPixel = (b << 16) | (g << 8) | r;
432 }
433 else {
434 clearPixel = (r << 16) | (g << 8) | b;
435 }
436
437 if (all) {
438 if (r==g && g==b) {
439 /* same value for all three components (gray) */
440 const GLint w3 = xmesa->xm_draw_buffer->width * 3;
441 const GLint h = xmesa->xm_draw_buffer->height;
442 GLint i;
443 for (i = 0; i < h; i++) {
444 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
445 MEMSET(ptr3, r, w3);
446 }
447 }
448 else {
449 /* the usual case */
450 const GLint w = xmesa->xm_draw_buffer->width;
451 const GLint h = xmesa->xm_draw_buffer->height;
452 GLint i, j;
453 for (i = 0; i < h; i++) {
454 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
455 for (j = 0; j < w; j++) {
456 ptr3->r = r;
457 ptr3->g = g;
458 ptr3->b = b;
459 ptr3++;
460 }
461 }
462 #if 0 /* this code doesn't work for all window widths */
463 register GLuint *ptr4 = (GLuint *) ptr3;
464 register GLuint px;
465 GLuint pixel4[3];
466 register GLuint *p = pixel4;
467 pixel4[0] = clearPixel | (clearPixel << 24);
468 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
469 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
470 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
471 case 0:
472 break;
473 case 1:
474 px = *ptr4 & 0x00ffffff;
475 px |= pixel4[0] & 0xff000000;
476 *ptr4++ = px;
477 px = *ptr4 & 0xffff0000;
478 px |= pixel4[2] & 0x0000ffff;
479 *ptr4 = px;
480 if (0 == --n)
481 break;
482 case 2:
483 px = *ptr4 & 0x0000fffff;
484 px |= pixel4[1] & 0xffff0000;
485 *ptr4++ = px;
486 px = *ptr4 & 0xffffff00;
487 px |= pixel4[2] & 0x000000ff;
488 *ptr4 = px;
489 if (0 == --n)
490 break;
491 case 3:
492 px = *ptr4 & 0x000000ff;
493 px |= pixel4[2] & 0xffffff00;
494 *ptr4++ = px;
495 --n;
496 break;
497 }
498 while (n > 3) {
499 p = pixel4;
500 *ptr4++ = *p++;
501 *ptr4++ = *p++;
502 *ptr4++ = *p++;
503 n -= 4;
504 }
505 switch (n) {
506 case 3:
507 p = pixel4;
508 *ptr4++ = *p++;
509 *ptr4++ = *p++;
510 px = *ptr4 & 0xffffff00;
511 px |= clearPixel & 0xff;
512 *ptr4 = px;
513 break;
514 case 2:
515 p = pixel4;
516 *ptr4++ = *p++;
517 px = *ptr4 & 0xffff0000;
518 px |= *p & 0xffff;
519 *ptr4 = px;
520 break;
521 case 1:
522 px = *ptr4 & 0xff000000;
523 px |= *p & 0xffffff;
524 *ptr4 = px;
525 break;
526 case 0:
527 break;
528 }
529 #endif
530 }
531 }
532 else {
533 /* only clear subrect of color buffer */
534 if (r==g && g==b) {
535 /* same value for all three components (gray) */
536 GLint j;
537 for (j=0;j<height;j++) {
538 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
539 MEMSET(ptr3, r, 3 * width);
540 }
541 }
542 else {
543 /* non-gray clear color */
544 GLint i, j;
545 for (j = 0; j < height; j++) {
546 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
547 for (i = 0; i < width; i++) {
548 ptr3->r = r;
549 ptr3->g = g;
550 ptr3->b = b;
551 ptr3++;
552 }
553 }
554 #if 0 /* this code might not always (seems ptr3 always == ptr4) */
555 GLint j;
556 GLuint pixel4[3];
557 pixel4[0] = clearPixel | (clearPixel << 24);
558 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
559 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
560 for (j=0;j<height;j++) {
561 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
562 register GLuint *ptr4 = (GLuint *)ptr3;
563 register GLuint *p, px;
564 GLuint w = width;
565 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
566 case 0:
567 break;
568 case 1:
569 px = *ptr4 & 0x00ffffff;
570 px |= pixel4[0] & 0xff000000;
571 *ptr4++ = px;
572 px = *ptr4 & 0xffff0000;
573 px |= pixel4[2] & 0x0000ffff;
574 *ptr4 = px;
575 if (0 == --w)
576 break;
577 case 2:
578 px = *ptr4 & 0x0000fffff;
579 px |= pixel4[1] & 0xffff0000;
580 *ptr4++ = px;
581 px = *ptr4 & 0xffffff00;
582 px |= pixel4[2] & 0x000000ff;
583 *ptr4 = px;
584 if (0 == --w)
585 break;
586 case 3:
587 px = *ptr4 & 0x000000ff;
588 px |= pixel4[2] & 0xffffff00;
589 *ptr4++ = px;
590 --w;
591 break;
592 }
593 while (w > 3){
594 p = pixel4;
595 *ptr4++ = *p++;
596 *ptr4++ = *p++;
597 *ptr4++ = *p++;
598 w -= 4;
599 }
600 switch (w) {
601 case 3:
602 p = pixel4;
603 *ptr4++ = *p++;
604 *ptr4++ = *p++;
605 px = *ptr4 & 0xffffff00;
606 px |= *p & 0xff;
607 *ptr4 = px;
608 break;
609 case 2:
610 p = pixel4;
611 *ptr4++ = *p++;
612 px = *ptr4 & 0xffff0000;
613 px |= *p & 0xffff;
614 *ptr4 = px;
615 break;
616 case 1:
617 px = *ptr4 & 0xff000000;
618 px |= pixel4[0] & 0xffffff;
619 *ptr4 = px;
620 break;
621 case 0:
622 break;
623 }
624 }
625 #endif
626 }
627 }
628 }
629
630
631 static void
632 clear_32bit_ximage( GLcontext *ctx, GLboolean all,
633 GLint x, GLint y, GLint width, GLint height )
634 {
635 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
636 register GLuint pixel = (GLuint) xmesa->clearpixel;
637 if (xmesa->swapbytes) {
638 pixel = ((pixel >> 24) & 0x000000ff)
639 | ((pixel >> 8) & 0x0000ff00)
640 | ((pixel << 8) & 0x00ff0000)
641 | ((pixel << 24) & 0xff000000);
642 }
643 if (all) {
644 register GLint n = xmesa->xm_draw_buffer->width * xmesa->xm_draw_buffer->height;
645 register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
646 if (pixel==0) {
647 MEMSET( ptr4, pixel, 4*n );
648 }
649 else {
650 do {
651 *ptr4++ = pixel;
652 n--;
653 } while (n!=0);
654 }
655 }
656 else {
657 register int i, j;
658 for (j=0;j<height;j++) {
659 register GLuint *ptr4 = PIXELADDR4( xmesa->xm_draw_buffer, x, y+j );
660 for (i=0;i<width;i++) {
661 *ptr4++ = pixel;
662 }
663 }
664 }
665 }
666
667
668 static void
669 clear_nbit_ximage( GLcontext *ctx, GLboolean all,
670 GLint x, GLint y, GLint width, GLint height )
671 {
672 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
673 XMesaImage *img = xmesa->xm_draw_buffer->backimage;
674 if (all) {
675 register int i, j;
676 width = xmesa->xm_draw_buffer->width;
677 height = xmesa->xm_draw_buffer->height;
678 for (j=0;j<height;j++) {
679 for (i=0;i<width;i++) {
680 XMesaPutPixel( img, i, j, xmesa->clearpixel );
681 }
682 }
683 }
684 else {
685 /* TODO: optimize this */
686 register int i, j;
687 y = FLIP(xmesa->xm_draw_buffer, y);
688 for (j=0;j<height;j++) {
689 for (i=0;i<width;i++) {
690 XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
691 }
692 }
693 }
694 }
695
696
697
698 static void
699 clear_buffers( GLcontext *ctx, GLbitfield mask,
700 GLboolean all, GLint x, GLint y, GLint width, GLint height )
701 {
702 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
703 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
704
705 if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) &&
706 xmesa->xm_draw_buffer->mesa_buffer.UseSoftwareAlphaBuffers &&
707 ctx->Color.ColorMask[ACOMP]) {
708 _mesa_clear_alpha_buffers(ctx);
709 }
710
711 /* we can't handle color or index masking */
712 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
713 if (mask & DD_FRONT_LEFT_BIT) {
714 ASSERT(xmesa->xm_draw_buffer->front_clear_func);
715 (*xmesa->xm_draw_buffer->front_clear_func)( ctx, all, x, y, width, height );
716 mask &= ~DD_FRONT_LEFT_BIT;
717 }
718 if (mask & DD_BACK_LEFT_BIT) {
719 ASSERT(xmesa->xm_draw_buffer->back_clear_func);
720 (*xmesa->xm_draw_buffer->back_clear_func)( ctx, all, x, y, width, height );
721 mask &= ~DD_BACK_LEFT_BIT;
722 }
723 }
724
725 if (mask)
726 _swrast_Clear( ctx, mask, all, x, y, width, height );
727 }
728
729
730 /*
731 * When we detect that the user has resized the window this function will
732 * get called. Here we'll reallocate the back buffer, depth buffer,
733 * stencil buffer etc. to match the new window size.
734 */
735 void
736 xmesa_resize_buffers( GLframebuffer *buffer )
737 {
738 int height = (int) buffer->Height;
739 /* We can do this cast because the first field in the XMesaBuffer
740 * struct is a GLframebuffer struct. If this weren't true, we'd
741 * need a pointer from the GLframebuffer to the XMesaBuffer.
742 */
743 XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
744
745 xmBuffer->width = buffer->Width;
746 xmBuffer->height = buffer->Height;
747 xmesa_alloc_back_buffer( xmBuffer );
748
749 /* Needed by FLIP macro */
750 xmBuffer->bottom = height - 1;
751
752 if (xmBuffer->backimage) {
753 /* Needed by PIXELADDR1 macro */
754 xmBuffer->ximage_width1 = xmBuffer->backimage->bytes_per_line;
755 xmBuffer->ximage_origin1 = (GLubyte *) xmBuffer->backimage->data
756 + xmBuffer->ximage_width1 * (height-1);
757
758 /* Needed by PIXELADDR2 macro */
759 xmBuffer->ximage_width2 = xmBuffer->backimage->bytes_per_line / 2;
760 xmBuffer->ximage_origin2 = (GLushort *) xmBuffer->backimage->data
761 + xmBuffer->ximage_width2 * (height-1);
762
763 /* Needed by PIXELADDR3 macro */
764 xmBuffer->ximage_width3 = xmBuffer->backimage->bytes_per_line;
765 xmBuffer->ximage_origin3 = (GLubyte *) xmBuffer->backimage->data
766 + xmBuffer->ximage_width3 * (height-1);
767
768 /* Needed by PIXELADDR4 macro */
769 xmBuffer->ximage_width4 = xmBuffer->backimage->width;
770 xmBuffer->ximage_origin4 = (GLuint *) xmBuffer->backimage->data
771 + xmBuffer->ximage_width4 * (height-1);
772 }
773
774 _swrast_alloc_buffers( buffer );
775 }
776
777 #if 0
778 /*
779 * This function implements glDrawPixels() with an XPutImage call when
780 * drawing to the front buffer (X Window drawable).
781 * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
782 * XXX top/bottom edge clipping is broken!
783 */
784 static GLboolean
785 drawpixels_8R8G8B( GLcontext *ctx,
786 GLint x, GLint y, GLsizei width, GLsizei height,
787 GLenum format, GLenum type,
788 const struct gl_pixelstore_attrib *unpack,
789 const GLvoid *pixels )
790 {
791 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
792 XMesaDisplay *dpy = xmesa->xm_visual->display;
793 XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
794 XMesaGC gc = xmesa->xm_draw_buffer->gc;
795 assert(dpy);
796 assert(buffer);
797 assert(gc);
798
799 /* XXX also check for pixel scale/bias/lookup/zooming! */
800 if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) {
801 int dstX = x;
802 int dstY = y;
803 int w = width;
804 int h = height;
805 int srcX = unpack->SkipPixels;
806 int srcY = unpack->SkipRows;
807 if (_mesa_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
808 XMesaImage ximage;
809 MEMSET(&ximage, 0, sizeof(XMesaImage));
810 ximage.width = width;
811 ximage.height = height;
812 ximage.format = ZPixmap;
813 ximage.data = (char *) pixels + (height - 1) * width * 4;
814 ximage.byte_order = LSBFirst;
815 ximage.bitmap_unit = 32;
816 ximage.bitmap_bit_order = LSBFirst;
817 ximage.bitmap_pad = 32;
818 ximage.depth = 24;
819 ximage.bytes_per_line = -width * 4;
820 ximage.bits_per_pixel = 32;
821 ximage.red_mask = 0xff0000;
822 ximage.green_mask = 0x00ff00;
823 ximage.blue_mask = 0x0000ff;
824 dstY = FLIP(xmesa->xm_draw_buffer,dstY) - height + 1;
825 XPutImage(dpy, buffer, gc, &ximage, srcX, srcY, dstX, dstY, w, h);
826 return GL_TRUE;
827 }
828 }
829 return GL_FALSE;
830 }
831 #endif
832
833
834
835 static const GLubyte *
836 get_string( GLcontext *ctx, GLenum name )
837 {
838 (void) ctx;
839 switch (name) {
840 case GL_RENDERER:
841 #ifdef XFree86Server
842 return (const GLubyte *) "Mesa GLX Indirect";
843 #else
844 return (const GLubyte *) "Mesa X11";
845 #endif
846 case GL_VENDOR:
847 #ifdef XFree86Server
848 return (const GLubyte *) "Mesa project: www.mesa3d.org";
849 #else
850 return NULL;
851 #endif
852 default:
853 return NULL;
854 }
855 }
856
857
858 static void
859 enable( GLcontext *ctx, GLenum pname, GLboolean state )
860 {
861 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
862
863 switch (pname) {
864 case GL_DITHER:
865 if (state)
866 xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
867 else
868 xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
869 break;
870 default:
871 ; /* silence compiler warning */
872 }
873 }
874
875
876 void xmesa_update_state( GLcontext *ctx, GLuint new_state )
877 {
878 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
879
880 /* Propogate statechange information to swrast and swrast_setup
881 * modules. The X11 driver has no internal GL-dependent state.
882 */
883 _swrast_InvalidateState( ctx, new_state );
884 _ac_InvalidateState( ctx, new_state );
885 _tnl_InvalidateState( ctx, new_state );
886 _swsetup_InvalidateState( ctx, new_state );
887
888
889 /* setup pointers to front and back buffer clear functions */
890 xmesa->xm_draw_buffer->front_clear_func = clear_front_pixmap;
891 if (xmesa->xm_draw_buffer->backpixmap != XIMAGE) {
892 xmesa->xm_draw_buffer->back_clear_func = clear_back_pixmap;
893 }
894 else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
895 xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
896 }
897 else switch (xmesa->xm_visual->BitsPerPixel) {
898 case 8:
899 if (xmesa->xm_visual->hpcr_clear_flag) {
900 xmesa->xm_draw_buffer->back_clear_func = clear_HPCR_ximage;
901 }
902 else {
903 xmesa->xm_draw_buffer->back_clear_func = clear_8bit_ximage;
904 }
905 break;
906 case 16:
907 xmesa->xm_draw_buffer->back_clear_func = clear_16bit_ximage;
908 break;
909 case 24:
910 xmesa->xm_draw_buffer->back_clear_func = clear_24bit_ximage;
911 break;
912 case 32:
913 xmesa->xm_draw_buffer->back_clear_func = clear_32bit_ximage;
914 break;
915 default:
916 xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
917 break;
918 }
919
920 xmesa_update_span_funcs(ctx);
921 }
922
923
924
925 /* Setup pointers and other driver state that is constant for the life
926 * of a context.
927 */
928 void xmesa_init_pointers( GLcontext *ctx )
929 {
930 TNLcontext *tnl;
931 struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference( ctx );
932
933 ctx->Driver.GetString = get_string;
934 ctx->Driver.GetBufferSize = get_buffer_size;
935 ctx->Driver.Flush = flush;
936 ctx->Driver.Finish = finish;
937
938 /* Software rasterizer pixel paths:
939 */
940 ctx->Driver.Accum = _swrast_Accum;
941 ctx->Driver.Bitmap = _swrast_Bitmap;
942 ctx->Driver.Clear = clear_buffers;
943 ctx->Driver.ResizeBuffers = xmesa_resize_buffers;
944 ctx->Driver.CopyPixels = _swrast_CopyPixels;
945 ctx->Driver.DrawPixels = _swrast_DrawPixels;
946 ctx->Driver.ReadPixels = _swrast_ReadPixels;
947 ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
948
949 /* Software texture functions:
950 */
951 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
952 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
953 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
954 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
955 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
956 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
957 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
958 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
959
960 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
961 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
962 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
963 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
964 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
965
966 ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
967 ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
968 ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
969 ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
970 ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
971 ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
972
973 /* Swrast hooks for imaging extensions:
974 */
975 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
976 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
977 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
978 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
979
980
981 /* Statechange callbacks:
982 */
983 ctx->Driver.ClearIndex = clear_index;
984 ctx->Driver.ClearColor = clear_color;
985 ctx->Driver.IndexMask = index_mask;
986 ctx->Driver.ColorMask = color_mask;
987 ctx->Driver.Enable = enable;
988
989
990 /* Initialize the TNL driver interface:
991 */
992 tnl = TNL_CONTEXT(ctx);
993 tnl->Driver.RunPipeline = _tnl_run_pipeline;
994
995 dd->SetBuffer = set_buffer;
996
997 /* Install swsetup for tnl->Driver.Render.*:
998 */
999 _swsetup_Wakeup(ctx);
1000
1001 (void) DitherValues; /* silenced unused var warning */
1002 }
1003
1004
1005
1006
1007
1008 #define XMESA_NEW_POINT (_NEW_POINT | \
1009 _NEW_RENDERMODE | \
1010 _SWRAST_NEW_RASTERMASK)
1011
1012 #define XMESA_NEW_LINE (_NEW_LINE | \
1013 _NEW_TEXTURE | \
1014 _NEW_LIGHT | \
1015 _NEW_DEPTH | \
1016 _NEW_RENDERMODE | \
1017 _SWRAST_NEW_RASTERMASK)
1018
1019 #define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1020 _NEW_TEXTURE | \
1021 _NEW_LIGHT | \
1022 _NEW_DEPTH | \
1023 _NEW_RENDERMODE | \
1024 _SWRAST_NEW_RASTERMASK)
1025
1026
1027 /* Extend the software rasterizer with our line/point/triangle
1028 * functions.
1029 */
1030 void xmesa_register_swrast_functions( GLcontext *ctx )
1031 {
1032 SWcontext *swrast = SWRAST_CONTEXT( ctx );
1033
1034 swrast->choose_point = xmesa_choose_point;
1035 swrast->choose_line = xmesa_choose_line;
1036 swrast->choose_triangle = xmesa_choose_triangle;
1037
1038 swrast->invalidate_point |= XMESA_NEW_POINT;
1039 swrast->invalidate_line |= XMESA_NEW_LINE;
1040 swrast->invalidate_triangle |= XMESA_NEW_TRIANGLE;
1041 }