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