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