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