1 /* 2 * Copyright 2008, 2010 George Sapountzis <gsapountzis (at) gmail.com> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 /* 24 * DRI software rasterizer 25 * 26 * This is the mesa swrast module packaged into a DRI driver structure. 27 * 28 * The front-buffer is allocated by the loader. The loader provides read/write 29 * callbacks for access to the front-buffer. The driver uses a scratch row for 30 * front-buffer rendering to avoid repeated calls to the loader. 31 * 32 * The back-buffer is allocated by the driver and is private. 33 */ 34 35 #include <stdio.h> 36 #include "main/api_exec.h" 37 #include "main/context.h" 38 #include "main/extensions.h" 39 #include "main/formats.h" 40 #include "main/framebuffer.h" 41 #include "main/imports.h" 42 #include "main/renderbuffer.h" 43 #include "main/version.h" 44 #include "main/vtxfmt.h" 45 #include "swrast/swrast.h" 46 #include "swrast/s_renderbuffer.h" 47 #include "swrast_setup/swrast_setup.h" 48 #include "tnl/tnl.h" 49 #include "tnl/t_context.h" 50 #include "tnl/t_pipeline.h" 51 #include "vbo/vbo.h" 52 #include "drivers/common/driverfuncs.h" 53 #include "drivers/common/meta.h" 54 #include "utils.h" 55 56 #include "main/teximage.h" 57 #include "main/texformat.h" 58 #include "main/texobj.h" 59 #include "main/texstate.h" 60 61 #include "swrast_priv.h" 62 #include "swrast/s_context.h" 63 64 #include <sys/types.h> 65 #ifdef HAVE_SYS_SYSCTL_H 66 # include <sys/sysctl.h> 67 #endif 68 69 const __DRIextension **__driDriverGetExtensions_swrast(void); 70 71 const char * const swrast_vendor_string = "Mesa Project"; 72 const char * const swrast_renderer_string = "Software Rasterizer"; 73 74 /** 75 * Screen and config-related functions 76 */ 77 78 static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, 79 GLint texture_format, __DRIdrawable *dPriv) 80 { 81 struct dri_context *dri_ctx; 82 int x, y, w, h; 83 __DRIscreen *sPriv = dPriv->driScreenPriv; 84 struct gl_texture_object *texObj; 85 struct gl_texture_image *texImage; 86 struct swrast_texture_image *swImage; 87 uint32_t internalFormat; 88 mesa_format texFormat; 89 90 dri_ctx = pDRICtx->driverPrivate; 91 92 internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4); 93 94 texObj = _mesa_get_current_tex_object(&dri_ctx->Base, target); 95 texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0); 96 swImage = swrast_texture_image(texImage); 97 98 _mesa_lock_texture(&dri_ctx->Base, texObj); 99 100 sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate); 101 102 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) 103 texFormat = MESA_FORMAT_B8G8R8X8_UNORM; 104 else 105 texFormat = MESA_FORMAT_B8G8R8A8_UNORM; 106 107 _mesa_init_teximage_fields(&dri_ctx->Base, texImage, 108 w, h, 1, 0, internalFormat, texFormat); 109 110 sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer, 111 dPriv->loaderPrivate); 112 113 _mesa_unlock_texture(&dri_ctx->Base, texObj); 114 } 115 116 static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target, 117 __DRIdrawable *dPriv) 118 { 119 swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 120 } 121 122 static const __DRItexBufferExtension swrastTexBufferExtension = { 123 .base = { __DRI_TEX_BUFFER, 3 }, 124 125 .setTexBuffer = swrastSetTexBuffer, 126 .setTexBuffer2 = swrastSetTexBuffer2, 127 .releaseTexBuffer = NULL, 128 }; 129 130 131 static int 132 swrast_query_renderer_integer(__DRIscreen *psp, int param, 133 unsigned int *value) 134 { 135 switch (param) { 136 case __DRI2_RENDERER_VENDOR_ID: 137 case __DRI2_RENDERER_DEVICE_ID: 138 /* Return 0xffffffff for both vendor and device id */ 139 value[0] = 0xffffffff; 140 return 0; 141 case __DRI2_RENDERER_ACCELERATED: 142 value[0] = 0; 143 return 0; 144 case __DRI2_RENDERER_VIDEO_MEMORY: { 145 /* This should probably share code with os_get_total_physical_memory() 146 * from src/gallium/auxiliary/os/os_misc.c 147 */ 148 #if defined(CTL_HW) && defined(HW_MEMSIZE) 149 int mib[2] = { CTL_HW, HW_MEMSIZE }; 150 unsigned long system_memory_bytes; 151 size_t len = sizeof(system_memory_bytes); 152 if (sysctl(mib, 2, &system_memory_bytes, &len, NULL, 0) != 0) 153 return -1; 154 #elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE) 155 /* XXX: Do we want to return the full amount of system memory ? */ 156 const long system_memory_pages = sysconf(_SC_PHYS_PAGES); 157 const long system_page_size = sysconf(_SC_PAGE_SIZE); 158 159 if (system_memory_pages <= 0 || system_page_size <= 0) 160 return -1; 161 162 const uint64_t system_memory_bytes = (uint64_t) system_memory_pages 163 * (uint64_t) system_page_size; 164 #else 165 #error "Unsupported platform" 166 #endif 167 168 const unsigned system_memory_megabytes = 169 (unsigned) (system_memory_bytes / (1024 * 1024)); 170 171 value[0] = system_memory_megabytes; 172 return 0; 173 } 174 case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE: 175 /** 176 * XXX: Perhaps we should return 1 ? 177 * See issue #7 from the spec, currently UNRESOLVED. 178 */ 179 value[0] = 0; 180 return 0; 181 default: 182 return driQueryRendererIntegerCommon(psp, param, value); 183 } 184 } 185 186 static int 187 swrast_query_renderer_string(__DRIscreen *psp, int param, const char **value) 188 { 189 switch (param) { 190 case __DRI2_RENDERER_VENDOR_ID: 191 value[0] = swrast_vendor_string; 192 return 0; 193 case __DRI2_RENDERER_DEVICE_ID: 194 value[0] = swrast_renderer_string; 195 return 0; 196 default: 197 return -1; 198 } 199 } 200 201 static const __DRI2rendererQueryExtension swrast_query_renderer_extension = { 202 .base = { __DRI2_RENDERER_QUERY, 1 }, 203 204 .queryInteger = swrast_query_renderer_integer, 205 .queryString = swrast_query_renderer_string 206 }; 207 208 static const __DRIextension *dri_screen_extensions[] = { 209 &swrastTexBufferExtension.base, 210 &swrast_query_renderer_extension.base, 211 &dri2ConfigQueryExtension.base, 212 &dri2NoErrorExtension.base, 213 NULL 214 }; 215 216 static __DRIconfig ** 217 swrastFillInModes(__DRIscreen *psp, 218 unsigned pixel_bits, unsigned depth_bits, 219 unsigned stencil_bits, GLboolean have_back_buffer) 220 { 221 __DRIconfig **configs; 222 unsigned depth_buffer_factor; 223 unsigned back_buffer_factor; 224 mesa_format format; 225 226 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 227 * support pageflipping at all. 228 */ 229 static const GLenum back_buffer_modes[] = { 230 __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED 231 }; 232 233 uint8_t depth_bits_array[4]; 234 uint8_t stencil_bits_array[4]; 235 uint8_t msaa_samples_array[1]; 236 237 (void) psp; 238 (void) have_back_buffer; 239 240 depth_bits_array[0] = 0; 241 depth_bits_array[1] = 0; 242 depth_bits_array[2] = depth_bits; 243 depth_bits_array[3] = depth_bits; 244 245 /* Just like with the accumulation buffer, always provide some modes 246 * with a stencil buffer. 247 */ 248 stencil_bits_array[0] = 0; 249 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; 250 stencil_bits_array[2] = 0; 251 stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits; 252 253 msaa_samples_array[0] = 0; 254 255 depth_buffer_factor = 4; 256 back_buffer_factor = 2; 257 258 switch (pixel_bits) { 259 case 16: 260 format = MESA_FORMAT_B5G6R5_UNORM; 261 break; 262 case 24: 263 format = MESA_FORMAT_B8G8R8X8_UNORM; 264 break; 265 case 32: 266 format = MESA_FORMAT_B8G8R8A8_UNORM; 267 break; 268 default: 269 fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__, 270 pixel_bits); 271 return NULL; 272 } 273 274 configs = driCreateConfigs(format, 275 depth_bits_array, stencil_bits_array, 276 depth_buffer_factor, back_buffer_modes, 277 back_buffer_factor, msaa_samples_array, 1, 278 GL_TRUE, GL_FALSE); 279 if (configs == NULL) { 280 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 281 __LINE__); 282 return NULL; 283 } 284 285 return configs; 286 } 287 288 static const __DRIconfig ** 289 dri_init_screen(__DRIscreen * psp) 290 { 291 __DRIconfig **configs16, **configs24, **configs32; 292 293 TRACE; 294 295 psp->max_gl_compat_version = 21; 296 psp->max_gl_es1_version = 11; 297 psp->max_gl_es2_version = 20; 298 299 psp->extensions = dri_screen_extensions; 300 301 configs16 = swrastFillInModes(psp, 16, 16, 0, 1); 302 configs24 = swrastFillInModes(psp, 24, 24, 8, 1); 303 configs32 = swrastFillInModes(psp, 32, 24, 8, 1); 304 305 configs24 = driConcatConfigs(configs16, configs24); 306 configs32 = driConcatConfigs(configs24, configs32); 307 308 return (const __DRIconfig **)configs32; 309 } 310 311 static void 312 dri_destroy_screen(__DRIscreen * sPriv) 313 { 314 TRACE; 315 (void) sPriv; 316 } 317 318 319 /** 320 * Framebuffer and renderbuffer-related functions. 321 */ 322 323 static GLuint 324 choose_pixel_format(const struct gl_config *v) 325 { 326 int depth = v->rgbBits; 327 328 if (depth == 32 329 && v->redMask == 0xff0000 330 && v->greenMask == 0x00ff00 331 && v->blueMask == 0x0000ff) 332 return PF_A8R8G8B8; 333 else if (depth == 24 334 && v->redMask == 0xff0000 335 && v->greenMask == 0x00ff00 336 && v->blueMask == 0x0000ff) 337 return PF_X8R8G8B8; 338 else if (depth == 16 339 && v->redMask == 0xf800 340 && v->greenMask == 0x07e0 341 && v->blueMask == 0x001f) 342 return PF_R5G6B5; 343 else if (depth == 8 344 && v->redMask == 0x07 345 && v->greenMask == 0x38 346 && v->blueMask == 0xc0) 347 return PF_R3G3B2; 348 349 _mesa_problem( NULL, "unexpected format in %s", __func__ ); 350 return 0; 351 } 352 353 static void 354 swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 355 { 356 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 357 358 TRACE; 359 360 free(xrb->Base.Buffer); 361 _mesa_delete_renderbuffer(ctx, rb); 362 } 363 364 /* see bytes_per_line in libGL */ 365 static inline int 366 bytes_per_line(unsigned pitch_bits, unsigned mul) 367 { 368 unsigned mask = mul - 1; 369 370 return ((pitch_bits + mask) & ~mask) / 8; 371 } 372 373 static GLboolean 374 swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 375 GLenum internalFormat, GLuint width, GLuint height) 376 { 377 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 378 379 TRACE; 380 381 (void) ctx; 382 (void) internalFormat; 383 384 xrb->Base.Buffer = NULL; 385 rb->Width = width; 386 rb->Height = height; 387 xrb->pitch = bytes_per_line(width * xrb->bpp, 32); 388 389 return GL_TRUE; 390 } 391 392 static GLboolean 393 swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 394 GLenum internalFormat, GLuint width, GLuint height) 395 { 396 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 397 398 TRACE; 399 400 free(xrb->Base.Buffer); 401 402 swrast_alloc_front_storage(ctx, rb, internalFormat, width, height); 403 404 xrb->Base.Buffer = malloc(height * xrb->pitch); 405 406 return GL_TRUE; 407 } 408 409 static struct dri_swrast_renderbuffer * 410 swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv, 411 GLboolean front) 412 { 413 struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb); 414 struct gl_renderbuffer *rb; 415 GLuint pixel_format; 416 417 TRACE; 418 419 if (!xrb) 420 return NULL; 421 422 rb = &xrb->Base.Base; 423 424 _mesa_init_renderbuffer(rb, 0); 425 426 pixel_format = choose_pixel_format(visual); 427 428 xrb->dPriv = dPriv; 429 xrb->Base.Base.Delete = swrast_delete_renderbuffer; 430 if (front) { 431 rb->AllocStorage = swrast_alloc_front_storage; 432 } 433 else { 434 rb->AllocStorage = swrast_alloc_back_storage; 435 } 436 437 switch (pixel_format) { 438 case PF_A8R8G8B8: 439 rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; 440 rb->InternalFormat = GL_RGBA; 441 rb->_BaseFormat = GL_RGBA; 442 xrb->bpp = 32; 443 break; 444 case PF_X8R8G8B8: 445 rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; /* XXX */ 446 rb->InternalFormat = GL_RGB; 447 rb->_BaseFormat = GL_RGB; 448 xrb->bpp = 32; 449 break; 450 case PF_R5G6B5: 451 rb->Format = MESA_FORMAT_B5G6R5_UNORM; 452 rb->InternalFormat = GL_RGB; 453 rb->_BaseFormat = GL_RGB; 454 xrb->bpp = 16; 455 break; 456 case PF_R3G3B2: 457 rb->Format = MESA_FORMAT_B2G3R3_UNORM; 458 rb->InternalFormat = GL_RGB; 459 rb->_BaseFormat = GL_RGB; 460 xrb->bpp = 8; 461 break; 462 default: 463 free(xrb); 464 return NULL; 465 } 466 467 return xrb; 468 } 469 470 static void 471 swrast_map_renderbuffer(struct gl_context *ctx, 472 struct gl_renderbuffer *rb, 473 GLuint x, GLuint y, GLuint w, GLuint h, 474 GLbitfield mode, 475 GLubyte **out_map, 476 GLint *out_stride) 477 { 478 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 479 GLubyte *map = xrb->Base.Buffer; 480 int cpp = _mesa_get_format_bytes(rb->Format); 481 int stride = rb->Width * cpp; 482 483 if (rb->AllocStorage == swrast_alloc_front_storage) { 484 __DRIdrawable *dPriv = xrb->dPriv; 485 __DRIscreen *sPriv = dPriv->driScreenPriv; 486 487 xrb->map_mode = mode; 488 xrb->map_x = x; 489 xrb->map_y = rb->Height - y - h; 490 xrb->map_w = w; 491 xrb->map_h = h; 492 493 stride = w * cpp; 494 xrb->Base.Buffer = malloc(h * stride); 495 496 sPriv->swrast_loader->getImage(dPriv, x, xrb->map_y, w, h, 497 (char *) xrb->Base.Buffer, 498 dPriv->loaderPrivate); 499 500 *out_map = xrb->Base.Buffer + (h - 1) * stride; 501 *out_stride = -stride; 502 return; 503 } 504 505 assert(xrb->Base.Buffer); 506 507 if (rb->AllocStorage == swrast_alloc_back_storage) { 508 map += (rb->Height - 1) * stride; 509 stride = -stride; 510 } 511 512 map += (GLsizei)y * stride; 513 map += (GLsizei)x * cpp; 514 515 *out_map = map; 516 *out_stride = stride; 517 } 518 519 static void 520 swrast_unmap_renderbuffer(struct gl_context *ctx, 521 struct gl_renderbuffer *rb) 522 { 523 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 524 525 if (rb->AllocStorage == swrast_alloc_front_storage) { 526 __DRIdrawable *dPriv = xrb->dPriv; 527 __DRIscreen *sPriv = dPriv->driScreenPriv; 528 529 if (xrb->map_mode & GL_MAP_WRITE_BIT) { 530 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW, 531 xrb->map_x, xrb->map_y, 532 xrb->map_w, xrb->map_h, 533 (char *) xrb->Base.Buffer, 534 dPriv->loaderPrivate); 535 } 536 537 free(xrb->Base.Buffer); 538 xrb->Base.Buffer = NULL; 539 } 540 } 541 542 static GLboolean 543 dri_create_buffer(__DRIscreen * sPriv, 544 __DRIdrawable * dPriv, 545 const struct gl_config * visual, GLboolean isPixmap) 546 { 547 struct dri_drawable *drawable = NULL; 548 struct gl_framebuffer *fb; 549 struct dri_swrast_renderbuffer *frontrb, *backrb; 550 551 TRACE; 552 553 (void) sPriv; 554 (void) isPixmap; 555 556 drawable = CALLOC_STRUCT(dri_drawable); 557 if (drawable == NULL) 558 goto drawable_fail; 559 560 dPriv->driverPrivate = drawable; 561 drawable->dPriv = dPriv; 562 563 drawable->row = malloc(SWRAST_MAX_WIDTH * 4); 564 if (drawable->row == NULL) 565 goto drawable_fail; 566 567 fb = &drawable->Base; 568 569 /* basic framebuffer setup */ 570 _mesa_initialize_window_framebuffer(fb, visual); 571 572 /* add front renderbuffer */ 573 frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE); 574 _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base); 575 576 /* add back renderbuffer */ 577 if (visual->doubleBufferMode) { 578 backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE); 579 _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, &backrb->Base.Base); 580 } 581 582 /* add software renderbuffers */ 583 _swrast_add_soft_renderbuffers(fb, 584 GL_FALSE, /* color */ 585 visual->haveDepthBuffer, 586 visual->haveStencilBuffer, 587 visual->haveAccumBuffer, 588 GL_FALSE, /* alpha */ 589 GL_FALSE /* aux bufs */); 590 591 return GL_TRUE; 592 593 drawable_fail: 594 595 if (drawable) 596 free(drawable->row); 597 598 free(drawable); 599 600 return GL_FALSE; 601 } 602 603 static void 604 dri_destroy_buffer(__DRIdrawable * dPriv) 605 { 606 TRACE; 607 608 if (dPriv) { 609 struct dri_drawable *drawable = dri_drawable(dPriv); 610 struct gl_framebuffer *fb; 611 612 free(drawable->row); 613 614 fb = &drawable->Base; 615 616 fb->DeletePending = GL_TRUE; 617 _mesa_reference_framebuffer(&fb, NULL); 618 } 619 } 620 621 static void 622 dri_swap_buffers(__DRIdrawable * dPriv) 623 { 624 __DRIscreen *sPriv = dPriv->driScreenPriv; 625 626 GET_CURRENT_CONTEXT(ctx); 627 628 struct dri_drawable *drawable = dri_drawable(dPriv); 629 struct gl_framebuffer *fb; 630 struct dri_swrast_renderbuffer *frontrb, *backrb; 631 632 TRACE; 633 634 fb = &drawable->Base; 635 636 frontrb = 637 dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 638 backrb = 639 dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 640 641 /* check for signle-buffered */ 642 if (backrb == NULL) 643 return; 644 645 /* check if swapping currently bound buffer */ 646 if (ctx && ctx->DrawBuffer == fb) { 647 /* flush pending rendering */ 648 _mesa_notifySwapBuffers(ctx); 649 } 650 651 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 652 0, 0, 653 frontrb->Base.Base.Width, 654 frontrb->Base.Base.Height, 655 (char *) backrb->Base.Buffer, 656 dPriv->loaderPrivate); 657 } 658 659 660 /** 661 * General device driver functions. 662 */ 663 664 static void 665 get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h ) 666 { 667 __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv; 668 __DRIscreen *sPriv = dPriv->driScreenPriv; 669 int x, y; 670 671 sPriv->swrast_loader->getDrawableInfo(dPriv, 672 &x, &y, w, h, 673 dPriv->loaderPrivate); 674 } 675 676 static void 677 swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb ) 678 { 679 GLsizei width, height; 680 681 get_window_size(fb, &width, &height); 682 if (fb->Width != width || fb->Height != height) { 683 _mesa_resize_framebuffer(ctx, fb, width, height); 684 } 685 } 686 687 static const GLubyte * 688 get_string(struct gl_context *ctx, GLenum pname) 689 { 690 (void) ctx; 691 switch (pname) { 692 case GL_VENDOR: 693 return (const GLubyte *) swrast_vendor_string; 694 case GL_RENDERER: 695 return (const GLubyte *) swrast_renderer_string; 696 default: 697 return NULL; 698 } 699 } 700 701 static void 702 update_state(struct gl_context *ctx) 703 { 704 GLuint new_state = ctx->NewState; 705 706 if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) 707 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); 708 709 /* not much to do here - pass it on */ 710 _swrast_InvalidateState( ctx, new_state ); 711 _swsetup_InvalidateState( ctx, new_state ); 712 _tnl_InvalidateState( ctx, new_state ); 713 } 714 715 static void 716 viewport(struct gl_context *ctx) 717 { 718 struct gl_framebuffer *draw = ctx->WinSysDrawBuffer; 719 struct gl_framebuffer *read = ctx->WinSysReadBuffer; 720 721 swrast_check_and_update_window_size(ctx, draw); 722 swrast_check_and_update_window_size(ctx, read); 723 } 724 725 static mesa_format swrastChooseTextureFormat(struct gl_context * ctx, 726 GLenum target, 727 GLint internalFormat, 728 GLenum format, 729 GLenum type) 730 { 731 if (internalFormat == GL_RGB) 732 return MESA_FORMAT_B8G8R8X8_UNORM; 733 return _mesa_choose_tex_format(ctx, target, internalFormat, format, type); 734 } 735 736 static void 737 swrast_init_driver_functions(struct dd_function_table *driver) 738 { 739 driver->GetString = get_string; 740 driver->UpdateState = update_state; 741 driver->Viewport = viewport; 742 driver->ChooseTextureFormat = swrastChooseTextureFormat; 743 driver->MapRenderbuffer = swrast_map_renderbuffer; 744 driver->UnmapRenderbuffer = swrast_unmap_renderbuffer; 745 } 746 747 /** 748 * Context-related functions. 749 */ 750 751 static GLboolean 752 dri_create_context(gl_api api, 753 const struct gl_config * visual, 754 __DRIcontext * cPriv, 755 const struct __DriverContextConfig *ctx_config, 756 unsigned *error, 757 void *sharedContextPrivate) 758 { 759 struct dri_context *ctx = NULL; 760 struct dri_context *share = (struct dri_context *)sharedContextPrivate; 761 struct gl_context *mesaCtx = NULL; 762 struct gl_context *sharedCtx = NULL; 763 struct dd_function_table functions; 764 765 TRACE; 766 767 /* Flag filtering is handled in dri2CreateContextAttribs. 768 */ 769 (void) ctx_config->flags; 770 771 /* The swrast driver doesn't understand any of the attributes */ 772 if (ctx_config->attribute_mask != 0) { 773 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 774 return false; 775 } 776 777 ctx = CALLOC_STRUCT(dri_context); 778 if (ctx == NULL) { 779 *error = __DRI_CTX_ERROR_NO_MEMORY; 780 goto context_fail; 781 } 782 783 cPriv->driverPrivate = ctx; 784 ctx->cPriv = cPriv; 785 786 /* build table of device driver functions */ 787 _mesa_init_driver_functions(&functions); 788 swrast_init_driver_functions(&functions); 789 790 if (share) { 791 sharedCtx = &share->Base; 792 } 793 794 mesaCtx = &ctx->Base; 795 796 /* basic context setup */ 797 if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) { 798 *error = __DRI_CTX_ERROR_NO_MEMORY; 799 goto context_fail; 800 } 801 802 driContextSetFlags(mesaCtx, ctx_config->flags); 803 804 /* create module contexts */ 805 _swrast_CreateContext( mesaCtx ); 806 _vbo_CreateContext( mesaCtx ); 807 _tnl_CreateContext( mesaCtx ); 808 _swsetup_CreateContext( mesaCtx ); 809 _swsetup_Wakeup( mesaCtx ); 810 811 /* use default TCL pipeline */ 812 { 813 TNLcontext *tnl = TNL_CONTEXT(mesaCtx); 814 tnl->Driver.RunPipeline = _tnl_run_pipeline; 815 } 816 817 _mesa_meta_init(mesaCtx); 818 _mesa_enable_sw_extensions(mesaCtx); 819 820 _mesa_override_extensions(mesaCtx); 821 _mesa_compute_version(mesaCtx); 822 823 _mesa_initialize_dispatch_tables(mesaCtx); 824 _mesa_initialize_vbo_vtxfmt(mesaCtx); 825 826 *error = __DRI_CTX_ERROR_SUCCESS; 827 return GL_TRUE; 828 829 context_fail: 830 831 free(ctx); 832 833 return GL_FALSE; 834 } 835 836 static void 837 dri_destroy_context(__DRIcontext * cPriv) 838 { 839 TRACE; 840 841 if (cPriv) { 842 struct dri_context *ctx = dri_context(cPriv); 843 struct gl_context *mesaCtx; 844 845 mesaCtx = &ctx->Base; 846 847 _mesa_meta_free(mesaCtx); 848 _swsetup_DestroyContext( mesaCtx ); 849 _swrast_DestroyContext( mesaCtx ); 850 _tnl_DestroyContext( mesaCtx ); 851 _vbo_DestroyContext( mesaCtx ); 852 _mesa_destroy_context( mesaCtx ); 853 } 854 } 855 856 static GLboolean 857 dri_make_current(__DRIcontext * cPriv, 858 __DRIdrawable * driDrawPriv, 859 __DRIdrawable * driReadPriv) 860 { 861 struct gl_context *mesaCtx; 862 struct gl_framebuffer *mesaDraw; 863 struct gl_framebuffer *mesaRead; 864 TRACE; 865 866 if (cPriv) { 867 struct dri_context *ctx = dri_context(cPriv); 868 struct dri_drawable *draw; 869 struct dri_drawable *read; 870 871 if (!driDrawPriv || !driReadPriv) 872 return GL_FALSE; 873 874 draw = dri_drawable(driDrawPriv); 875 read = dri_drawable(driReadPriv); 876 mesaCtx = &ctx->Base; 877 mesaDraw = &draw->Base; 878 mesaRead = &read->Base; 879 880 /* check for same context and buffer */ 881 if (mesaCtx == _mesa_get_current_context() 882 && mesaCtx->DrawBuffer == mesaDraw 883 && mesaCtx->ReadBuffer == mesaRead) { 884 return GL_TRUE; 885 } 886 887 _glapi_check_multithread(); 888 889 swrast_check_and_update_window_size(mesaCtx, mesaDraw); 890 if (mesaRead != mesaDraw) 891 swrast_check_and_update_window_size(mesaCtx, mesaRead); 892 893 _mesa_make_current( mesaCtx, 894 mesaDraw, 895 mesaRead ); 896 } 897 else { 898 /* unbind */ 899 _mesa_make_current( NULL, NULL, NULL ); 900 } 901 902 return GL_TRUE; 903 } 904 905 static GLboolean 906 dri_unbind_context(__DRIcontext * cPriv) 907 { 908 TRACE; 909 (void) cPriv; 910 911 /* Unset current context and dispath table */ 912 _mesa_make_current(NULL, NULL, NULL); 913 914 return GL_TRUE; 915 } 916 917 static void 918 dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, 919 int w, int h) 920 { 921 __DRIscreen *sPriv = dPriv->driScreenPriv; 922 void *data; 923 int iy; 924 struct dri_drawable *drawable = dri_drawable(dPriv); 925 struct gl_framebuffer *fb; 926 struct dri_swrast_renderbuffer *frontrb, *backrb; 927 928 TRACE; 929 930 fb = &drawable->Base; 931 932 frontrb = 933 dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 934 backrb = 935 dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 936 937 /* check for signle-buffered */ 938 if (backrb == NULL) 939 return; 940 941 iy = frontrb->Base.Base.Height - y - h; 942 data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8)); 943 sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 944 x, iy, w, h, 945 frontrb->pitch, 946 data, 947 dPriv->loaderPrivate); 948 } 949 950 951 static const struct __DriverAPIRec swrast_driver_api = { 952 .InitScreen = dri_init_screen, 953 .DestroyScreen = dri_destroy_screen, 954 .CreateContext = dri_create_context, 955 .DestroyContext = dri_destroy_context, 956 .CreateBuffer = dri_create_buffer, 957 .DestroyBuffer = dri_destroy_buffer, 958 .SwapBuffers = dri_swap_buffers, 959 .MakeCurrent = dri_make_current, 960 .UnbindContext = dri_unbind_context, 961 .CopySubBuffer = dri_copy_sub_buffer, 962 }; 963 964 static const struct __DRIDriverVtableExtensionRec swrast_vtable = { 965 .base = { __DRI_DRIVER_VTABLE, 1 }, 966 .vtable = &swrast_driver_api, 967 }; 968 969 static const __DRIextension *swrast_driver_extensions[] = { 970 &driCoreExtension.base, 971 &driSWRastExtension.base, 972 &driCopySubBufferExtension.base, 973 &swrast_vtable.base, 974 NULL 975 }; 976 977 PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void) 978 { 979 globalDriverAPI = &swrast_driver_api; 980 981 return swrast_driver_extensions; 982 } 983