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