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