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