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