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