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