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