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