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