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