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