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