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