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