Major rework of tnl module
[mesa.git] / src / mesa / drivers / x11 / xm_dd.c
1 /* $Id: xm_dd.c,v 1.8 2000/12/26 05:09:31 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999-2000 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
27
28 #include "glxheader.h"
29 #include "context.h"
30 #include "drawpix.h"
31 #include "mem.h"
32 #include "state.h"
33 #include "depth.h"
34 #include "macros.h"
35 #include "mtypes.h"
36 #include "xmesaP.h"
37 #include "extensions.h"
38 #include "swrast/swrast.h"
39 #include "swrast_setup/swrast_setup.h"
40 #include "tnl/tnl.h"
41 #include "array_cache/acache.h"
42
43 /*
44 * Return the size (width,height of the current color buffer.
45 * This function should be called by the glViewport function because
46 * glViewport is often called when the window gets resized. We need to
47 * update some X/Mesa stuff when that happens.
48 * Output: width - width of buffer in pixels.
49 * height - height of buffer in pixels.
50 */
51 static void
52 get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
53 {
54 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
55 unsigned int winwidth, winheight;
56 #ifndef XFree86Server
57 Window root;
58 int winx, winy;
59 unsigned int bw, d;
60
61 _glthread_LOCK_MUTEX(_xmesa_lock);
62 XGetGeometry( xmesa->display, xmesa->xm_buffer->frontbuffer, &root,
63 &winx, &winy, &winwidth, &winheight, &bw, &d );
64 _glthread_UNLOCK_MUTEX(_xmesa_lock);
65 #else
66
67 winwidth = xmesa->xm_buffer->frontbuffer->width;
68 winheight = xmesa->xm_buffer->frontbuffer->height;
69 #endif
70
71 *width = winwidth;
72 *height = winheight;
73
74 if ( winwidth!=xmesa->xm_buffer->width
75 || winheight!=xmesa->xm_buffer->height) {
76 xmesa->xm_buffer->width = winwidth;
77 xmesa->xm_buffer->height = winheight;
78 xmesa_alloc_back_buffer( xmesa->xm_buffer );
79 }
80
81 /* Needed by FLIP macro */
82 xmesa->xm_buffer->bottom = (int) winheight - 1;
83
84 if (xmesa->xm_buffer->backimage) {
85 /* Needed by PIXELADDR1 macro */
86 xmesa->xm_buffer->ximage_width1
87 = xmesa->xm_buffer->backimage->bytes_per_line;
88 xmesa->xm_buffer->ximage_origin1
89 = (GLubyte *) xmesa->xm_buffer->backimage->data
90 + xmesa->xm_buffer->ximage_width1 * (winheight-1);
91
92 /* Needed by PIXELADDR2 macro */
93 xmesa->xm_buffer->ximage_width2
94 = xmesa->xm_buffer->backimage->bytes_per_line / 2;
95 xmesa->xm_buffer->ximage_origin2
96 = (GLushort *) xmesa->xm_buffer->backimage->data
97 + xmesa->xm_buffer->ximage_width2 * (winheight-1);
98
99 /* Needed by PIXELADDR3 macro */
100 xmesa->xm_buffer->ximage_width3
101 = xmesa->xm_buffer->backimage->bytes_per_line;
102 xmesa->xm_buffer->ximage_origin3
103 = (GLubyte *) xmesa->xm_buffer->backimage->data
104 + xmesa->xm_buffer->ximage_width3 * (winheight-1);
105
106 /* Needed by PIXELADDR4 macro */
107 xmesa->xm_buffer->ximage_width4 = xmesa->xm_buffer->backimage->width;
108 xmesa->xm_buffer->ximage_origin4
109 = (GLuint *) xmesa->xm_buffer->backimage->data
110 + xmesa->xm_buffer->ximage_width4 * (winheight-1);
111 }
112 }
113
114
115 static void
116 finish( GLcontext *ctx )
117 {
118 #ifdef XFree86Server
119 /* NOT_NEEDED */
120 #else
121 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
122 if (xmesa) {
123 _glthread_LOCK_MUTEX(_xmesa_lock);
124 XSync( xmesa->display, False );
125 _glthread_UNLOCK_MUTEX(_xmesa_lock);
126 }
127 #endif
128 }
129
130
131 static void
132 flush( GLcontext *ctx )
133 {
134 #ifdef XFree86Server
135 /* NOT_NEEDED */
136 #else
137 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
138 if (xmesa) {
139 _glthread_LOCK_MUTEX(_xmesa_lock);
140 XFlush( xmesa->display );
141 _glthread_UNLOCK_MUTEX(_xmesa_lock);
142 }
143 #endif
144 }
145
146
147
148
149 static GLboolean
150 set_draw_buffer( GLcontext *ctx, GLenum mode )
151 {
152 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
153 if (mode == GL_FRONT_LEFT) {
154 /* write to front buffer */
155 xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
156 xmesa_update_span_funcs(ctx);
157 return GL_TRUE;
158 }
159 else if (mode==GL_BACK_LEFT && xmesa->xm_buffer->db_state) {
160 /* write to back buffer */
161 if (xmesa->xm_buffer->backpixmap) {
162 xmesa->xm_buffer->buffer =
163 (XMesaDrawable)xmesa->xm_buffer->backpixmap;
164 }
165 else if (xmesa->xm_buffer->backimage) {
166 xmesa->xm_buffer->buffer = None;
167 }
168 else {
169 /* just in case there wasn't enough memory for back buffer */
170 xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
171 }
172 xmesa_update_span_funcs(ctx);
173 return GL_TRUE;
174 }
175 else {
176 return GL_FALSE;
177 }
178 }
179
180
181 static void
182 set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
183 {
184 XMesaBuffer target;
185 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
186
187 if (buffer == ctx->DrawBuffer) {
188 target = xmesa->xm_buffer;
189 xmesa->use_read_buffer = GL_FALSE;
190 }
191 else {
192 ASSERT(buffer == ctx->ReadBuffer);
193 target = xmesa->xm_read_buffer;
194 xmesa->use_read_buffer = GL_TRUE;
195 }
196
197 if (mode == GL_FRONT_LEFT) {
198 target->buffer = target->frontbuffer;
199 xmesa_update_span_funcs(ctx);
200 }
201 else if (mode==GL_BACK_LEFT && xmesa->xm_read_buffer->db_state) {
202 if (target->backpixmap) {
203 target->buffer = (XMesaDrawable)xmesa->xm_buffer->backpixmap;
204 }
205 else if (target->backimage) {
206 target->buffer = None;
207 }
208 else {
209 /* just in case there wasn't enough memory for back buffer */
210 target->buffer = target->frontbuffer;
211 }
212 xmesa_update_span_funcs(ctx);
213 }
214 else {
215 gl_problem(ctx, "invalid buffer in set_read_buffer() in xmesa2.c");
216 }
217 }
218
219
220
221 static void
222 clear_index( GLcontext *ctx, GLuint index )
223 {
224 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
225 xmesa->clearpixel = (unsigned long) index;
226 XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
227 (unsigned long) index );
228 }
229
230
231 static void
232 clear_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
233 {
234 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
235 xmesa->clearcolor[0] = r;
236 xmesa->clearcolor[1] = g;
237 xmesa->clearcolor[2] = b;
238 xmesa->clearcolor[3] = a;
239 xmesa->clearpixel = xmesa_color_to_pixel( xmesa, r, g, b, a,
240 xmesa->xm_visual->undithered_pf );
241 _glthread_LOCK_MUTEX(_xmesa_lock);
242 XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
243 xmesa->clearpixel );
244 _glthread_UNLOCK_MUTEX(_xmesa_lock);
245 }
246
247
248
249 /* Set index mask ala glIndexMask */
250 static void
251 index_mask( GLcontext *ctx, GLuint mask )
252 {
253 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
254 if (xmesa->xm_buffer->buffer != XIMAGE) {
255 unsigned long m;
256 if (mask==0xffffffff) {
257 m = ((unsigned long)~0L);
258 }
259 else {
260 m = (unsigned long) mask;
261 }
262 XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
263 }
264 }
265
266
267 /* Implements glColorMask() */
268 static void
269 color_mask(GLcontext *ctx,
270 GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
271 {
272 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
273 int xclass = GET_VISUAL_CLASS(xmesa->xm_visual);
274 (void) amask;
275
276 if (xmesa->xm_buffer->buffer != XIMAGE
277 && (xclass == TrueColor || xclass == DirectColor)) {
278 unsigned long m;
279 if (rmask && gmask && bmask) {
280 m = ((unsigned long)~0L);
281 }
282 else {
283 m = 0;
284 if (rmask) m |= GET_REDMASK(xmesa->xm_visual);
285 if (gmask) m |= GET_GREENMASK(xmesa->xm_visual);
286 if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual);
287 }
288 XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
289 }
290 }
291
292
293
294 /**********************************************************************/
295 /*** glClear implementations ***/
296 /**********************************************************************/
297
298
299 static void
300 clear_front_pixmap( GLcontext *ctx, GLboolean all,
301 GLint x, GLint y, GLint width, GLint height )
302 {
303 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
304 if (all) {
305 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
306 xmesa->xm_buffer->cleargc,
307 0, 0,
308 xmesa->xm_buffer->width+1,
309 xmesa->xm_buffer->height+1 );
310 }
311 else {
312 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
313 xmesa->xm_buffer->cleargc,
314 x, xmesa->xm_buffer->height - y - height,
315 width, height );
316 }
317 }
318
319
320 static void
321 clear_back_pixmap( GLcontext *ctx, GLboolean all,
322 GLint x, GLint y, GLint width, GLint height )
323 {
324 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
325 if (all) {
326 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
327 xmesa->xm_buffer->cleargc,
328 0, 0,
329 xmesa->xm_buffer->width+1,
330 xmesa->xm_buffer->height+1 );
331 }
332 else {
333 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
334 xmesa->xm_buffer->cleargc,
335 x, xmesa->xm_buffer->height - y - height,
336 width, height );
337 }
338 }
339
340
341 static void
342 clear_8bit_ximage( GLcontext *ctx, GLboolean all,
343 GLint x, GLint y, GLint width, GLint height )
344 {
345 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
346 if (all) {
347 size_t n = xmesa->xm_buffer->backimage->bytes_per_line
348 * xmesa->xm_buffer->backimage->height;
349 MEMSET( xmesa->xm_buffer->backimage->data, xmesa->clearpixel, n );
350 }
351 else {
352 GLint i;
353 for (i=0;i<height;i++) {
354 GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y+i );
355 MEMSET( ptr, xmesa->clearpixel, width );
356 }
357 }
358 }
359
360
361 static void
362 clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
363 GLint x, GLint y, GLint width, GLint height )
364 {
365 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
366 if (all) {
367 GLint i, c16 = (xmesa->xm_buffer->backimage->bytes_per_line>>4)<<4;
368 GLubyte *ptr = (GLubyte *)xmesa->xm_buffer->backimage->data;
369 for (i=0; i<xmesa->xm_buffer->backimage->height; i++) {
370 GLint j;
371 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
372 if (i&1) {
373 sptr += 16;
374 }
375 for (j=0; j<c16; j+=16) {
376 ptr[0] = sptr[0];
377 ptr[1] = sptr[1];
378 ptr[2] = sptr[2];
379 ptr[3] = sptr[3];
380 ptr[4] = sptr[4];
381 ptr[5] = sptr[5];
382 ptr[6] = sptr[6];
383 ptr[7] = sptr[7];
384 ptr[8] = sptr[8];
385 ptr[9] = sptr[9];
386 ptr[10] = sptr[10];
387 ptr[11] = sptr[11];
388 ptr[12] = sptr[12];
389 ptr[13] = sptr[13];
390 ptr[14] = sptr[14];
391 ptr[15] = sptr[15];
392 ptr += 16;
393 }
394 for (; j<xmesa->xm_buffer->backimage->bytes_per_line; j++) {
395 *ptr = sptr[j&15];
396 ptr++;
397 }
398 }
399 }
400 else {
401 GLint i;
402 for (i=y; i<y+height; i++) {
403 GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, i );
404 int j;
405 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
406 if (i&1) {
407 sptr += 16;
408 }
409 for (j=x; j<x+width; j++) {
410 *ptr = sptr[j&15];
411 ptr++;
412 }
413 }
414 }
415 }
416
417
418 static void
419 clear_16bit_ximage( GLcontext *ctx, GLboolean all,
420 GLint x, GLint y, GLint width, GLint height )
421 {
422 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
423 register GLuint pixel = (GLuint) xmesa->clearpixel;
424 if (xmesa->swapbytes) {
425 pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
426 }
427 if (all) {
428 register GLuint n;
429 register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
430 if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
431 /* low and high bytes are equal so use memset() */
432 n = xmesa->xm_buffer->backimage->bytes_per_line
433 * xmesa->xm_buffer->height;
434 MEMSET( ptr4, pixel & 0xff, n );
435 }
436 else {
437 pixel = pixel | (pixel<<16);
438 n = xmesa->xm_buffer->backimage->bytes_per_line
439 * xmesa->xm_buffer->height / 4;
440 do {
441 *ptr4++ = pixel;
442 n--;
443 } while (n!=0);
444
445 if ((xmesa->xm_buffer->backimage->bytes_per_line *
446 xmesa->xm_buffer->height) & 0x2)
447 *(GLushort *)ptr4 = pixel & 0xffff;
448 }
449 }
450 else {
451 register int i, j;
452 for (j=0;j<height;j++) {
453 register GLushort *ptr2 = PIXELADDR2( xmesa->xm_buffer, x, y+j );
454 for (i=0;i<width;i++) {
455 *ptr2++ = pixel;
456 }
457 }
458 }
459 }
460
461
462 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
463 static void
464 clear_24bit_ximage( GLcontext *ctx, GLboolean all,
465 GLint x, GLint y, GLint width, GLint height )
466 {
467 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
468 const GLubyte r = xmesa->clearcolor[0];
469 const GLubyte g = xmesa->clearcolor[1];
470 const GLubyte b = xmesa->clearcolor[2];
471 register GLuint clearPixel;
472 if (xmesa->swapbytes) {
473 clearPixel = (b << 16) | (g << 8) | r;
474 }
475 else {
476 clearPixel = (r << 16) | (g << 8) | b;
477 }
478
479 if (all) {
480 if (r==g && g==b) {
481 /* same value for all three components (gray) */
482 const GLint w3 = xmesa->xm_buffer->width * 3;
483 const GLint h = xmesa->xm_buffer->height;
484 GLint i;
485 for (i = 0; i < h; i++) {
486 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
487 MEMSET(ptr3, r, w3);
488 }
489 }
490 else {
491 /* the usual case */
492 const GLint w = xmesa->xm_buffer->width;
493 const GLint h = xmesa->xm_buffer->height;
494 GLint i, j;
495 for (i = 0; i < h; i++) {
496 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
497 for (j = 0; j < w; j++) {
498 ptr3->r = r;
499 ptr3->g = g;
500 ptr3->b = b;
501 ptr3++;
502 }
503 }
504 #if 0 /* this code doesn't work for all window widths */
505 register GLuint *ptr4 = (GLuint *) ptr3;
506 register GLuint px;
507 GLuint pixel4[3];
508 register GLuint *p = pixel4;
509 pixel4[0] = clearPixel | (clearPixel << 24);
510 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
511 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
512 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
513 case 0:
514 break;
515 case 1:
516 px = *ptr4 & 0x00ffffff;
517 px |= pixel4[0] & 0xff000000;
518 *ptr4++ = px;
519 px = *ptr4 & 0xffff0000;
520 px |= pixel4[2] & 0x0000ffff;
521 *ptr4 = px;
522 if (0 == --n)
523 break;
524 case 2:
525 px = *ptr4 & 0x0000fffff;
526 px |= pixel4[1] & 0xffff0000;
527 *ptr4++ = px;
528 px = *ptr4 & 0xffffff00;
529 px |= pixel4[2] & 0x000000ff;
530 *ptr4 = px;
531 if (0 == --n)
532 break;
533 case 3:
534 px = *ptr4 & 0x000000ff;
535 px |= pixel4[2] & 0xffffff00;
536 *ptr4++ = px;
537 --n;
538 break;
539 }
540 while (n > 3) {
541 p = pixel4;
542 *ptr4++ = *p++;
543 *ptr4++ = *p++;
544 *ptr4++ = *p++;
545 n -= 4;
546 }
547 switch (n) {
548 case 3:
549 p = pixel4;
550 *ptr4++ = *p++;
551 *ptr4++ = *p++;
552 px = *ptr4 & 0xffffff00;
553 px |= clearPixel & 0xff;
554 *ptr4 = px;
555 break;
556 case 2:
557 p = pixel4;
558 *ptr4++ = *p++;
559 px = *ptr4 & 0xffff0000;
560 px |= *p & 0xffff;
561 *ptr4 = px;
562 break;
563 case 1:
564 px = *ptr4 & 0xff000000;
565 px |= *p & 0xffffff;
566 *ptr4 = px;
567 break;
568 case 0:
569 break;
570 }
571 #endif
572 }
573 }
574 else {
575 /* only clear subrect of color buffer */
576 if (r==g && g==b) {
577 /* same value for all three components (gray) */
578 GLint j;
579 for (j=0;j<height;j++) {
580 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
581 MEMSET(ptr3, r, 3 * width);
582 }
583 }
584 else {
585 /* non-gray clear color */
586 GLint i, j;
587 for (j = 0; j < height; j++) {
588 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
589 for (i = 0; i < width; i++) {
590 ptr3->r = r;
591 ptr3->g = g;
592 ptr3->b = b;
593 ptr3++;
594 }
595 }
596 #if 0 /* this code might not always (seems ptr3 always == ptr4) */
597 GLint j;
598 GLuint pixel4[3];
599 pixel4[0] = clearPixel | (clearPixel << 24);
600 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
601 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
602 for (j=0;j<height;j++) {
603 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
604 register GLuint *ptr4 = (GLuint *)ptr3;
605 register GLuint *p, px;
606 GLuint w = width;
607 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
608 case 0:
609 break;
610 case 1:
611 px = *ptr4 & 0x00ffffff;
612 px |= pixel4[0] & 0xff000000;
613 *ptr4++ = px;
614 px = *ptr4 & 0xffff0000;
615 px |= pixel4[2] & 0x0000ffff;
616 *ptr4 = px;
617 if (0 == --w)
618 break;
619 case 2:
620 px = *ptr4 & 0x0000fffff;
621 px |= pixel4[1] & 0xffff0000;
622 *ptr4++ = px;
623 px = *ptr4 & 0xffffff00;
624 px |= pixel4[2] & 0x000000ff;
625 *ptr4 = px;
626 if (0 == --w)
627 break;
628 case 3:
629 px = *ptr4 & 0x000000ff;
630 px |= pixel4[2] & 0xffffff00;
631 *ptr4++ = px;
632 --w;
633 break;
634 }
635 while (w > 3){
636 p = pixel4;
637 *ptr4++ = *p++;
638 *ptr4++ = *p++;
639 *ptr4++ = *p++;
640 w -= 4;
641 }
642 switch (w) {
643 case 3:
644 p = pixel4;
645 *ptr4++ = *p++;
646 *ptr4++ = *p++;
647 px = *ptr4 & 0xffffff00;
648 px |= *p & 0xff;
649 *ptr4 = px;
650 break;
651 case 2:
652 p = pixel4;
653 *ptr4++ = *p++;
654 px = *ptr4 & 0xffff0000;
655 px |= *p & 0xffff;
656 *ptr4 = px;
657 break;
658 case 1:
659 px = *ptr4 & 0xff000000;
660 px |= pixel4[0] & 0xffffff;
661 *ptr4 = px;
662 break;
663 case 0:
664 break;
665 }
666 }
667 #endif
668 }
669 }
670 }
671
672
673 static void
674 clear_32bit_ximage( GLcontext *ctx, GLboolean all,
675 GLint x, GLint y, GLint width, GLint height )
676 {
677 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
678 if (all) {
679 register GLint n = xmesa->xm_buffer->width * xmesa->xm_buffer->height;
680 register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
681 register GLuint pixel = (GLuint) xmesa->clearpixel;
682 if (xmesa->swapbytes) {
683 pixel = ((pixel >> 24) & 0x000000ff)
684 | ((pixel >> 8) & 0x0000ff00)
685 | ((pixel << 8) & 0x00ff0000)
686 | ((pixel << 24) & 0xff000000);
687 }
688 if (pixel==0) {
689 MEMSET( ptr4, pixel, 4*n );
690 }
691 else {
692 do {
693 *ptr4++ = pixel;
694 n--;
695 } while (n!=0);
696 }
697 }
698 else {
699 register int i, j;
700 register GLuint pixel = (GLuint) xmesa->clearpixel;
701 for (j=0;j<height;j++) {
702 register GLuint *ptr4 = PIXELADDR4( xmesa->xm_buffer, x, y+j );
703 for (i=0;i<width;i++) {
704 *ptr4++ = pixel;
705 }
706 }
707 }
708 }
709
710
711 static void
712 clear_nbit_ximage( GLcontext *ctx, GLboolean all,
713 GLint x, GLint y, GLint width, GLint height )
714 {
715 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
716 XMesaImage *img = xmesa->xm_buffer->backimage;
717 if (all) {
718 register int i, j;
719 width = xmesa->xm_buffer->width;
720 height = xmesa->xm_buffer->height;
721 for (j=0;j<height;j++) {
722 for (i=0;i<width;i++) {
723 XMesaPutPixel( img, i, j, xmesa->clearpixel );
724 }
725 }
726 }
727 else {
728 /* TODO: optimize this */
729 register int i, j;
730 y = FLIP(xmesa->xm_buffer, y);
731 for (j=0;j<height;j++) {
732 for (i=0;i<width;i++) {
733 XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
734 }
735 }
736 }
737 }
738
739
740
741 static GLbitfield
742 clear_buffers( GLcontext *ctx, GLbitfield mask,
743 GLboolean all, GLint x, GLint y, GLint width, GLint height )
744 {
745 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
746 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
747
748 /* we can't handle color or index masking */
749 if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
750 if (*colorMask != 0xffffffff || ctx->Color.IndexMask != 0xffffffff)
751 return mask;
752 }
753
754 if (mask & DD_FRONT_LEFT_BIT) {
755 ASSERT(xmesa->xm_buffer->front_clear_func);
756 (*xmesa->xm_buffer->front_clear_func)( ctx, all, x, y, width, height );
757 }
758 if (mask & DD_BACK_LEFT_BIT) {
759 ASSERT(xmesa->xm_buffer->back_clear_func);
760 (*xmesa->xm_buffer->back_clear_func)( ctx, all, x, y, width, height );
761 }
762 return mask & (~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
763 }
764
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_buffer->buffer;
784 XMesaGC gc = xmesa->xm_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_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 *) "VA Linux Systems, Inc.";
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_buffer->front_clear_func = clear_front_pixmap;
881 if (xmesa->xm_buffer->backpixmap != XIMAGE) {
882 xmesa->xm_buffer->back_clear_func = clear_back_pixmap;
883 }
884 else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
885 xmesa->xm_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_buffer->back_clear_func = clear_HPCR_ximage;
891 }
892 else {
893 xmesa->xm_buffer->back_clear_func = clear_8bit_ximage;
894 }
895 break;
896 case 16:
897 xmesa->xm_buffer->back_clear_func = clear_16bit_ximage;
898 break;
899 case 24:
900 xmesa->xm_buffer->back_clear_func = clear_24bit_ximage;
901 break;
902 case 32:
903 xmesa->xm_buffer->back_clear_func = clear_32bit_ximage;
904 break;
905 default:
906 xmesa->xm_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 ctx->Driver.GetString = get_string;
921 ctx->Driver.GetBufferSize = get_buffer_size;
922 ctx->Driver.Flush = flush;
923 ctx->Driver.Finish = finish;
924
925 ctx->Driver.RenderStart = 0;
926 ctx->Driver.RenderFinish = _swrast_flush;
927
928 ctx->Driver.SetDrawBuffer = set_draw_buffer;
929 ctx->Driver.SetReadBuffer = set_read_buffer;
930
931 ctx->Driver.ClearIndex = clear_index;
932 ctx->Driver.ClearColor = clear_color;
933 ctx->Driver.Clear = clear_buffers;
934 ctx->Driver.IndexMask = index_mask;
935 ctx->Driver.ColorMask = color_mask;
936 ctx->Driver.Enable = enable;
937
938 ctx->Driver.PointsFunc = _swsetup_Points;
939 ctx->Driver.LineFunc = _swsetup_Line;
940 ctx->Driver.TriangleFunc = _swsetup_Triangle;
941 ctx->Driver.QuadFunc = _swsetup_Quad;
942 ctx->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices;
943 ctx->Driver.ResetLineStipple = _swrast_ResetLineStipple;
944 (void) DitherValues; /* silenced unused var warning */
945 }