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