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