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