xm_dd.c revision d98fdad3bfc7018740cf781e00fa53ad9a4479cd
1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/* $Id: xm_dd.c,v 1.13 2001/01/29 20:56:32 keithw Exp $ */ 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/* 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Mesa 3-D graphics library 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Version: 3.5 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Permission is hereby granted, free of charge, to any person obtaining a 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * copy of this software and associated documentation files (the "Software"), 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * to deal in the Software without restriction, including without limitation 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * and/or sell copies of the Software, and to permit persons to whom the 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Software is furnished to do so, subject to the following conditions: 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * The above copyright notice and this permission notice shall be included 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * in all copies or substantial portions of the Software. 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28#include "glxheader.h" 29#include "context.h" 30#include "drawpix.h" 31#include "mem.h" 32#include "state.h" 33#include "depth.h" 34#include "macros.h" 35#include "mtypes.h" 36#include "xmesaP.h" 37#include "extensions.h" 38#include "swrast/swrast.h" 39#include "swrast_setup/swrast_setup.h" 40#include "tnl/tnl.h" 41#include "array_cache/acache.h" 42 43/* 44 * Return the size (width,height of the current color buffer. 45 * This function should be called by the glViewport function because 46 * glViewport is often called when the window gets resized. We need to 47 * update some X/Mesa stuff when that happens. 48 * Output: width - width of buffer in pixels. 49 * height - height of buffer in pixels. 50 */ 51static void 52get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) 53{ 54 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 55 unsigned int winwidth, winheight; 56#ifndef XFree86Server 57 Window root; 58 int winx, winy; 59 unsigned int bw, d; 60 61 _glthread_LOCK_MUTEX(_xmesa_lock); 62 XGetGeometry( xmesa->display, xmesa->xm_buffer->frontbuffer, &root, 63 &winx, &winy, &winwidth, &winheight, &bw, &d ); 64 _glthread_UNLOCK_MUTEX(_xmesa_lock); 65#else 66 67 winwidth = xmesa->xm_buffer->frontbuffer->width; 68 winheight = xmesa->xm_buffer->frontbuffer->height; 69#endif 70 71 *width = winwidth; 72 *height = winheight; 73 74 if ( winwidth!=xmesa->xm_buffer->width 75 || winheight!=xmesa->xm_buffer->height) { 76 xmesa->xm_buffer->width = winwidth; 77 xmesa->xm_buffer->height = winheight; 78 xmesa_alloc_back_buffer( xmesa->xm_buffer ); 79 } 80 81 /* Needed by FLIP macro */ 82 xmesa->xm_buffer->bottom = (int) winheight - 1; 83 84 if (xmesa->xm_buffer->backimage) { 85 /* Needed by PIXELADDR1 macro */ 86 xmesa->xm_buffer->ximage_width1 87 = xmesa->xm_buffer->backimage->bytes_per_line; 88 xmesa->xm_buffer->ximage_origin1 89 = (GLubyte *) xmesa->xm_buffer->backimage->data 90 + xmesa->xm_buffer->ximage_width1 * (winheight-1); 91 92 /* Needed by PIXELADDR2 macro */ 93 xmesa->xm_buffer->ximage_width2 94 = xmesa->xm_buffer->backimage->bytes_per_line / 2; 95 xmesa->xm_buffer->ximage_origin2 96 = (GLushort *) xmesa->xm_buffer->backimage->data 97 + xmesa->xm_buffer->ximage_width2 * (winheight-1); 98 99 /* Needed by PIXELADDR3 macro */ 100 xmesa->xm_buffer->ximage_width3 101 = xmesa->xm_buffer->backimage->bytes_per_line; 102 xmesa->xm_buffer->ximage_origin3 103 = (GLubyte *) xmesa->xm_buffer->backimage->data 104 + xmesa->xm_buffer->ximage_width3 * (winheight-1); 105 106 /* Needed by PIXELADDR4 macro */ 107 xmesa->xm_buffer->ximage_width4 = xmesa->xm_buffer->backimage->width; 108 xmesa->xm_buffer->ximage_origin4 109 = (GLuint *) xmesa->xm_buffer->backimage->data 110 + xmesa->xm_buffer->ximage_width4 * (winheight-1); 111 } 112} 113 114 115static void 116finish( GLcontext *ctx ) 117{ 118#ifdef XFree86Server 119 /* NOT_NEEDED */ 120#else 121 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 122 if (xmesa) { 123 _glthread_LOCK_MUTEX(_xmesa_lock); 124 XSync( xmesa->display, False ); 125 _glthread_UNLOCK_MUTEX(_xmesa_lock); 126 } 127#endif 128} 129 130 131static void 132flush( GLcontext *ctx ) 133{ 134#ifdef XFree86Server 135 /* NOT_NEEDED */ 136#else 137 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 138 if (xmesa) { 139 _glthread_LOCK_MUTEX(_xmesa_lock); 140 XFlush( xmesa->display ); 141 _glthread_UNLOCK_MUTEX(_xmesa_lock); 142 } 143#endif 144} 145 146 147 148 149static GLboolean 150set_draw_buffer( GLcontext *ctx, GLenum mode ) 151{ 152 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 153 if (mode == GL_FRONT_LEFT) { 154 /* write to front buffer */ 155 xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer; 156 xmesa_update_span_funcs(ctx); 157 return GL_TRUE; 158 } 159 else if (mode==GL_BACK_LEFT && xmesa->xm_buffer->db_state) { 160 /* write to back buffer */ 161 if (xmesa->xm_buffer->backpixmap) { 162 xmesa->xm_buffer->buffer = 163 (XMesaDrawable)xmesa->xm_buffer->backpixmap; 164 } 165 else if (xmesa->xm_buffer->backimage) { 166 xmesa->xm_buffer->buffer = None; 167 } 168 else { 169 /* just in case there wasn't enough memory for back buffer */ 170 xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer; 171 } 172 xmesa_update_span_funcs(ctx); 173 return GL_TRUE; 174 } 175 else { 176 return GL_FALSE; 177 } 178} 179 180 181static void 182set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode ) 183{ 184 XMesaBuffer target; 185 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 186 187 if (buffer == ctx->DrawBuffer) { 188 target = xmesa->xm_buffer; 189 xmesa->use_read_buffer = GL_FALSE; 190 } 191 else { 192 ASSERT(buffer == ctx->ReadBuffer); 193 target = xmesa->xm_read_buffer; 194 xmesa->use_read_buffer = GL_TRUE; 195 } 196 197 if (mode == GL_FRONT_LEFT) { 198 target->buffer = target->frontbuffer; 199 xmesa_update_span_funcs(ctx); 200 } 201 else if (mode==GL_BACK_LEFT && xmesa->xm_read_buffer->db_state) { 202 if (target->backpixmap) { 203 target->buffer = (XMesaDrawable)xmesa->xm_buffer->backpixmap; 204 } 205 else if (target->backimage) { 206 target->buffer = None; 207 } 208 else { 209 /* just in case there wasn't enough memory for back buffer */ 210 target->buffer = target->frontbuffer; 211 } 212 xmesa_update_span_funcs(ctx); 213 } 214 else { 215 gl_problem(ctx, "invalid buffer in set_read_buffer() in xmesa2.c"); 216 } 217} 218 219 220 221static void 222clear_index( GLcontext *ctx, GLuint index ) 223{ 224 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 225 xmesa->clearpixel = (unsigned long) index; 226 XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc, 227 (unsigned long) index ); 228} 229 230 231static void 232clear_color( GLcontext *ctx, const GLchan color[4] ) 233{ 234 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 235 xmesa->clearcolor[0] = color[0]; 236 xmesa->clearcolor[1] = color[1]; 237 xmesa->clearcolor[2] = color[2]; 238 xmesa->clearcolor[3] = color[3]; 239 xmesa->clearpixel = xmesa_color_to_pixel( xmesa, color[0], color[1], 240 color[2], color[3], 241 xmesa->xm_visual->undithered_pf ); 242 _glthread_LOCK_MUTEX(_xmesa_lock); 243 XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc, 244 xmesa->clearpixel ); 245 _glthread_UNLOCK_MUTEX(_xmesa_lock); 246} 247 248 249 250/* Set index mask ala glIndexMask */ 251static void 252index_mask( GLcontext *ctx, GLuint mask ) 253{ 254 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 255 if (xmesa->xm_buffer->buffer != XIMAGE) { 256 unsigned long m; 257 if (mask==0xffffffff) { 258 m = ((unsigned long)~0L); 259 } 260 else { 261 m = (unsigned long) mask; 262 } 263 XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m ); 264 } 265} 266 267 268/* Implements glColorMask() */ 269static void 270color_mask(GLcontext *ctx, 271 GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask) 272{ 273 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 274 int xclass = GET_VISUAL_CLASS(xmesa->xm_visual); 275 (void) amask; 276 277 if (xmesa->xm_buffer->buffer != XIMAGE 278 && (xclass == TrueColor || xclass == DirectColor)) { 279 unsigned long m; 280 if (rmask && gmask && bmask) { 281 m = ((unsigned long)~0L); 282 } 283 else { 284 m = 0; 285 if (rmask) m |= GET_REDMASK(xmesa->xm_visual); 286 if (gmask) m |= GET_GREENMASK(xmesa->xm_visual); 287 if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual); 288 } 289 XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m ); 290 } 291} 292 293 294 295/**********************************************************************/ 296/*** glClear implementations ***/ 297/**********************************************************************/ 298 299 300static void 301clear_front_pixmap( GLcontext *ctx, GLboolean all, 302 GLint x, GLint y, GLint width, GLint height ) 303{ 304 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 305 if (all) { 306 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer, 307 xmesa->xm_buffer->cleargc, 308 0, 0, 309 xmesa->xm_buffer->width+1, 310 xmesa->xm_buffer->height+1 ); 311 } 312 else { 313 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer, 314 xmesa->xm_buffer->cleargc, 315 x, xmesa->xm_buffer->height - y - height, 316 width, height ); 317 } 318} 319 320 321static void 322clear_back_pixmap( GLcontext *ctx, GLboolean all, 323 GLint x, GLint y, GLint width, GLint height ) 324{ 325 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 326 if (all) { 327 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap, 328 xmesa->xm_buffer->cleargc, 329 0, 0, 330 xmesa->xm_buffer->width+1, 331 xmesa->xm_buffer->height+1 ); 332 } 333 else { 334 XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap, 335 xmesa->xm_buffer->cleargc, 336 x, xmesa->xm_buffer->height - y - height, 337 width, height ); 338 } 339} 340 341 342static void 343clear_8bit_ximage( GLcontext *ctx, GLboolean all, 344 GLint x, GLint y, GLint width, GLint height ) 345{ 346 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 347 if (all) { 348 size_t n = xmesa->xm_buffer->backimage->bytes_per_line 349 * xmesa->xm_buffer->backimage->height; 350 MEMSET( xmesa->xm_buffer->backimage->data, xmesa->clearpixel, n ); 351 } 352 else { 353 GLint i; 354 for (i=0;i<height;i++) { 355 GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y+i ); 356 MEMSET( ptr, xmesa->clearpixel, width ); 357 } 358 } 359} 360 361 362static void 363clear_HPCR_ximage( GLcontext *ctx, GLboolean all, 364 GLint x, GLint y, GLint width, GLint height ) 365{ 366 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 367 if (all) { 368 GLint i, c16 = (xmesa->xm_buffer->backimage->bytes_per_line>>4)<<4; 369 GLubyte *ptr = (GLubyte *)xmesa->xm_buffer->backimage->data; 370 for (i=0; i<xmesa->xm_buffer->backimage->height; i++) { 371 GLint j; 372 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0]; 373 if (i&1) { 374 sptr += 16; 375 } 376 for (j=0; j<c16; j+=16) { 377 ptr[0] = sptr[0]; 378 ptr[1] = sptr[1]; 379 ptr[2] = sptr[2]; 380 ptr[3] = sptr[3]; 381 ptr[4] = sptr[4]; 382 ptr[5] = sptr[5]; 383 ptr[6] = sptr[6]; 384 ptr[7] = sptr[7]; 385 ptr[8] = sptr[8]; 386 ptr[9] = sptr[9]; 387 ptr[10] = sptr[10]; 388 ptr[11] = sptr[11]; 389 ptr[12] = sptr[12]; 390 ptr[13] = sptr[13]; 391 ptr[14] = sptr[14]; 392 ptr[15] = sptr[15]; 393 ptr += 16; 394 } 395 for (; j<xmesa->xm_buffer->backimage->bytes_per_line; j++) { 396 *ptr = sptr[j&15]; 397 ptr++; 398 } 399 } 400 } 401 else { 402 GLint i; 403 for (i=y; i<y+height; i++) { 404 GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, i ); 405 int j; 406 GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0]; 407 if (i&1) { 408 sptr += 16; 409 } 410 for (j=x; j<x+width; j++) { 411 *ptr = sptr[j&15]; 412 ptr++; 413 } 414 } 415 } 416} 417 418 419static void 420clear_16bit_ximage( GLcontext *ctx, GLboolean all, 421 GLint x, GLint y, GLint width, GLint height ) 422{ 423 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 424 register GLuint pixel = (GLuint) xmesa->clearpixel; 425 if (xmesa->swapbytes) { 426 pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00); 427 } 428 if (all) { 429 register GLuint n; 430 register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data; 431 if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) { 432 /* low and high bytes are equal so use memset() */ 433 n = xmesa->xm_buffer->backimage->bytes_per_line 434 * xmesa->xm_buffer->height; 435 MEMSET( ptr4, pixel & 0xff, n ); 436 } 437 else { 438 pixel = pixel | (pixel<<16); 439 n = xmesa->xm_buffer->backimage->bytes_per_line 440 * xmesa->xm_buffer->height / 4; 441 do { 442 *ptr4++ = pixel; 443 n--; 444 } while (n!=0); 445 446 if ((xmesa->xm_buffer->backimage->bytes_per_line * 447 xmesa->xm_buffer->height) & 0x2) 448 *(GLushort *)ptr4 = pixel & 0xffff; 449 } 450 } 451 else { 452 register int i, j; 453 for (j=0;j<height;j++) { 454 register GLushort *ptr2 = PIXELADDR2( xmesa->xm_buffer, x, y+j ); 455 for (i=0;i<width;i++) { 456 *ptr2++ = pixel; 457 } 458 } 459 } 460} 461 462 463/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */ 464static void 465clear_24bit_ximage( GLcontext *ctx, GLboolean all, 466 GLint x, GLint y, GLint width, GLint height ) 467{ 468 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 469 const GLubyte r = xmesa->clearcolor[0]; 470 const GLubyte g = xmesa->clearcolor[1]; 471 const GLubyte b = xmesa->clearcolor[2]; 472 register GLuint clearPixel; 473 if (xmesa->swapbytes) { 474 clearPixel = (b << 16) | (g << 8) | r; 475 } 476 else { 477 clearPixel = (r << 16) | (g << 8) | b; 478 } 479 480 if (all) { 481 if (r==g && g==b) { 482 /* same value for all three components (gray) */ 483 const GLint w3 = xmesa->xm_buffer->width * 3; 484 const GLint h = xmesa->xm_buffer->height; 485 GLint i; 486 for (i = 0; i < h; i++) { 487 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i); 488 MEMSET(ptr3, r, w3); 489 } 490 } 491 else { 492 /* the usual case */ 493 const GLint w = xmesa->xm_buffer->width; 494 const GLint h = xmesa->xm_buffer->height; 495 GLint i, j; 496 for (i = 0; i < h; i++) { 497 bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i); 498 for (j = 0; j < w; j++) { 499 ptr3->r = r; 500 ptr3->g = g; 501 ptr3->b = b; 502 ptr3++; 503 } 504 } 505#if 0 /* this code doesn't work for all window widths */ 506 register GLuint *ptr4 = (GLuint *) ptr3; 507 register GLuint px; 508 GLuint pixel4[3]; 509 register GLuint *p = pixel4; 510 pixel4[0] = clearPixel | (clearPixel << 24); 511 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8); 512 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16); 513 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){ 514 case 0: 515 break; 516 case 1: 517 px = *ptr4 & 0x00ffffff; 518 px |= pixel4[0] & 0xff000000; 519 *ptr4++ = px; 520 px = *ptr4 & 0xffff0000; 521 px |= pixel4[2] & 0x0000ffff; 522 *ptr4 = px; 523 if (0 == --n) 524 break; 525 case 2: 526 px = *ptr4 & 0x0000fffff; 527 px |= pixel4[1] & 0xffff0000; 528 *ptr4++ = px; 529 px = *ptr4 & 0xffffff00; 530 px |= pixel4[2] & 0x000000ff; 531 *ptr4 = px; 532 if (0 == --n) 533 break; 534 case 3: 535 px = *ptr4 & 0x000000ff; 536 px |= pixel4[2] & 0xffffff00; 537 *ptr4++ = px; 538 --n; 539 break; 540 } 541 while (n > 3) { 542 p = pixel4; 543 *ptr4++ = *p++; 544 *ptr4++ = *p++; 545 *ptr4++ = *p++; 546 n -= 4; 547 } 548 switch (n) { 549 case 3: 550 p = pixel4; 551 *ptr4++ = *p++; 552 *ptr4++ = *p++; 553 px = *ptr4 & 0xffffff00; 554 px |= clearPixel & 0xff; 555 *ptr4 = px; 556 break; 557 case 2: 558 p = pixel4; 559 *ptr4++ = *p++; 560 px = *ptr4 & 0xffff0000; 561 px |= *p & 0xffff; 562 *ptr4 = px; 563 break; 564 case 1: 565 px = *ptr4 & 0xff000000; 566 px |= *p & 0xffffff; 567 *ptr4 = px; 568 break; 569 case 0: 570 break; 571 } 572#endif 573 } 574 } 575 else { 576 /* only clear subrect of color buffer */ 577 if (r==g && g==b) { 578 /* same value for all three components (gray) */ 579 GLint j; 580 for (j=0;j<height;j++) { 581 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j ); 582 MEMSET(ptr3, r, 3 * width); 583 } 584 } 585 else { 586 /* non-gray clear color */ 587 GLint i, j; 588 for (j = 0; j < height; j++) { 589 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j ); 590 for (i = 0; i < width; i++) { 591 ptr3->r = r; 592 ptr3->g = g; 593 ptr3->b = b; 594 ptr3++; 595 } 596 } 597#if 0 /* this code might not always (seems ptr3 always == ptr4) */ 598 GLint j; 599 GLuint pixel4[3]; 600 pixel4[0] = clearPixel | (clearPixel << 24); 601 pixel4[1] = (clearPixel << 16) | (clearPixel >> 8); 602 pixel4[2] = (clearPixel << 8) | (clearPixel >> 16); 603 for (j=0;j<height;j++) { 604 bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j ); 605 register GLuint *ptr4 = (GLuint *)ptr3; 606 register GLuint *p, px; 607 GLuint w = width; 608 switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){ 609 case 0: 610 break; 611 case 1: 612 px = *ptr4 & 0x00ffffff; 613 px |= pixel4[0] & 0xff000000; 614 *ptr4++ = px; 615 px = *ptr4 & 0xffff0000; 616 px |= pixel4[2] & 0x0000ffff; 617 *ptr4 = px; 618 if (0 == --w) 619 break; 620 case 2: 621 px = *ptr4 & 0x0000fffff; 622 px |= pixel4[1] & 0xffff0000; 623 *ptr4++ = px; 624 px = *ptr4 & 0xffffff00; 625 px |= pixel4[2] & 0x000000ff; 626 *ptr4 = px; 627 if (0 == --w) 628 break; 629 case 3: 630 px = *ptr4 & 0x000000ff; 631 px |= pixel4[2] & 0xffffff00; 632 *ptr4++ = px; 633 --w; 634 break; 635 } 636 while (w > 3){ 637 p = pixel4; 638 *ptr4++ = *p++; 639 *ptr4++ = *p++; 640 *ptr4++ = *p++; 641 w -= 4; 642 } 643 switch (w) { 644 case 3: 645 p = pixel4; 646 *ptr4++ = *p++; 647 *ptr4++ = *p++; 648 px = *ptr4 & 0xffffff00; 649 px |= *p & 0xff; 650 *ptr4 = px; 651 break; 652 case 2: 653 p = pixel4; 654 *ptr4++ = *p++; 655 px = *ptr4 & 0xffff0000; 656 px |= *p & 0xffff; 657 *ptr4 = px; 658 break; 659 case 1: 660 px = *ptr4 & 0xff000000; 661 px |= pixel4[0] & 0xffffff; 662 *ptr4 = px; 663 break; 664 case 0: 665 break; 666 } 667 } 668#endif 669 } 670 } 671} 672 673 674static void 675clear_32bit_ximage( GLcontext *ctx, GLboolean all, 676 GLint x, GLint y, GLint width, GLint height ) 677{ 678 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 679 if (all) { 680 register GLint n = xmesa->xm_buffer->width * xmesa->xm_buffer->height; 681 register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data; 682 register GLuint pixel = (GLuint) xmesa->clearpixel; 683 if (xmesa->swapbytes) { 684 pixel = ((pixel >> 24) & 0x000000ff) 685 | ((pixel >> 8) & 0x0000ff00) 686 | ((pixel << 8) & 0x00ff0000) 687 | ((pixel << 24) & 0xff000000); 688 } 689 if (pixel==0) { 690 MEMSET( ptr4, pixel, 4*n ); 691 } 692 else { 693 do { 694 *ptr4++ = pixel; 695 n--; 696 } while (n!=0); 697 } 698 } 699 else { 700 register int i, j; 701 register GLuint pixel = (GLuint) xmesa->clearpixel; 702 for (j=0;j<height;j++) { 703 register GLuint *ptr4 = PIXELADDR4( xmesa->xm_buffer, x, y+j ); 704 for (i=0;i<width;i++) { 705 *ptr4++ = pixel; 706 } 707 } 708 } 709} 710 711 712static void 713clear_nbit_ximage( GLcontext *ctx, GLboolean all, 714 GLint x, GLint y, GLint width, GLint height ) 715{ 716 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 717 XMesaImage *img = xmesa->xm_buffer->backimage; 718 if (all) { 719 register int i, j; 720 width = xmesa->xm_buffer->width; 721 height = xmesa->xm_buffer->height; 722 for (j=0;j<height;j++) { 723 for (i=0;i<width;i++) { 724 XMesaPutPixel( img, i, j, xmesa->clearpixel ); 725 } 726 } 727 } 728 else { 729 /* TODO: optimize this */ 730 register int i, j; 731 y = FLIP(xmesa->xm_buffer, y); 732 for (j=0;j<height;j++) { 733 for (i=0;i<width;i++) { 734 XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel ); 735 } 736 } 737 } 738} 739 740 741 742static void 743clear_buffers( GLcontext *ctx, GLbitfield mask, 744 GLboolean all, GLint x, GLint y, GLint width, GLint height ) 745{ 746 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 747 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; 748 749 /* we can't handle color or index masking */ 750 if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { 751 if (mask & DD_FRONT_LEFT_BIT) { 752 ASSERT(xmesa->xm_buffer->front_clear_func); 753 (*xmesa->xm_buffer->front_clear_func)( ctx, all, x, y, width, height ); 754 mask &= ~DD_FRONT_LEFT_BIT; 755 } 756 if (mask & DD_BACK_LEFT_BIT) { 757 ASSERT(xmesa->xm_buffer->back_clear_func); 758 (*xmesa->xm_buffer->back_clear_func)( ctx, all, x, y, width, height ); 759 mask &= ~DD_BACK_LEFT_BIT; 760 } 761 } 762 763 if (mask) 764 _swrast_Clear( ctx, mask, all, x, y, width, height ); 765} 766 767 768static void 769resize_buffers( GLcontext *ctx ) 770{ 771 _swrast_alloc_buffers( ctx ); 772} 773 774#if 0 775/* 776 * This function implements glDrawPixels() with an XPutImage call when 777 * drawing to the front buffer (X Window drawable). 778 * The image format must be GL_BGRA to match the PF_8R8G8B pixel format. 779 * XXX top/bottom edge clipping is broken! 780 */ 781static GLboolean 782drawpixels_8R8G8B( GLcontext *ctx, 783 GLint x, GLint y, GLsizei width, GLsizei height, 784 GLenum format, GLenum type, 785 const struct gl_pixelstore_attrib *unpack, 786 const GLvoid *pixels ) 787{ 788 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 789 XMesaDisplay *dpy = xmesa->xm_visual->display; 790 XMesaDrawable buffer = xmesa->xm_buffer->buffer; 791 XMesaGC gc = xmesa->xm_buffer->gc; 792 assert(dpy); 793 assert(buffer); 794 assert(gc); 795 796 /* XXX also check for pixel scale/bias/lookup/zooming! */ 797 if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) { 798 int dstX = x; 799 int dstY = y; 800 int w = width; 801 int h = height; 802 int srcX = unpack->SkipPixels; 803 int srcY = unpack->SkipRows; 804 if (_mesa_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) { 805 XMesaImage ximage; 806 MEMSET(&ximage, 0, sizeof(XMesaImage)); 807 ximage.width = width; 808 ximage.height = height; 809 ximage.format = ZPixmap; 810 ximage.data = (char *) pixels + (height - 1) * width * 4; 811 ximage.byte_order = LSBFirst; 812 ximage.bitmap_unit = 32; 813 ximage.bitmap_bit_order = LSBFirst; 814 ximage.bitmap_pad = 32; 815 ximage.depth = 24; 816 ximage.bytes_per_line = -width * 4; 817 ximage.bits_per_pixel = 32; 818 ximage.red_mask = 0xff0000; 819 ximage.green_mask = 0x00ff00; 820 ximage.blue_mask = 0x0000ff; 821 dstY = FLIP(xmesa->xm_buffer,dstY) - height + 1; 822 XPutImage(dpy, buffer, gc, &ximage, srcX, srcY, dstX, dstY, w, h); 823 return GL_TRUE; 824 } 825 } 826 return GL_FALSE; 827} 828#endif 829 830 831 832static const GLubyte * 833get_string( GLcontext *ctx, GLenum name ) 834{ 835 (void) ctx; 836 switch (name) { 837 case GL_RENDERER: 838#ifdef XFree86Server 839 return (const GLubyte *) "Mesa GLX Indirect"; 840#else 841 return (const GLubyte *) "Mesa X11"; 842#endif 843 case GL_VENDOR: 844#ifdef XFree86Server 845 return (const GLubyte *) "VA Linux Systems, Inc."; 846#else 847 return NULL; 848#endif 849 default: 850 return NULL; 851 } 852} 853 854 855static void 856enable( GLcontext *ctx, GLenum pname, GLboolean state ) 857{ 858 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 859 860 switch (pname) { 861 case GL_DITHER: 862 if (state) 863 xmesa->pixelformat = xmesa->xm_visual->dithered_pf; 864 else 865 xmesa->pixelformat = xmesa->xm_visual->undithered_pf; 866 break; 867 default: 868 ; /* silence compiler warning */ 869 } 870} 871 872 873void xmesa_update_state( GLcontext *ctx, GLuint new_state ) 874{ 875 const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx; 876 877 /* Propogate statechange information to swrast and swrast_setup 878 * modules. The X11 driver has no internal GL-dependent state. 879 */ 880 _swrast_InvalidateState( ctx, new_state ); 881 _ac_InvalidateState( ctx, new_state ); 882 _tnl_InvalidateState( ctx, new_state ); 883 _swsetup_InvalidateState( ctx, new_state ); 884 885 886 /* setup pointers to front and back buffer clear functions */ 887 xmesa->xm_buffer->front_clear_func = clear_front_pixmap; 888 if (xmesa->xm_buffer->backpixmap != XIMAGE) { 889 xmesa->xm_buffer->back_clear_func = clear_back_pixmap; 890 } 891 else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) { 892 xmesa->xm_buffer->back_clear_func = clear_nbit_ximage; 893 } 894 else switch (xmesa->xm_visual->BitsPerPixel) { 895 case 8: 896 if (xmesa->xm_visual->hpcr_clear_flag) { 897 xmesa->xm_buffer->back_clear_func = clear_HPCR_ximage; 898 } 899 else { 900 xmesa->xm_buffer->back_clear_func = clear_8bit_ximage; 901 } 902 break; 903 case 16: 904 xmesa->xm_buffer->back_clear_func = clear_16bit_ximage; 905 break; 906 case 24: 907 xmesa->xm_buffer->back_clear_func = clear_24bit_ximage; 908 break; 909 case 32: 910 xmesa->xm_buffer->back_clear_func = clear_32bit_ximage; 911 break; 912 default: 913 xmesa->xm_buffer->back_clear_func = clear_nbit_ximage; 914 break; 915 } 916 917 xmesa_update_span_funcs(ctx); 918} 919 920 921 922/* Setup pointers and other driver state that is constant for the life 923 * of a context. 924 */ 925void xmesa_init_pointers( GLcontext *ctx ) 926{ 927 ctx->Driver.GetString = get_string; 928 ctx->Driver.GetBufferSize = get_buffer_size; 929 ctx->Driver.Flush = flush; 930 ctx->Driver.Finish = finish; 931 932 /* Hooks for t_vb_render.c: 933 */ 934 ctx->Driver.RenderStart = _swsetup_RenderStart; 935 ctx->Driver.RenderFinish = _swsetup_RenderFinish; 936 ctx->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices; 937 ctx->Driver.RenderPrimitive = _swsetup_RenderPrimitive; 938 ctx->Driver.PointsFunc = _swsetup_Points; 939 ctx->Driver.LineFunc = _swsetup_Line; 940 ctx->Driver.TriangleFunc = _swsetup_Triangle; 941 ctx->Driver.QuadFunc = _swsetup_Quad; 942 ctx->Driver.ResetLineStipple = _swrast_ResetLineStipple; 943 ctx->Driver.RenderInterp = _swsetup_RenderInterp; 944 ctx->Driver.RenderCopyPV = _swsetup_RenderCopyPV; 945 ctx->Driver.RenderClippedLine = _swsetup_RenderClippedLine; 946 ctx->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon; 947 948 /* Software rasterizer pixel paths: 949 */ 950 ctx->Driver.Accum = _swrast_Accum; 951 ctx->Driver.Bitmap = _swrast_Bitmap; 952 ctx->Driver.Clear = clear_buffers; 953 ctx->Driver.ResizeBuffersMESA = resize_buffers; 954 ctx->Driver.CopyPixels = _swrast_CopyPixels; 955 ctx->Driver.DrawPixels = _swrast_DrawPixels; 956 ctx->Driver.ReadPixels = _swrast_ReadPixels; 957 958 959 /* 960 */ 961 ctx->Driver.SetDrawBuffer = set_draw_buffer; 962 ctx->Driver.SetReadBuffer = set_read_buffer; 963 ctx->Driver.ClearIndex = clear_index; 964 ctx->Driver.ClearColor = clear_color; 965 ctx->Driver.IndexMask = index_mask; 966 ctx->Driver.ColorMask = color_mask; 967 ctx->Driver.Enable = enable; 968 969 (void) DitherValues; /* silenced unused var warning */ 970} 971