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