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 NULL 212 }; 213 214 static __DRIconfig ** 215 swrastFillInModes(__DRIscreen *psp, 216 unsigned pixel_bits, unsigned depth_bits, 217 unsigned stencil_bits, GLboolean have_back_buffer) 218 { 219 __DRIconfig **configs; 220 unsigned depth_buffer_factor; 221 unsigned back_buffer_factor; 222 mesa_format format; 223 224 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 225 * support pageflipping at all. 226 */ 227 static const GLenum back_buffer_modes[] = { 228 GLX_NONE, GLX_SWAP_UNDEFINED_OML 229 }; 230 231 uint8_t depth_bits_array[4]; 232 uint8_t stencil_bits_array[4]; 233 uint8_t msaa_samples_array[1]; 234 235 (void) psp; 236 (void) have_back_buffer; 237 238 depth_bits_array[0] = 0; 239 depth_bits_array[1] = 0; 240 depth_bits_array[2] = depth_bits; 241 depth_bits_array[3] = depth_bits; 242 243 /* Just like with the accumulation buffer, always provide some modes 244 * with a stencil buffer. 245 */ 246 stencil_bits_array[0] = 0; 247 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; 248 stencil_bits_array[2] = 0; 249 stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits; 250 251 msaa_samples_array[0] = 0; 252 253 depth_buffer_factor = 4; 254 back_buffer_factor = 2; 255 256 switch (pixel_bits) { 257 case 16: 258 format = MESA_FORMAT_B5G6R5_UNORM; 259 break; 260 case 24: 261 format = MESA_FORMAT_B8G8R8X8_UNORM; 262 break; 263 case 32: 264 format = MESA_FORMAT_B8G8R8A8_UNORM; 265 break; 266 default: 267 fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__, 268 pixel_bits); 269 return NULL; 270 } 271 272 configs = driCreateConfigs(format, 273 depth_bits_array, stencil_bits_array, 274 depth_buffer_factor, back_buffer_modes, 275 back_buffer_factor, msaa_samples_array, 1, 276 GL_TRUE, GL_FALSE); 277 if (configs == NULL) { 278 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 279 __LINE__); 280 return NULL; 281 } 282 283 return configs; 284 } 285 286 static const __DRIconfig ** 287 dri_init_screen(__DRIscreen * psp) 288 { 289 __DRIconfig **configs16, **configs24, **configs32; 290 291 TRACE; 292 293 psp->max_gl_compat_version = 21; 294 psp->max_gl_es1_version = 11; 295 psp->max_gl_es2_version = 20; 296 297 psp->extensions = dri_screen_extensions; 298 299 configs16 = swrastFillInModes(psp, 16, 16, 0, 1); 300 configs24 = swrastFillInModes(psp, 24, 24, 8, 1); 301 configs32 = swrastFillInModes(psp, 32, 24, 8, 1); 302 303 configs24 = driConcatConfigs(configs16, configs24); 304 configs32 = driConcatConfigs(configs24, configs32); 305 306 return (const __DRIconfig **)configs32; 307 } 308 309 static void 310 dri_destroy_screen(__DRIscreen * sPriv) 311 { 312 TRACE; 313 (void) sPriv; 314 } 315 316 317 /** 318 * Framebuffer and renderbuffer-related functions. 319 */ 320 321 static GLuint 322 choose_pixel_format(const struct gl_config *v) 323 { 324 int depth = v->rgbBits; 325 326 if (depth == 32 327 && v->redMask == 0xff0000 328 && v->greenMask == 0x00ff00 329 && v->blueMask == 0x0000ff) 330 return PF_A8R8G8B8; 331 else if (depth == 24 332 && v->redMask == 0xff0000 333 && v->greenMask == 0x00ff00 334 && v->blueMask == 0x0000ff) 335 return PF_X8R8G8B8; 336 else if (depth == 16 337 && v->redMask == 0xf800 338 && v->greenMask == 0x07e0 339 && v->blueMask == 0x001f) 340 return PF_R5G6B5; 341 else if (depth == 8 342 && v->redMask == 0x07 343 && v->greenMask == 0x38 344 && v->blueMask == 0xc0) 345 return PF_R3G3B2; 346 347 _mesa_problem( NULL, "unexpected format in %s", __func__ ); 348 return 0; 349 } 350 351 static void 352 swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 353 { 354 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 355 356 TRACE; 357 358 free(xrb->Base.Buffer); 359 _mesa_delete_renderbuffer(ctx, rb); 360 } 361 362 /* see bytes_per_line in libGL */ 363 static inline int 364 bytes_per_line(unsigned pitch_bits, unsigned mul) 365 { 366 unsigned mask = mul - 1; 367 368 return ((pitch_bits + mask) & ~mask) / 8; 369 } 370 371 static GLboolean 372 swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 373 GLenum internalFormat, GLuint width, GLuint height) 374 { 375 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 376 377 TRACE; 378 379 (void) ctx; 380 (void) internalFormat; 381 382 xrb->Base.Buffer = NULL; 383 rb->Width = width; 384 rb->Height = height; 385 xrb->pitch = bytes_per_line(width * xrb->bpp, 32); 386 387 return GL_TRUE; 388 } 389 390 static GLboolean 391 swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 392 GLenum internalFormat, GLuint width, GLuint height) 393 { 394 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 395 396 TRACE; 397 398 free(xrb->Base.Buffer); 399 400 swrast_alloc_front_storage(ctx, rb, internalFormat, width, height); 401 402 xrb->Base.Buffer = malloc(height * xrb->pitch); 403 404 return GL_TRUE; 405 } 406 407 static struct dri_swrast_renderbuffer * 408 swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv, 409 GLboolean front) 410 { 411 struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb); 412 struct gl_renderbuffer *rb; 413 GLuint pixel_format; 414 415 TRACE; 416 417 if (!xrb) 418 return NULL; 419 420 rb = &xrb->Base.Base; 421 422 _mesa_init_renderbuffer(rb, 0); 423 424 pixel_format = choose_pixel_format(visual); 425 426 xrb->dPriv = dPriv; 427 xrb->Base.Base.Delete = swrast_delete_renderbuffer; 428 if (front) { 429 rb->AllocStorage = swrast_alloc_front_storage; 430 } 431 else { 432 rb->AllocStorage = swrast_alloc_back_storage; 433 } 434 435 switch (pixel_format) { 436 case PF_A8R8G8B8: 437 rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; 438 rb->InternalFormat = GL_RGBA; 439 rb->_BaseFormat = GL_RGBA; 440 xrb->bpp = 32; 441 break; 442 case PF_X8R8G8B8: 443 rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; /* XXX */ 444 rb->InternalFormat = GL_RGB; 445 rb->_BaseFormat = GL_RGB; 446 xrb->bpp = 32; 447 break; 448 case PF_R5G6B5: 449 rb->Format = MESA_FORMAT_B5G6R5_UNORM; 450 rb->InternalFormat = GL_RGB; 451 rb->_BaseFormat = GL_RGB; 452 xrb->bpp = 16; 453 break; 454 case PF_R3G3B2: 455 rb->Format = MESA_FORMAT_B2G3R3_UNORM; 456 rb->InternalFormat = GL_RGB; 457 rb->_BaseFormat = GL_RGB; 458 xrb->bpp = 8; 459 break; 460 default: 461 free(xrb); 462 return NULL; 463 } 464 465 return xrb; 466 } 467 468 static void 469 swrast_map_renderbuffer(struct gl_context *ctx, 470 struct gl_renderbuffer *rb, 471 GLuint x, GLuint y, GLuint w, GLuint h, 472 GLbitfield mode, 473 GLubyte **out_map, 474 GLint *out_stride) 475 { 476 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 477 GLubyte *map = xrb->Base.Buffer; 478 int cpp = _mesa_get_format_bytes(rb->Format); 479 int stride = rb->Width * cpp; 480 481 if (rb->AllocStorage == swrast_alloc_front_storage) { 482 __DRIdrawable *dPriv = xrb->dPriv; 483 __DRIscreen *sPriv = dPriv->driScreenPriv; 484 485 xrb->map_mode = mode; 486 xrb->map_x = x; 487 xrb->map_y = rb->Height - y - h; 488 xrb->map_w = w; 489 xrb->map_h = h; 490 491 stride = w * cpp; 492 xrb->Base.Buffer = malloc(h * stride); 493 494 sPriv->swrast_loader->getImage(dPriv, x, xrb->map_y, w, h, 495 (char *) xrb->Base.Buffer, 496 dPriv->loaderPrivate); 497 498 *out_map = xrb->Base.Buffer + (h - 1) * stride; 499 *out_stride = -stride; 500 return; 501 } 502 503 assert(xrb->Base.Buffer); 504 505 if (rb->AllocStorage == swrast_alloc_back_storage) { 506 map += (rb->Height - 1) * stride; 507 stride = -stride; 508 } 509 510 map += (GLsizei)y * stride; 511 map += (GLsizei)x * cpp; 512 513 *out_map = map; 514 *out_stride = stride; 515 } 516 517 static void 518 swrast_unmap_renderbuffer(struct gl_context *ctx, 519 struct gl_renderbuffer *rb) 520 { 521 struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); 522 523 if (rb->AllocStorage == swrast_alloc_front_storage) { 524 __DRIdrawable *dPriv = xrb->dPriv; 525 __DRIscreen *sPriv = dPriv->driScreenPriv; 526 527 if (xrb->map_mode & GL_MAP_WRITE_BIT) { 528 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW, 529 xrb->map_x, xrb->map_y, 530 xrb->map_w, xrb->map_h, 531 (char *) xrb->Base.Buffer, 532 dPriv->loaderPrivate); 533 } 534 535 free(xrb->Base.Buffer); 536 xrb->Base.Buffer = NULL; 537 } 538 } 539 540 static GLboolean 541 dri_create_buffer(__DRIscreen * sPriv, 542 __DRIdrawable * dPriv, 543 const struct gl_config * visual, GLboolean isPixmap) 544 { 545 struct dri_drawable *drawable = NULL; 546 struct gl_framebuffer *fb; 547 struct dri_swrast_renderbuffer *frontrb, *backrb; 548 549 TRACE; 550 551 (void) sPriv; 552 (void) isPixmap; 553 554 drawable = CALLOC_STRUCT(dri_drawable); 555 if (drawable == NULL) 556 goto drawable_fail; 557 558 dPriv->driverPrivate = drawable; 559 drawable->dPriv = dPriv; 560 561 drawable->row = malloc(SWRAST_MAX_WIDTH * 4); 562 if (drawable->row == NULL) 563 goto drawable_fail; 564 565 fb = &drawable->Base; 566 567 /* basic framebuffer setup */ 568 _mesa_initialize_window_framebuffer(fb, visual); 569 570 /* add front renderbuffer */ 571 frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE); 572 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base); 573 574 /* add back renderbuffer */ 575 if (visual->doubleBufferMode) { 576 backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE); 577 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base.Base); 578 } 579 580 /* add software renderbuffers */ 581 _swrast_add_soft_renderbuffers(fb, 582 GL_FALSE, /* color */ 583 visual->haveDepthBuffer, 584 visual->haveStencilBuffer, 585 visual->haveAccumBuffer, 586 GL_FALSE, /* alpha */ 587 GL_FALSE /* aux bufs */); 588 589 return GL_TRUE; 590 591 drawable_fail: 592 593 if (drawable) 594 free(drawable->row); 595 596 free(drawable); 597 598 return GL_FALSE; 599 } 600 601 static void 602 dri_destroy_buffer(__DRIdrawable * dPriv) 603 { 604 TRACE; 605 606 if (dPriv) { 607 struct dri_drawable *drawable = dri_drawable(dPriv); 608 struct gl_framebuffer *fb; 609 610 free(drawable->row); 611 612 fb = &drawable->Base; 613 614 fb->DeletePending = GL_TRUE; 615 _mesa_reference_framebuffer(&fb, NULL); 616 } 617 } 618 619 static void 620 dri_swap_buffers(__DRIdrawable * dPriv) 621 { 622 __DRIscreen *sPriv = dPriv->driScreenPriv; 623 624 GET_CURRENT_CONTEXT(ctx); 625 626 struct dri_drawable *drawable = dri_drawable(dPriv); 627 struct gl_framebuffer *fb; 628 struct dri_swrast_renderbuffer *frontrb, *backrb; 629 630 TRACE; 631 632 fb = &drawable->Base; 633 634 frontrb = 635 dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 636 backrb = 637 dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 638 639 /* check for signle-buffered */ 640 if (backrb == NULL) 641 return; 642 643 /* check if swapping currently bound buffer */ 644 if (ctx && ctx->DrawBuffer == fb) { 645 /* flush pending rendering */ 646 _mesa_notifySwapBuffers(ctx); 647 } 648 649 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 650 0, 0, 651 frontrb->Base.Base.Width, 652 frontrb->Base.Base.Height, 653 (char *) backrb->Base.Buffer, 654 dPriv->loaderPrivate); 655 } 656 657 658 /** 659 * General device driver functions. 660 */ 661 662 static void 663 get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h ) 664 { 665 __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv; 666 __DRIscreen *sPriv = dPriv->driScreenPriv; 667 int x, y; 668 669 sPriv->swrast_loader->getDrawableInfo(dPriv, 670 &x, &y, w, h, 671 dPriv->loaderPrivate); 672 } 673 674 static void 675 swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb ) 676 { 677 GLsizei width, height; 678 679 get_window_size(fb, &width, &height); 680 if (fb->Width != width || fb->Height != height) { 681 _mesa_resize_framebuffer(ctx, fb, width, height); 682 } 683 } 684 685 static const GLubyte * 686 get_string(struct gl_context *ctx, GLenum pname) 687 { 688 (void) ctx; 689 switch (pname) { 690 case GL_VENDOR: 691 return (const GLubyte *) swrast_vendor_string; 692 case GL_RENDERER: 693 return (const GLubyte *) swrast_renderer_string; 694 default: 695 return NULL; 696 } 697 } 698 699 static void 700 update_state( struct gl_context *ctx, GLuint new_state ) 701 { 702 /* not much to do here - pass it on */ 703 _swrast_InvalidateState( ctx, new_state ); 704 _swsetup_InvalidateState( ctx, new_state ); 705 _vbo_InvalidateState( ctx, new_state ); 706 _tnl_InvalidateState( ctx, new_state ); 707 } 708 709 static void 710 viewport(struct gl_context *ctx) 711 { 712 struct gl_framebuffer *draw = ctx->WinSysDrawBuffer; 713 struct gl_framebuffer *read = ctx->WinSysReadBuffer; 714 715 swrast_check_and_update_window_size(ctx, draw); 716 swrast_check_and_update_window_size(ctx, read); 717 } 718 719 static mesa_format swrastChooseTextureFormat(struct gl_context * ctx, 720 GLenum target, 721 GLint internalFormat, 722 GLenum format, 723 GLenum type) 724 { 725 if (internalFormat == GL_RGB) 726 return MESA_FORMAT_B8G8R8X8_UNORM; 727 return _mesa_choose_tex_format(ctx, target, internalFormat, format, type); 728 } 729 730 static void 731 swrast_init_driver_functions(struct dd_function_table *driver) 732 { 733 driver->GetString = get_string; 734 driver->UpdateState = update_state; 735 driver->Viewport = viewport; 736 driver->ChooseTextureFormat = swrastChooseTextureFormat; 737 driver->MapRenderbuffer = swrast_map_renderbuffer; 738 driver->UnmapRenderbuffer = swrast_unmap_renderbuffer; 739 } 740 741 /** 742 * Context-related functions. 743 */ 744 745 static GLboolean 746 dri_create_context(gl_api api, 747 const struct gl_config * visual, 748 __DRIcontext * cPriv, 749 unsigned major_version, 750 unsigned minor_version, 751 uint32_t flags, 752 bool notify_reset, 753 unsigned *error, 754 void *sharedContextPrivate) 755 { 756 struct dri_context *ctx = NULL; 757 struct dri_context *share = (struct dri_context *)sharedContextPrivate; 758 struct gl_context *mesaCtx = NULL; 759 struct gl_context *sharedCtx = NULL; 760 struct dd_function_table functions; 761 762 TRACE; 763 764 /* Flag filtering is handled in dri2CreateContextAttribs. 765 */ 766 (void) flags; 767 768 ctx = CALLOC_STRUCT(dri_context); 769 if (ctx == NULL) { 770 *error = __DRI_CTX_ERROR_NO_MEMORY; 771 goto context_fail; 772 } 773 774 cPriv->driverPrivate = ctx; 775 ctx->cPriv = cPriv; 776 777 /* build table of device driver functions */ 778 _mesa_init_driver_functions(&functions); 779 swrast_init_driver_functions(&functions); 780 781 if (share) { 782 sharedCtx = &share->Base; 783 } 784 785 mesaCtx = &ctx->Base; 786 787 /* basic context setup */ 788 if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) { 789 *error = __DRI_CTX_ERROR_NO_MEMORY; 790 goto context_fail; 791 } 792 793 driContextSetFlags(mesaCtx, flags); 794 795 /* create module contexts */ 796 _swrast_CreateContext( mesaCtx ); 797 _vbo_CreateContext( mesaCtx ); 798 _tnl_CreateContext( mesaCtx ); 799 _swsetup_CreateContext( mesaCtx ); 800 _swsetup_Wakeup( mesaCtx ); 801 802 /* use default TCL pipeline */ 803 { 804 TNLcontext *tnl = TNL_CONTEXT(mesaCtx); 805 tnl->Driver.RunPipeline = _tnl_run_pipeline; 806 } 807 808 _mesa_meta_init(mesaCtx); 809 _mesa_enable_sw_extensions(mesaCtx); 810 811 _mesa_compute_version(mesaCtx); 812 813 _mesa_initialize_dispatch_tables(mesaCtx); 814 _mesa_initialize_vbo_vtxfmt(mesaCtx); 815 816 *error = __DRI_CTX_ERROR_SUCCESS; 817 return GL_TRUE; 818 819 context_fail: 820 821 free(ctx); 822 823 return GL_FALSE; 824 } 825 826 static void 827 dri_destroy_context(__DRIcontext * cPriv) 828 { 829 TRACE; 830 831 if (cPriv) { 832 struct dri_context *ctx = dri_context(cPriv); 833 struct gl_context *mesaCtx; 834 835 mesaCtx = &ctx->Base; 836 837 _mesa_meta_free(mesaCtx); 838 _swsetup_DestroyContext( mesaCtx ); 839 _swrast_DestroyContext( mesaCtx ); 840 _tnl_DestroyContext( mesaCtx ); 841 _vbo_DestroyContext( mesaCtx ); 842 _mesa_destroy_context( mesaCtx ); 843 } 844 } 845 846 static GLboolean 847 dri_make_current(__DRIcontext * cPriv, 848 __DRIdrawable * driDrawPriv, 849 __DRIdrawable * driReadPriv) 850 { 851 struct gl_context *mesaCtx; 852 struct gl_framebuffer *mesaDraw; 853 struct gl_framebuffer *mesaRead; 854 TRACE; 855 856 if (cPriv) { 857 struct dri_context *ctx = dri_context(cPriv); 858 struct dri_drawable *draw; 859 struct dri_drawable *read; 860 861 if (!driDrawPriv || !driReadPriv) 862 return GL_FALSE; 863 864 draw = dri_drawable(driDrawPriv); 865 read = dri_drawable(driReadPriv); 866 mesaCtx = &ctx->Base; 867 mesaDraw = &draw->Base; 868 mesaRead = &read->Base; 869 870 /* check for same context and buffer */ 871 if (mesaCtx == _mesa_get_current_context() 872 && mesaCtx->DrawBuffer == mesaDraw 873 && mesaCtx->ReadBuffer == mesaRead) { 874 return GL_TRUE; 875 } 876 877 _glapi_check_multithread(); 878 879 swrast_check_and_update_window_size(mesaCtx, mesaDraw); 880 if (mesaRead != mesaDraw) 881 swrast_check_and_update_window_size(mesaCtx, mesaRead); 882 883 _mesa_make_current( mesaCtx, 884 mesaDraw, 885 mesaRead ); 886 } 887 else { 888 /* unbind */ 889 _mesa_make_current( NULL, NULL, NULL ); 890 } 891 892 return GL_TRUE; 893 } 894 895 static GLboolean 896 dri_unbind_context(__DRIcontext * cPriv) 897 { 898 TRACE; 899 (void) cPriv; 900 901 /* Unset current context and dispath table */ 902 _mesa_make_current(NULL, NULL, NULL); 903 904 return GL_TRUE; 905 } 906 907 static void 908 dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, 909 int w, int h) 910 { 911 __DRIscreen *sPriv = dPriv->driScreenPriv; 912 void *data; 913 int iy; 914 struct dri_drawable *drawable = dri_drawable(dPriv); 915 struct gl_framebuffer *fb; 916 struct dri_swrast_renderbuffer *frontrb, *backrb; 917 918 TRACE; 919 920 fb = &drawable->Base; 921 922 frontrb = 923 dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 924 backrb = 925 dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 926 927 /* check for signle-buffered */ 928 if (backrb == NULL) 929 return; 930 931 iy = frontrb->Base.Base.Height - y - h; 932 data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8)); 933 sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 934 x, iy, w, h, 935 frontrb->pitch, 936 data, 937 dPriv->loaderPrivate); 938 } 939 940 941 static const struct __DriverAPIRec swrast_driver_api = { 942 .InitScreen = dri_init_screen, 943 .DestroyScreen = dri_destroy_screen, 944 .CreateContext = dri_create_context, 945 .DestroyContext = dri_destroy_context, 946 .CreateBuffer = dri_create_buffer, 947 .DestroyBuffer = dri_destroy_buffer, 948 .SwapBuffers = dri_swap_buffers, 949 .MakeCurrent = dri_make_current, 950 .UnbindContext = dri_unbind_context, 951 .CopySubBuffer = dri_copy_sub_buffer, 952 }; 953 954 static const struct __DRIDriverVtableExtensionRec swrast_vtable = { 955 .base = { __DRI_DRIVER_VTABLE, 1 }, 956 .vtable = &swrast_driver_api, 957 }; 958 959 static const __DRIextension *swrast_driver_extensions[] = { 960 &driCoreExtension.base, 961 &driSWRastExtension.base, 962 &driCopySubBufferExtension.base, 963 &dri2ConfigQueryExtension.base, 964 &swrast_vtable.base, 965 NULL 966 }; 967 968 PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void) 969 { 970 globalDriverAPI = &swrast_driver_api; 971 972 return swrast_driver_extensions; 973 } 974