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