don't use new glDrawPixel routines in Xserver
[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 pixmap */
141 target->buffer = (XMesaDrawable) target->backpixmap;
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 #if 0 /* See below */
417 register GLuint clearPixel;
418 if (xmesa->swapbytes) {
419 clearPixel = (b << 16) | (g << 8) | r;
420 }
421 else {
422 clearPixel = (r << 16) | (g << 8) | b;
423 }
424 #endif
425
426 if (all) {
427 if (r==g && g==b) {
428 /* same value for all three components (gray) */
429 const GLint w3 = xmesa->xm_draw_buffer->width * 3;
430 const GLint h = xmesa->xm_draw_buffer->height;
431 GLint i;
432 for (i = 0; i < h; i++) {
433 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
434 MEMSET(ptr3, r, w3);
435 }
436 }
437 else {
438 /* the usual case */
439 const GLint w = xmesa->xm_draw_buffer->width;
440 const GLint h = xmesa->xm_draw_buffer->height;
441 GLint i, j;
442 for (i = 0; i < h; i++) {
443 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
444 for (j = 0; j < w; j++) {
445 ptr3->r = r;
446 ptr3->g = g;
447 ptr3->b = b;
448 ptr3++;
449 }
450 }
451 #if 0 /* this code doesn't work for all window widths */
452 register GLuint *ptr4 = (GLuint *) ptr3;
453 register GLuint px;
454 GLuint pixel4[3];
455 register GLuint *p = pixel4;
456 pixel4[0] = clearPixel | (clearPixel << 24);
457 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
458 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
459 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
460 case 0:
461 break;
462 case 1:
463 px = *ptr4 & 0x00ffffff;
464 px |= pixel4[0] & 0xff000000;
465 *ptr4++ = px;
466 px = *ptr4 & 0xffff0000;
467 px |= pixel4[2] & 0x0000ffff;
468 *ptr4 = px;
469 if (0 == --n)
470 break;
471 case 2:
472 px = *ptr4 & 0x0000fffff;
473 px |= pixel4[1] & 0xffff0000;
474 *ptr4++ = px;
475 px = *ptr4 & 0xffffff00;
476 px |= pixel4[2] & 0x000000ff;
477 *ptr4 = px;
478 if (0 == --n)
479 break;
480 case 3:
481 px = *ptr4 & 0x000000ff;
482 px |= pixel4[2] & 0xffffff00;
483 *ptr4++ = px;
484 --n;
485 break;
486 }
487 while (n > 3) {
488 p = pixel4;
489 *ptr4++ = *p++;
490 *ptr4++ = *p++;
491 *ptr4++ = *p++;
492 n -= 4;
493 }
494 switch (n) {
495 case 3:
496 p = pixel4;
497 *ptr4++ = *p++;
498 *ptr4++ = *p++;
499 px = *ptr4 & 0xffffff00;
500 px |= clearPixel & 0xff;
501 *ptr4 = px;
502 break;
503 case 2:
504 p = pixel4;
505 *ptr4++ = *p++;
506 px = *ptr4 & 0xffff0000;
507 px |= *p & 0xffff;
508 *ptr4 = px;
509 break;
510 case 1:
511 px = *ptr4 & 0xff000000;
512 px |= *p & 0xffffff;
513 *ptr4 = px;
514 break;
515 case 0:
516 break;
517 }
518 #endif
519 }
520 }
521 else {
522 /* only clear subrect of color buffer */
523 if (r==g && g==b) {
524 /* same value for all three components (gray) */
525 GLint j;
526 for (j=0;j<height;j++) {
527 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
528 MEMSET(ptr3, r, 3 * width);
529 }
530 }
531 else {
532 /* non-gray clear color */
533 GLint i, j;
534 for (j = 0; j < height; j++) {
535 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
536 for (i = 0; i < width; i++) {
537 ptr3->r = r;
538 ptr3->g = g;
539 ptr3->b = b;
540 ptr3++;
541 }
542 }
543 #if 0 /* this code might not always (seems ptr3 always == ptr4) */
544 GLint j;
545 GLuint pixel4[3];
546 pixel4[0] = clearPixel | (clearPixel << 24);
547 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
548 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
549 for (j=0;j<height;j++) {
550 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
551 register GLuint *ptr4 = (GLuint *)ptr3;
552 register GLuint *p, px;
553 GLuint w = width;
554 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
555 case 0:
556 break;
557 case 1:
558 px = *ptr4 & 0x00ffffff;
559 px |= pixel4[0] & 0xff000000;
560 *ptr4++ = px;
561 px = *ptr4 & 0xffff0000;
562 px |= pixel4[2] & 0x0000ffff;
563 *ptr4 = px;
564 if (0 == --w)
565 break;
566 case 2:
567 px = *ptr4 & 0x0000fffff;
568 px |= pixel4[1] & 0xffff0000;
569 *ptr4++ = px;
570 px = *ptr4 & 0xffffff00;
571 px |= pixel4[2] & 0x000000ff;
572 *ptr4 = px;
573 if (0 == --w)
574 break;
575 case 3:
576 px = *ptr4 & 0x000000ff;
577 px |= pixel4[2] & 0xffffff00;
578 *ptr4++ = px;
579 --w;
580 break;
581 }
582 while (w > 3){
583 p = pixel4;
584 *ptr4++ = *p++;
585 *ptr4++ = *p++;
586 *ptr4++ = *p++;
587 w -= 4;
588 }
589 switch (w) {
590 case 3:
591 p = pixel4;
592 *ptr4++ = *p++;
593 *ptr4++ = *p++;
594 px = *ptr4 & 0xffffff00;
595 px |= *p & 0xff;
596 *ptr4 = px;
597 break;
598 case 2:
599 p = pixel4;
600 *ptr4++ = *p++;
601 px = *ptr4 & 0xffff0000;
602 px |= *p & 0xffff;
603 *ptr4 = px;
604 break;
605 case 1:
606 px = *ptr4 & 0xff000000;
607 px |= pixel4[0] & 0xffffff;
608 *ptr4 = px;
609 break;
610 case 0:
611 break;
612 }
613 }
614 #endif
615 }
616 }
617 }
618
619
620 static void
621 clear_32bit_ximage( GLcontext *ctx, GLboolean all,
622 GLint x, GLint y, GLint width, GLint height )
623 {
624 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
625 register GLuint pixel = (GLuint) xmesa->clearpixel;
626 if (xmesa->swapbytes) {
627 pixel = ((pixel >> 24) & 0x000000ff)
628 | ((pixel >> 8) & 0x0000ff00)
629 | ((pixel << 8) & 0x00ff0000)
630 | ((pixel << 24) & 0xff000000);
631 }
632 if (all) {
633 register GLint n = xmesa->xm_draw_buffer->width * xmesa->xm_draw_buffer->height;
634 register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
635 if (pixel==0) {
636 MEMSET( ptr4, pixel, 4*n );
637 }
638 else {
639 do {
640 *ptr4++ = pixel;
641 n--;
642 } while (n!=0);
643 }
644 }
645 else {
646 register int i, j;
647 for (j=0;j<height;j++) {
648 register GLuint *ptr4 = PIXELADDR4( xmesa->xm_draw_buffer, x, y+j );
649 for (i=0;i<width;i++) {
650 *ptr4++ = pixel;
651 }
652 }
653 }
654 }
655
656
657 static void
658 clear_nbit_ximage( GLcontext *ctx, GLboolean all,
659 GLint x, GLint y, GLint width, GLint height )
660 {
661 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
662 XMesaImage *img = xmesa->xm_draw_buffer->backimage;
663 if (all) {
664 register int i, j;
665 width = xmesa->xm_draw_buffer->width;
666 height = xmesa->xm_draw_buffer->height;
667 for (j=0;j<height;j++) {
668 for (i=0;i<width;i++) {
669 XMesaPutPixel( img, i, j, xmesa->clearpixel );
670 }
671 }
672 }
673 else {
674 /* TODO: optimize this */
675 register int i, j;
676 y = FLIP(xmesa->xm_draw_buffer, y);
677 for (j=0;j<height;j++) {
678 for (i=0;i<width;i++) {
679 XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
680 }
681 }
682 }
683 }
684
685
686
687 static void
688 clear_buffers( GLcontext *ctx, GLbitfield mask,
689 GLboolean all, GLint x, GLint y, GLint width, GLint height )
690 {
691 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
692 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
693
694 if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) &&
695 xmesa->xm_draw_buffer->mesa_buffer.UseSoftwareAlphaBuffers &&
696 ctx->Color.ColorMask[ACOMP]) {
697 _swrast_clear_alpha_buffers(ctx);
698 }
699
700 /* we can't handle color or index masking */
701 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
702 if (mask & DD_FRONT_LEFT_BIT) {
703 ASSERT(xmesa->xm_draw_buffer->front_clear_func);
704 (*xmesa->xm_draw_buffer->front_clear_func)( ctx, all, x, y, width, height );
705 mask &= ~DD_FRONT_LEFT_BIT;
706 }
707 if (mask & DD_BACK_LEFT_BIT) {
708 ASSERT(xmesa->xm_draw_buffer->back_clear_func);
709 (*xmesa->xm_draw_buffer->back_clear_func)( ctx, all, x, y, width, height );
710 mask &= ~DD_BACK_LEFT_BIT;
711 }
712 }
713
714 if (mask)
715 _swrast_Clear( ctx, mask, all, x, y, width, height );
716 }
717
718
719 /*
720 * When we detect that the user has resized the window this function will
721 * get called. Here we'll reallocate the back buffer, depth buffer,
722 * stencil buffer etc. to match the new window size.
723 */
724 void
725 xmesa_resize_buffers( GLframebuffer *buffer )
726 {
727 int height = (int) buffer->Height;
728 /* We can do this cast because the first field in the XMesaBuffer
729 * struct is a GLframebuffer struct. If this weren't true, we'd
730 * need a pointer from the GLframebuffer to the XMesaBuffer.
731 */
732 XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
733
734 xmBuffer->width = buffer->Width;
735 xmBuffer->height = buffer->Height;
736 xmesa_alloc_back_buffer( xmBuffer );
737
738 /* Needed by FLIP macro */
739 xmBuffer->bottom = height - 1;
740
741 if (xmBuffer->backimage) {
742 /* Needed by PIXELADDR1 macro */
743 xmBuffer->ximage_width1 = xmBuffer->backimage->bytes_per_line;
744 xmBuffer->ximage_origin1 = (GLubyte *) xmBuffer->backimage->data
745 + xmBuffer->ximage_width1 * (height-1);
746
747 /* Needed by PIXELADDR2 macro */
748 xmBuffer->ximage_width2 = xmBuffer->backimage->bytes_per_line / 2;
749 xmBuffer->ximage_origin2 = (GLushort *) xmBuffer->backimage->data
750 + xmBuffer->ximage_width2 * (height-1);
751
752 /* Needed by PIXELADDR3 macro */
753 xmBuffer->ximage_width3 = xmBuffer->backimage->bytes_per_line;
754 xmBuffer->ximage_origin3 = (GLubyte *) xmBuffer->backimage->data
755 + xmBuffer->ximage_width3 * (height-1);
756
757 /* Needed by PIXELADDR4 macro */
758 xmBuffer->ximage_width4 = xmBuffer->backimage->width;
759 xmBuffer->ximage_origin4 = (GLuint *) xmBuffer->backimage->data
760 + xmBuffer->ximage_width4 * (height-1);
761 }
762
763 _swrast_alloc_buffers( buffer );
764 }
765
766
767 #ifndef XFree86Server
768 /* XXX this was never tested in the Xserver environment */
769
770 /**
771 * This function implements glDrawPixels() with an XPutImage call when
772 * drawing to the front buffer (X Window drawable).
773 * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
774 */
775 static void
776 xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
777 GLint x, GLint y, GLsizei width, GLsizei height,
778 GLenum format, GLenum type,
779 const struct gl_pixelstore_attrib *unpack,
780 const GLvoid *pixels )
781 {
782 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
783 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
784 XMesaDisplay *dpy = xmesa->xm_visual->display;
785 const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
786 const XMesaGC gc = xmesa->xm_draw_buffer->gc;
787
788 ASSERT(dpy);
789 ASSERT(gc);
790 ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
791 ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
792
793 if (buffer && /* buffer != 0 means it's a Window or Pixmap */
794 format == GL_BGRA &&
795 type == GL_UNSIGNED_BYTE &&
796 (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
797 ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
798 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
799 ctx->Pixel.ZoomY == 1.0) {
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 int rowLength = unpack->RowLength ? unpack->RowLength : width;
807 if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
808 /* This is a little tricky since all coordinates up to now have
809 * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
810 * so we have to carefully compute the Y coordinates/addresses here.
811 */
812 XMesaImage ximage;
813 MEMSET(&ximage, 0, sizeof(XMesaImage));
814 ximage.width = width;
815 ximage.height = height;
816 ximage.format = ZPixmap;
817 ximage.data = (char *) pixels
818 + ((srcY + h - 1) * rowLength + srcX) * 4;
819 ximage.byte_order = LSBFirst;
820 ximage.bitmap_unit = 32;
821 ximage.bitmap_bit_order = LSBFirst;
822 ximage.bitmap_pad = 32;
823 ximage.depth = 24;
824 ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
825 ximage.bits_per_pixel = 32;
826 /* it seems we don't need to set the ximage.red/green/blue_mask fields */
827 /* flip Y axis for dest position */
828 dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
829 XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
830 }
831 }
832 else {
833 /* software fallback */
834 _swrast_DrawPixels(ctx, x, y, width, height,
835 format, type, unpack, pixels);
836 }
837 }
838
839
840
841 /**
842 * This function implements glDrawPixels() with an XPutImage call when
843 * drawing to the front buffer (X Window drawable). The image format
844 * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
845 * match the PF_5R6G5B pixel format.
846 */
847 static void
848 xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
849 GLint x, GLint y, GLsizei width, GLsizei height,
850 GLenum format, GLenum type,
851 const struct gl_pixelstore_attrib *unpack,
852 const GLvoid *pixels )
853 {
854 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
855 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
856 XMesaDisplay *dpy = xmesa->xm_visual->display;
857 const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
858 const XMesaGC gc = xmesa->xm_draw_buffer->gc;
859
860 ASSERT(dpy);
861 ASSERT(gc);
862 ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
863
864 if (buffer && /* buffer != 0 means it's a Window or Pixmap */
865 format == GL_RGB &&
866 type == GL_UNSIGNED_SHORT_5_6_5 &&
867 !ctx->Color.DitherFlag && /* no dithering */
868 (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
869 ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
870 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
871 ctx->Pixel.ZoomY == 1.0) {
872 int dstX = x;
873 int dstY = y;
874 int w = width;
875 int h = height;
876 int srcX = unpack->SkipPixels;
877 int srcY = unpack->SkipRows;
878 int rowLength = unpack->RowLength ? unpack->RowLength : width;
879 if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
880 /* This is a little tricky since all coordinates up to now have
881 * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
882 * so we have to carefully compute the Y coordinates/addresses here.
883 */
884 XMesaImage ximage;
885 MEMSET(&ximage, 0, sizeof(XMesaImage));
886 ximage.width = width;
887 ximage.height = height;
888 ximage.format = ZPixmap;
889 ximage.data = (char *) pixels
890 + ((srcY + h - 1) * rowLength + srcX) * 2;
891 ximage.byte_order = LSBFirst;
892 ximage.bitmap_unit = 16;
893 ximage.bitmap_bit_order = LSBFirst;
894 ximage.bitmap_pad = 16;
895 ximage.depth = 16;
896 ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
897 ximage.bits_per_pixel = 16;
898 /* it seems we don't need to set the ximage.red/green/blue_mask fields */
899 /* flip Y axis for dest position */
900 dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
901 XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
902 }
903 }
904 else {
905 /* software fallback */
906 _swrast_DrawPixels(ctx, x, y, width, height,
907 format, type, unpack, pixels);
908 }
909 }
910 #endif /* XFree86Server */
911
912
913
914 /**
915 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
916 * for the color buffer. Don't support zooming, pixel transfer, etc.
917 * We do support copying from one window to another, ala glXMakeCurrentRead.
918 */
919 static void
920 xmesa_CopyPixels( GLcontext *ctx,
921 GLint srcx, GLint srcy, GLsizei width, GLsizei height,
922 GLint destx, GLint desty, GLenum type )
923 {
924 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
925 const SWcontext *swrast = SWRAST_CONTEXT( ctx );
926 XMesaDisplay *dpy = xmesa->xm_visual->display;
927 const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
928 const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
929 const XMesaGC gc = xmesa->xm_draw_buffer->gc;
930
931 ASSERT(dpy);
932 ASSERT(gc);
933
934 if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
935 readBuffer &&
936 type == GL_COLOR &&
937 (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
938 ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
939 ctx->Pixel.ZoomX == 1.0 && /* no zooming */
940 ctx->Pixel.ZoomY == 1.0) {
941 /* Note: we don't do any special clipping work here. We could,
942 * but X will do it for us.
943 */
944 srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
945 desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
946 XCopyArea(dpy, readBuffer, drawBuffer, gc,
947 srcx, srcy, width, height, destx, desty);
948 }
949 else {
950 _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
951 }
952 }
953
954
955
956 /*
957 * Every driver should implement a GetString function in order to
958 * return a meaningful GL_RENDERER string.
959 */
960 static const GLubyte *
961 get_string( GLcontext *ctx, GLenum name )
962 {
963 (void) ctx;
964 switch (name) {
965 case GL_RENDERER:
966 #ifdef XFree86Server
967 return (const GLubyte *) "Mesa GLX Indirect";
968 #else
969 return (const GLubyte *) "Mesa X11";
970 #endif
971 case GL_VENDOR:
972 #ifdef XFree86Server
973 return (const GLubyte *) "Mesa project: www.mesa3d.org";
974 #else
975 return NULL;
976 #endif
977 default:
978 return NULL;
979 }
980 }
981
982
983 /*
984 * We implement the glEnable function only because we care about
985 * dither enable/disable.
986 */
987 static void
988 enable( GLcontext *ctx, GLenum pname, GLboolean state )
989 {
990 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
991
992 switch (pname) {
993 case GL_DITHER:
994 if (state)
995 xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
996 else
997 xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
998 break;
999 default:
1000 ; /* silence compiler warning */
1001 }
1002 }
1003
1004
1005 void xmesa_update_state( GLcontext *ctx, GLuint new_state )
1006 {
1007 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
1008
1009 /* Propogate statechange information to swrast and swrast_setup
1010 * modules. The X11 driver has no internal GL-dependent state.
1011 */
1012 _swrast_InvalidateState( ctx, new_state );
1013 _ac_InvalidateState( ctx, new_state );
1014 _tnl_InvalidateState( ctx, new_state );
1015 _swsetup_InvalidateState( ctx, new_state );
1016
1017
1018 /* setup pointers to front and back buffer clear functions */
1019 xmesa->xm_draw_buffer->front_clear_func = clear_front_pixmap;
1020 if (xmesa->xm_draw_buffer->backpixmap != XIMAGE) {
1021 xmesa->xm_draw_buffer->back_clear_func = clear_back_pixmap;
1022 }
1023 else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
1024 xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
1025 }
1026 else switch (xmesa->xm_visual->BitsPerPixel) {
1027 case 8:
1028 if (xmesa->xm_visual->hpcr_clear_flag) {
1029 xmesa->xm_draw_buffer->back_clear_func = clear_HPCR_ximage;
1030 }
1031 else {
1032 xmesa->xm_draw_buffer->back_clear_func = clear_8bit_ximage;
1033 }
1034 break;
1035 case 16:
1036 xmesa->xm_draw_buffer->back_clear_func = clear_16bit_ximage;
1037 break;
1038 case 24:
1039 xmesa->xm_draw_buffer->back_clear_func = clear_24bit_ximage;
1040 break;
1041 case 32:
1042 xmesa->xm_draw_buffer->back_clear_func = clear_32bit_ximage;
1043 break;
1044 default:
1045 xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
1046 break;
1047 }
1048
1049 xmesa_update_span_funcs(ctx);
1050 }
1051
1052
1053
1054 /**
1055 * Called via ctx->Driver.TestProxyTeximage(). Normally, we'd just use
1056 * the _mesa_test_proxy_teximage() fallback function, but we're going to
1057 * special-case the 3D texture case to allow textures up to 512x512x32
1058 * texels.
1059 */
1060 static GLboolean
1061 test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1062 GLint internalFormat, GLenum format, GLenum type,
1063 GLint width, GLint height, GLint depth, GLint border)
1064 {
1065 if (target == GL_PROXY_TEXTURE_3D) {
1066 /* special case for 3D textures */
1067 if (width * height * depth > 512 * 512 * 64 ||
1068 width < 2 * border ||
1069 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1070 _mesa_bitcount(width - 2 * border) != 1) ||
1071 height < 2 * border ||
1072 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1073 _mesa_bitcount(height - 2 * border) != 1) ||
1074 depth < 2 * border ||
1075 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1076 _mesa_bitcount(depth - 2 * border) != 1)) {
1077 /* Bad size, or too many texels */
1078 return GL_FALSE;
1079 }
1080 return GL_TRUE;
1081 }
1082 else {
1083 /* use the fallback routine for 1D, 2D, cube and rect targets */
1084 return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
1085 format, type, width, height, depth,
1086 border);
1087 }
1088 }
1089
1090
1091
1092
1093 /* Setup pointers and other driver state that is constant for the life
1094 * of a context.
1095 */
1096 void xmesa_init_pointers( GLcontext *ctx )
1097 {
1098 TNLcontext *tnl;
1099 struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference( ctx );
1100 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
1101
1102 /* Plug in our driver-specific functions here */
1103 ctx->Driver.GetString = get_string;
1104 ctx->Driver.GetBufferSize = get_buffer_size;
1105 ctx->Driver.Flush = finish_or_flush;
1106 ctx->Driver.Finish = finish_or_flush;
1107 ctx->Driver.ClearIndex = clear_index;
1108 ctx->Driver.ClearColor = clear_color;
1109 ctx->Driver.IndexMask = index_mask;
1110 ctx->Driver.ColorMask = color_mask;
1111 ctx->Driver.Enable = enable;
1112
1113 /* Software rasterizer pixel paths:
1114 */
1115 ctx->Driver.Accum = _swrast_Accum;
1116 ctx->Driver.Bitmap = _swrast_Bitmap;
1117 ctx->Driver.Clear = clear_buffers;
1118 ctx->Driver.ResizeBuffers = xmesa_resize_buffers;
1119 ctx->Driver.CopyPixels = xmesa_CopyPixels;
1120 #ifdef XFree86Server
1121 ctx->Driver.DrawPixels = _swrast_DrawPixels;
1122 #else
1123 if (xmesa->xm_visual->undithered_pf == PF_8R8G8B &&
1124 xmesa->xm_visual->dithered_pf == PF_8R8G8B) {
1125 ctx->Driver.DrawPixels = xmesa_DrawPixels_8R8G8B;
1126 }
1127 else if (xmesa->xm_visual->undithered_pf == PF_5R6G5B) {
1128 ctx->Driver.DrawPixels = xmesa_DrawPixels_5R6G5B;
1129 }
1130 else {
1131 ctx->Driver.DrawPixels = _swrast_DrawPixels;
1132 }
1133 #endif
1134 ctx->Driver.ReadPixels = _swrast_ReadPixels;
1135 ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
1136
1137 /* Software texture functions:
1138 */
1139 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
1140 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
1141 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
1142 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
1143 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
1144 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
1145 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
1146 ctx->Driver.TestProxyTexImage = test_proxy_teximage;
1147
1148 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
1149 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
1150 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
1151 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
1152 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
1153
1154 ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
1155 ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
1156 ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
1157 ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
1158 ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
1159 ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
1160
1161 /* Swrast hooks for imaging extensions:
1162 */
1163 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1164 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1165 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1166 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1167
1168 /* Initialize the TNL driver interface:
1169 */
1170 tnl = TNL_CONTEXT(ctx);
1171 tnl->Driver.RunPipeline = _tnl_run_pipeline;
1172
1173 dd->SetBuffer = set_buffer;
1174
1175 /* Install swsetup for tnl->Driver.Render.*:
1176 */
1177 _swsetup_Wakeup(ctx);
1178
1179 (void) DitherValues; /* silenced unused var warning */
1180 }
1181
1182
1183
1184
1185
1186 #define XMESA_NEW_POINT (_NEW_POINT | \
1187 _NEW_RENDERMODE | \
1188 _SWRAST_NEW_RASTERMASK)
1189
1190 #define XMESA_NEW_LINE (_NEW_LINE | \
1191 _NEW_TEXTURE | \
1192 _NEW_LIGHT | \
1193 _NEW_DEPTH | \
1194 _NEW_RENDERMODE | \
1195 _SWRAST_NEW_RASTERMASK)
1196
1197 #define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1198 _NEW_TEXTURE | \
1199 _NEW_LIGHT | \
1200 _NEW_DEPTH | \
1201 _NEW_RENDERMODE | \
1202 _SWRAST_NEW_RASTERMASK)
1203
1204
1205 /* Extend the software rasterizer with our line/point/triangle
1206 * functions.
1207 */
1208 void xmesa_register_swrast_functions( GLcontext *ctx )
1209 {
1210 SWcontext *swrast = SWRAST_CONTEXT( ctx );
1211
1212 swrast->choose_point = xmesa_choose_point;
1213 swrast->choose_line = xmesa_choose_line;
1214 swrast->choose_triangle = xmesa_choose_triangle;
1215
1216 swrast->invalidate_point |= XMESA_NEW_POINT;
1217 swrast->invalidate_line |= XMESA_NEW_LINE;
1218 swrast->invalidate_triangle |= XMESA_NEW_TRIANGLE;
1219 }