bf0058cc41e96dad1fd03be3e49f91a8db46f9d9
[mesa.git] / src / mesa / drivers / x11 / xm_dd.c
1 /* $Id: xm_dd.c,v 1.15 2001/02/19 20:01:42 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #include "glxheader.h"
29 #include "context.h"
30 #include "depth.h"
31 #include "drawpix.h"
32 #include "extensions.h"
33 #include "macros.h"
34 #include "mem.h"
35 #include "mtypes.h"
36 #include "state.h"
37 #include "texstore.h"
38 #include "xmesaP.h"
39 #include "array_cache/acache.h"
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/tnl.h"
43
44
45 /*
46 * Return the size (width,height of the current color buffer.
47 * This function should be called by the glViewport function because
48 * glViewport is often called when the window gets resized. We need to
49 * update some X/Mesa stuff when that happens.
50 * Output: width - width of buffer in pixels.
51 * height - height of buffer in pixels.
52 */
53 static void
54 get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
55 {
56 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
57 unsigned int winwidth, winheight;
58 #ifndef XFree86Server
59 Window root;
60 int winx, winy;
61 unsigned int bw, d;
62
63 _glthread_LOCK_MUTEX(_xmesa_lock);
64 XGetGeometry( xmesa->display, xmesa->xm_buffer->frontbuffer, &root,
65 &winx, &winy, &winwidth, &winheight, &bw, &d );
66 _glthread_UNLOCK_MUTEX(_xmesa_lock);
67 #else
68
69 winwidth = xmesa->xm_buffer->frontbuffer->width;
70 winheight = xmesa->xm_buffer->frontbuffer->height;
71 #endif
72
73 *width = winwidth;
74 *height = winheight;
75
76 if ( winwidth!=xmesa->xm_buffer->width
77 || winheight!=xmesa->xm_buffer->height) {
78 xmesa->xm_buffer->width = winwidth;
79 xmesa->xm_buffer->height = winheight;
80 xmesa_alloc_back_buffer( xmesa->xm_buffer );
81 }
82
83 /* Needed by FLIP macro */
84 xmesa->xm_buffer->bottom = (int) winheight - 1;
85
86 if (xmesa->xm_buffer->backimage) {
87 /* Needed by PIXELADDR1 macro */
88 xmesa->xm_buffer->ximage_width1
89 = xmesa->xm_buffer->backimage->bytes_per_line;
90 xmesa->xm_buffer->ximage_origin1
91 = (GLubyte *) xmesa->xm_buffer->backimage->data
92 + xmesa->xm_buffer->ximage_width1 * (winheight-1);
93
94 /* Needed by PIXELADDR2 macro */
95 xmesa->xm_buffer->ximage_width2
96 = xmesa->xm_buffer->backimage->bytes_per_line / 2;
97 xmesa->xm_buffer->ximage_origin2
98 = (GLushort *) xmesa->xm_buffer->backimage->data
99 + xmesa->xm_buffer->ximage_width2 * (winheight-1);
100
101 /* Needed by PIXELADDR3 macro */
102 xmesa->xm_buffer->ximage_width3
103 = xmesa->xm_buffer->backimage->bytes_per_line;
104 xmesa->xm_buffer->ximage_origin3
105 = (GLubyte *) xmesa->xm_buffer->backimage->data
106 + xmesa->xm_buffer->ximage_width3 * (winheight-1);
107
108 /* Needed by PIXELADDR4 macro */
109 xmesa->xm_buffer->ximage_width4 = xmesa->xm_buffer->backimage->width;
110 xmesa->xm_buffer->ximage_origin4
111 = (GLuint *) xmesa->xm_buffer->backimage->data
112 + xmesa->xm_buffer->ximage_width4 * (winheight-1);
113 }
114 }
115
116
117 static void
118 finish( GLcontext *ctx )
119 {
120 #ifdef XFree86Server
121 /* NOT_NEEDED */
122 #else
123 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
124 if (xmesa) {
125 _glthread_LOCK_MUTEX(_xmesa_lock);
126 XSync( xmesa->display, False );
127 _glthread_UNLOCK_MUTEX(_xmesa_lock);
128 }
129 #endif
130 }
131
132
133 static void
134 flush( GLcontext *ctx )
135 {
136 #ifdef XFree86Server
137 /* NOT_NEEDED */
138 #else
139 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
140 if (xmesa) {
141 _glthread_LOCK_MUTEX(_xmesa_lock);
142 XFlush( xmesa->display );
143 _glthread_UNLOCK_MUTEX(_xmesa_lock);
144 }
145 #endif
146 }
147
148
149
150
151 static GLboolean
152 set_draw_buffer( GLcontext *ctx, GLenum mode )
153 {
154 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
155 if (mode == GL_FRONT_LEFT) {
156 /* write to front buffer */
157 xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
158 xmesa_update_span_funcs(ctx);
159 return GL_TRUE;
160 }
161 else if (mode==GL_BACK_LEFT && xmesa->xm_buffer->db_state) {
162 /* write to back buffer */
163 if (xmesa->xm_buffer->backpixmap) {
164 xmesa->xm_buffer->buffer =
165 (XMesaDrawable)xmesa->xm_buffer->backpixmap;
166 }
167 else if (xmesa->xm_buffer->backimage) {
168 xmesa->xm_buffer->buffer = None;
169 }
170 else {
171 /* just in case there wasn't enough memory for back buffer */
172 xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
173 }
174 xmesa_update_span_funcs(ctx);
175 return GL_TRUE;
176 }
177 else {
178 return GL_FALSE;
179 }
180 }
181
182
183 static void
184 set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
185 {
186 XMesaBuffer target;
187 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
188
189 if (buffer == ctx->DrawBuffer) {
190 target = xmesa->xm_buffer;
191 xmesa->use_read_buffer = GL_FALSE;
192 }
193 else {
194 ASSERT(buffer == ctx->ReadBuffer);
195 target = xmesa->xm_read_buffer;
196 xmesa->use_read_buffer = GL_TRUE;
197 }
198
199 if (mode == GL_FRONT_LEFT) {
200 target->buffer = target->frontbuffer;
201 xmesa_update_span_funcs(ctx);
202 }
203 else if (mode==GL_BACK_LEFT && xmesa->xm_read_buffer->db_state) {
204 if (target->backpixmap) {
205 target->buffer = (XMesaDrawable)xmesa->xm_buffer->backpixmap;
206 }
207 else if (target->backimage) {
208 target->buffer = None;
209 }
210 else {
211 /* just in case there wasn't enough memory for back buffer */
212 target->buffer = target->frontbuffer;
213 }
214 xmesa_update_span_funcs(ctx);
215 }
216 else {
217 gl_problem(ctx, "invalid buffer in set_read_buffer() in xmesa2.c");
218 }
219 }
220
221
222
223 static void
224 clear_index( GLcontext *ctx, GLuint index )
225 {
226 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
227 xmesa->clearpixel = (unsigned long) index;
228 XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
229 (unsigned long) index );
230 }
231
232
233 static void
234 clear_color( GLcontext *ctx, const GLchan color[4] )
235 {
236 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
237 xmesa->clearcolor[0] = color[0];
238 xmesa->clearcolor[1] = color[1];
239 xmesa->clearcolor[2] = color[2];
240 xmesa->clearcolor[3] = color[3];
241 xmesa->clearpixel = xmesa_color_to_pixel( xmesa, color[0], color[1],
242 color[2], color[3],
243 xmesa->xm_visual->undithered_pf );
244 _glthread_LOCK_MUTEX(_xmesa_lock);
245 XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
246 xmesa->clearpixel );
247 _glthread_UNLOCK_MUTEX(_xmesa_lock);
248 }
249
250
251
252 /* Set index mask ala glIndexMask */
253 static void
254 index_mask( GLcontext *ctx, GLuint mask )
255 {
256 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
257 if (xmesa->xm_buffer->buffer != XIMAGE) {
258 unsigned long m;
259 if (mask==0xffffffff) {
260 m = ((unsigned long)~0L);
261 }
262 else {
263 m = (unsigned long) mask;
264 }
265 XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
266 }
267 }
268
269
270 /* Implements glColorMask() */
271 static void
272 color_mask(GLcontext *ctx,
273 GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
274 {
275 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
276 int xclass = GET_VISUAL_CLASS(xmesa->xm_visual);
277 (void) amask;
278
279 if (xmesa->xm_buffer->buffer != XIMAGE
280 && (xclass == TrueColor || xclass == DirectColor)) {
281 unsigned long m;
282 if (rmask && gmask && bmask) {
283 m = ((unsigned long)~0L);
284 }
285 else {
286 m = 0;
287 if (rmask) m |= GET_REDMASK(xmesa->xm_visual);
288 if (gmask) m |= GET_GREENMASK(xmesa->xm_visual);
289 if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual);
290 }
291 XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
292 }
293 }
294
295
296
297 /**********************************************************************/
298 /*** glClear implementations ***/
299 /**********************************************************************/
300
301
302 static void
303 clear_front_pixmap( GLcontext *ctx, GLboolean all,
304 GLint x, GLint y, GLint width, GLint height )
305 {
306 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
307 if (all) {
308 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
309 xmesa->xm_buffer->cleargc,
310 0, 0,
311 xmesa->xm_buffer->width+1,
312 xmesa->xm_buffer->height+1 );
313 }
314 else {
315 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
316 xmesa->xm_buffer->cleargc,
317 x, xmesa->xm_buffer->height - y - height,
318 width, height );
319 }
320 }
321
322
323 static void
324 clear_back_pixmap( GLcontext *ctx, GLboolean all,
325 GLint x, GLint y, GLint width, GLint height )
326 {
327 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
328 if (all) {
329 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
330 xmesa->xm_buffer->cleargc,
331 0, 0,
332 xmesa->xm_buffer->width+1,
333 xmesa->xm_buffer->height+1 );
334 }
335 else {
336 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
337 xmesa->xm_buffer->cleargc,
338 x, xmesa->xm_buffer->height - y - height,
339 width, height );
340 }
341 }
342
343
344 static void
345 clear_8bit_ximage( GLcontext *ctx, GLboolean all,
346 GLint x, GLint y, GLint width, GLint height )
347 {
348 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
349 if (all) {
350 size_t n = xmesa->xm_buffer->backimage->bytes_per_line
351 * xmesa->xm_buffer->backimage->height;
352 MEMSET( xmesa->xm_buffer->backimage->data, xmesa->clearpixel, n );
353 }
354 else {
355 GLint i;
356 for (i=0;i<height;i++) {
357 GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y+i );
358 MEMSET( ptr, xmesa->clearpixel, width );
359 }
360 }
361 }
362
363
364 static void
365 clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
366 GLint x, GLint y, GLint width, GLint height )
367 {
368 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
369 if (all) {
370 GLint i, c16 = (xmesa->xm_buffer->backimage->bytes_per_line>>4)<<4;
371 GLubyte *ptr = (GLubyte *)xmesa->xm_buffer->backimage->data;
372 for (i=0; i<xmesa->xm_buffer->backimage->height; i++) {
373 GLint j;
374 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
375 if (i&1) {
376 sptr += 16;
377 }
378 for (j=0; j<c16; j+=16) {
379 ptr[0] = sptr[0];
380 ptr[1] = sptr[1];
381 ptr[2] = sptr[2];
382 ptr[3] = sptr[3];
383 ptr[4] = sptr[4];
384 ptr[5] = sptr[5];
385 ptr[6] = sptr[6];
386 ptr[7] = sptr[7];
387 ptr[8] = sptr[8];
388 ptr[9] = sptr[9];
389 ptr[10] = sptr[10];
390 ptr[11] = sptr[11];
391 ptr[12] = sptr[12];
392 ptr[13] = sptr[13];
393 ptr[14] = sptr[14];
394 ptr[15] = sptr[15];
395 ptr += 16;
396 }
397 for (; j<xmesa->xm_buffer->backimage->bytes_per_line; j++) {
398 *ptr = sptr[j&15];
399 ptr++;
400 }
401 }
402 }
403 else {
404 GLint i;
405 for (i=y; i<y+height; i++) {
406 GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, i );
407 int j;
408 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
409 if (i&1) {
410 sptr += 16;
411 }
412 for (j=x; j<x+width; j++) {
413 *ptr = sptr[j&15];
414 ptr++;
415 }
416 }
417 }
418 }
419
420
421 static void
422 clear_16bit_ximage( GLcontext *ctx, GLboolean all,
423 GLint x, GLint y, GLint width, GLint height )
424 {
425 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
426 register GLuint pixel = (GLuint) xmesa->clearpixel;
427 if (xmesa->swapbytes) {
428 pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
429 }
430 if (all) {
431 register GLuint n;
432 register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
433 if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
434 /* low and high bytes are equal so use memset() */
435 n = xmesa->xm_buffer->backimage->bytes_per_line
436 * xmesa->xm_buffer->height;
437 MEMSET( ptr4, pixel & 0xff, n );
438 }
439 else {
440 pixel = pixel | (pixel<<16);
441 n = xmesa->xm_buffer->backimage->bytes_per_line
442 * xmesa->xm_buffer->height / 4;
443 do {
444 *ptr4++ = pixel;
445 n--;
446 } while (n!=0);
447
448 if ((xmesa->xm_buffer->backimage->bytes_per_line *
449 xmesa->xm_buffer->height) & 0x2)
450 *(GLushort *)ptr4 = pixel & 0xffff;
451 }
452 }
453 else {
454 register int i, j;
455 for (j=0;j<height;j++) {
456 register GLushort *ptr2 = PIXELADDR2( xmesa->xm_buffer, x, y+j );
457 for (i=0;i<width;i++) {
458 *ptr2++ = pixel;
459 }
460 }
461 }
462 }
463
464
465 /* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
466 static void
467 clear_24bit_ximage( GLcontext *ctx, GLboolean all,
468 GLint x, GLint y, GLint width, GLint height )
469 {
470 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
471 const GLubyte r = xmesa->clearcolor[0];
472 const GLubyte g = xmesa->clearcolor[1];
473 const GLubyte b = xmesa->clearcolor[2];
474 register GLuint clearPixel;
475 if (xmesa->swapbytes) {
476 clearPixel = (b << 16) | (g << 8) | r;
477 }
478 else {
479 clearPixel = (r << 16) | (g << 8) | b;
480 }
481
482 if (all) {
483 if (r==g && g==b) {
484 /* same value for all three components (gray) */
485 const GLint w3 = xmesa->xm_buffer->width * 3;
486 const GLint h = xmesa->xm_buffer->height;
487 GLint i;
488 for (i = 0; i < h; i++) {
489 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
490 MEMSET(ptr3, r, w3);
491 }
492 }
493 else {
494 /* the usual case */
495 const GLint w = xmesa->xm_buffer->width;
496 const GLint h = xmesa->xm_buffer->height;
497 GLint i, j;
498 for (i = 0; i < h; i++) {
499 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
500 for (j = 0; j < w; j++) {
501 ptr3->r = r;
502 ptr3->g = g;
503 ptr3->b = b;
504 ptr3++;
505 }
506 }
507 #if 0 /* this code doesn't work for all window widths */
508 register GLuint *ptr4 = (GLuint *) ptr3;
509 register GLuint px;
510 GLuint pixel4[3];
511 register GLuint *p = pixel4;
512 pixel4[0] = clearPixel | (clearPixel << 24);
513 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
514 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
515 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
516 case 0:
517 break;
518 case 1:
519 px = *ptr4 & 0x00ffffff;
520 px |= pixel4[0] & 0xff000000;
521 *ptr4++ = px;
522 px = *ptr4 & 0xffff0000;
523 px |= pixel4[2] & 0x0000ffff;
524 *ptr4 = px;
525 if (0 == --n)
526 break;
527 case 2:
528 px = *ptr4 & 0x0000fffff;
529 px |= pixel4[1] & 0xffff0000;
530 *ptr4++ = px;
531 px = *ptr4 & 0xffffff00;
532 px |= pixel4[2] & 0x000000ff;
533 *ptr4 = px;
534 if (0 == --n)
535 break;
536 case 3:
537 px = *ptr4 & 0x000000ff;
538 px |= pixel4[2] & 0xffffff00;
539 *ptr4++ = px;
540 --n;
541 break;
542 }
543 while (n > 3) {
544 p = pixel4;
545 *ptr4++ = *p++;
546 *ptr4++ = *p++;
547 *ptr4++ = *p++;
548 n -= 4;
549 }
550 switch (n) {
551 case 3:
552 p = pixel4;
553 *ptr4++ = *p++;
554 *ptr4++ = *p++;
555 px = *ptr4 & 0xffffff00;
556 px |= clearPixel & 0xff;
557 *ptr4 = px;
558 break;
559 case 2:
560 p = pixel4;
561 *ptr4++ = *p++;
562 px = *ptr4 & 0xffff0000;
563 px |= *p & 0xffff;
564 *ptr4 = px;
565 break;
566 case 1:
567 px = *ptr4 & 0xff000000;
568 px |= *p & 0xffffff;
569 *ptr4 = px;
570 break;
571 case 0:
572 break;
573 }
574 #endif
575 }
576 }
577 else {
578 /* only clear subrect of color buffer */
579 if (r==g && g==b) {
580 /* same value for all three components (gray) */
581 GLint j;
582 for (j=0;j<height;j++) {
583 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
584 MEMSET(ptr3, r, 3 * width);
585 }
586 }
587 else {
588 /* non-gray clear color */
589 GLint i, j;
590 for (j = 0; j < height; j++) {
591 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
592 for (i = 0; i < width; i++) {
593 ptr3->r = r;
594 ptr3->g = g;
595 ptr3->b = b;
596 ptr3++;
597 }
598 }
599 #if 0 /* this code might not always (seems ptr3 always == ptr4) */
600 GLint j;
601 GLuint pixel4[3];
602 pixel4[0] = clearPixel | (clearPixel << 24);
603 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
604 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
605 for (j=0;j<height;j++) {
606 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
607 register GLuint *ptr4 = (GLuint *)ptr3;
608 register GLuint *p, px;
609 GLuint w = width;
610 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
611 case 0:
612 break;
613 case 1:
614 px = *ptr4 & 0x00ffffff;
615 px |= pixel4[0] & 0xff000000;
616 *ptr4++ = px;
617 px = *ptr4 & 0xffff0000;
618 px |= pixel4[2] & 0x0000ffff;
619 *ptr4 = px;
620 if (0 == --w)
621 break;
622 case 2:
623 px = *ptr4 & 0x0000fffff;
624 px |= pixel4[1] & 0xffff0000;
625 *ptr4++ = px;
626 px = *ptr4 & 0xffffff00;
627 px |= pixel4[2] & 0x000000ff;
628 *ptr4 = px;
629 if (0 == --w)
630 break;
631 case 3:
632 px = *ptr4 & 0x000000ff;
633 px |= pixel4[2] & 0xffffff00;
634 *ptr4++ = px;
635 --w;
636 break;
637 }
638 while (w > 3){
639 p = pixel4;
640 *ptr4++ = *p++;
641 *ptr4++ = *p++;
642 *ptr4++ = *p++;
643 w -= 4;
644 }
645 switch (w) {
646 case 3:
647 p = pixel4;
648 *ptr4++ = *p++;
649 *ptr4++ = *p++;
650 px = *ptr4 & 0xffffff00;
651 px |= *p & 0xff;
652 *ptr4 = px;
653 break;
654 case 2:
655 p = pixel4;
656 *ptr4++ = *p++;
657 px = *ptr4 & 0xffff0000;
658 px |= *p & 0xffff;
659 *ptr4 = px;
660 break;
661 case 1:
662 px = *ptr4 & 0xff000000;
663 px |= pixel4[0] & 0xffffff;
664 *ptr4 = px;
665 break;
666 case 0:
667 break;
668 }
669 }
670 #endif
671 }
672 }
673 }
674
675
676 static void
677 clear_32bit_ximage( GLcontext *ctx, GLboolean all,
678 GLint x, GLint y, GLint width, GLint height )
679 {
680 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
681 if (all) {
682 register GLint n = xmesa->xm_buffer->width * xmesa->xm_buffer->height;
683 register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
684 register GLuint pixel = (GLuint) xmesa->clearpixel;
685 if (xmesa->swapbytes) {
686 pixel = ((pixel >> 24) & 0x000000ff)
687 | ((pixel >> 8) & 0x0000ff00)
688 | ((pixel << 8) & 0x00ff0000)
689 | ((pixel << 24) & 0xff000000);
690 }
691 if (pixel==0) {
692 MEMSET( ptr4, pixel, 4*n );
693 }
694 else {
695 do {
696 *ptr4++ = pixel;
697 n--;
698 } while (n!=0);
699 }
700 }
701 else {
702 register int i, j;
703 register GLuint pixel = (GLuint) xmesa->clearpixel;
704 for (j=0;j<height;j++) {
705 register GLuint *ptr4 = PIXELADDR4( xmesa->xm_buffer, x, y+j );
706 for (i=0;i<width;i++) {
707 *ptr4++ = pixel;
708 }
709 }
710 }
711 }
712
713
714 static void
715 clear_nbit_ximage( GLcontext *ctx, GLboolean all,
716 GLint x, GLint y, GLint width, GLint height )
717 {
718 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
719 XMesaImage *img = xmesa->xm_buffer->backimage;
720 if (all) {
721 register int i, j;
722 width = xmesa->xm_buffer->width;
723 height = xmesa->xm_buffer->height;
724 for (j=0;j<height;j++) {
725 for (i=0;i<width;i++) {
726 XMesaPutPixel( img, i, j, xmesa->clearpixel );
727 }
728 }
729 }
730 else {
731 /* TODO: optimize this */
732 register int i, j;
733 y = FLIP(xmesa->xm_buffer, y);
734 for (j=0;j<height;j++) {
735 for (i=0;i<width;i++) {
736 XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
737 }
738 }
739 }
740 }
741
742
743
744 static void
745 clear_buffers( GLcontext *ctx, GLbitfield mask,
746 GLboolean all, GLint x, GLint y, GLint width, GLint height )
747 {
748 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
749 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
750
751 /* we can't handle color or index masking */
752 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
753 if (mask & DD_FRONT_LEFT_BIT) {
754 ASSERT(xmesa->xm_buffer->front_clear_func);
755 (*xmesa->xm_buffer->front_clear_func)( ctx, all, x, y, width, height );
756 mask &= ~DD_FRONT_LEFT_BIT;
757 }
758 if (mask & DD_BACK_LEFT_BIT) {
759 ASSERT(xmesa->xm_buffer->back_clear_func);
760 (*xmesa->xm_buffer->back_clear_func)( ctx, all, x, y, width, height );
761 mask &= ~DD_BACK_LEFT_BIT;
762 }
763 }
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 /* Software texture functions:
961 */
962 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
963 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
964 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
965 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
966 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
967 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
968 ctx->Driver.CopyTexImage1D = _mesa_copy_teximage1d;
969 ctx->Driver.CopyTexImage2D = _mesa_copy_teximage2d;
970 ctx->Driver.CopyTexSubImage1D = _mesa_copy_texsubimage1d;
971 ctx->Driver.CopyTexSubImage2D = _mesa_copy_texsubimage2d;
972 ctx->Driver.CopyTexSubImage3D = _mesa_copy_texsubimage3d;
973 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
974
975 /*
976 */
977 ctx->Driver.SetDrawBuffer = set_draw_buffer;
978 ctx->Driver.SetReadBuffer = set_read_buffer;
979 ctx->Driver.ClearIndex = clear_index;
980 ctx->Driver.ClearColor = clear_color;
981 ctx->Driver.IndexMask = index_mask;
982 ctx->Driver.ColorMask = color_mask;
983 ctx->Driver.Enable = enable;
984
985 (void) DitherValues; /* silenced unused var warning */
986 }