swrast.c revision 5a46e176715b0eae7b8a715e8aec42f5a27214fc
1/* 2 * Copyright (C) 2008 George Sapountzis <gsap7@yahoo.gr> 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 */ 21 22/* 23 * DRI software rasterizer 24 * 25 * This is the mesa swrast module packaged into a DRI driver structure. 26 * 27 * The front-buffer is allocated by the loader. The loader provides read/write 28 * callbacks for access to the front-buffer. The driver uses a scratch row for 29 * front-buffer rendering to avoid repeated calls to the loader. 30 * 31 * The back-buffer is allocated by the driver and is private. 32 */ 33 34#include "main/context.h" 35#include "main/extensions.h" 36#include "main/framebuffer.h" 37#include "main/imports.h" 38#include "main/renderbuffer.h" 39#include "swrast/swrast.h" 40#include "swrast_setup/swrast_setup.h" 41#include "tnl/tnl.h" 42#include "tnl/t_context.h" 43#include "tnl/t_pipeline.h" 44#include "vbo/vbo.h" 45#include "drivers/common/driverfuncs.h" 46#include "utils.h" 47 48#include "swrast_priv.h" 49 50 51#define need_GL_VERSION_1_3 52#define need_GL_VERSION_1_4 53#define need_GL_VERSION_1_5 54#define need_GL_VERSION_2_0 55#define need_GL_VERSION_2_1 56 57/* sw extensions for imaging */ 58#define need_GL_EXT_blend_color 59#define need_GL_EXT_blend_minmax 60#define need_GL_EXT_convolution 61#define need_GL_EXT_histogram 62#define need_GL_SGI_color_table 63 64/* sw extensions not associated with some GL version */ 65#define need_GL_ARB_shader_objects 66#define need_GL_ARB_vertex_program 67#define need_GL_APPLE_vertex_array_object 68#define need_GL_ATI_fragment_shader 69#define need_GL_EXT_depth_bounds_test 70#define need_GL_EXT_framebuffer_object 71#define need_GL_EXT_framebuffer_blit 72#define need_GL_EXT_gpu_program_parameters 73#define need_GL_EXT_paletted_texture 74#define need_GL_IBM_multimode_draw_arrays 75#define need_GL_MESA_resize_buffers 76#define need_GL_NV_vertex_program 77#define need_GL_NV_fragment_program 78 79#include "extension_helper.h" 80 81const struct dri_extension card_extensions[] = 82{ 83 { "GL_VERSION_1_3", GL_VERSION_1_3_functions }, 84 { "GL_VERSION_1_4", GL_VERSION_1_4_functions }, 85 { "GL_VERSION_1_5", GL_VERSION_1_5_functions }, 86 { "GL_VERSION_2_0", GL_VERSION_2_0_functions }, 87 { "GL_VERSION_2_1", GL_VERSION_2_1_functions }, 88 89 { "GL_EXT_blend_color", GL_EXT_blend_color_functions }, 90 { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions }, 91 { "GL_EXT_convolution", GL_EXT_convolution_functions }, 92 { "GL_EXT_histogram", GL_EXT_histogram_functions }, 93 { "GL_SGI_color_table", GL_SGI_color_table_functions }, 94 95 { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, 96 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, 97 { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions }, 98 { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions }, 99 { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions }, 100 { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, 101 { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions }, 102 { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions }, 103 { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions }, 104 { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions }, 105 { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions }, 106 { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, 107 { "GL_NV_fragment_program", GL_NV_fragment_program_functions }, 108 { NULL, NULL } 109}; 110 111 112/** 113 * Screen and config-related functions 114 */ 115 116static void 117setupLoaderExtensions(__DRIscreen *psp, 118 const __DRIextension **extensions) 119{ 120 int i; 121 122 for (i = 0; extensions[i]; i++) { 123 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) 124 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; 125 } 126} 127 128static __DRIconfig ** 129swrastFillInModes(__DRIscreen *psp, 130 unsigned pixel_bits, unsigned depth_bits, 131 unsigned stencil_bits, GLboolean have_back_buffer) 132{ 133 __DRIconfig **configs; 134 unsigned depth_buffer_factor; 135 unsigned back_buffer_factor; 136 GLenum fb_format; 137 GLenum fb_type; 138 139 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 140 * support pageflipping at all. 141 */ 142 static const GLenum back_buffer_modes[] = { 143 GLX_NONE, GLX_SWAP_UNDEFINED_OML 144 }; 145 146 uint8_t depth_bits_array[4]; 147 uint8_t stencil_bits_array[4]; 148 149 depth_bits_array[0] = 0; 150 depth_bits_array[1] = 0; 151 depth_bits_array[2] = depth_bits; 152 depth_bits_array[3] = depth_bits; 153 154 /* Just like with the accumulation buffer, always provide some modes 155 * with a stencil buffer. 156 */ 157 stencil_bits_array[0] = 0; 158 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; 159 stencil_bits_array[2] = 0; 160 stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits; 161 162 depth_buffer_factor = 4; 163 back_buffer_factor = 2; 164 165 if (pixel_bits == 8) { 166 fb_format = GL_RGB; 167 fb_type = GL_UNSIGNED_BYTE_2_3_3_REV; 168 } 169 else if (pixel_bits == 16) { 170 fb_format = GL_RGB; 171 fb_type = GL_UNSIGNED_SHORT_5_6_5; 172 } 173 else { 174 fb_format = GL_BGRA; 175 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; 176 } 177 178 configs = driCreateConfigs(fb_format, fb_type, 179 depth_bits_array, stencil_bits_array, 180 depth_buffer_factor, back_buffer_modes, 181 back_buffer_factor); 182 if (configs == NULL) { 183 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 184 __LINE__); 185 return NULL; 186 } 187 188 return configs; 189} 190 191static __DRIscreen * 192driCreateNewScreen(int scrn, const __DRIextension **extensions, 193 const __DRIconfig ***driver_configs, void *data) 194{ 195 static const __DRIextension *emptyExtensionList[] = { NULL }; 196 __DRIscreen *psp; 197 __DRIconfig **configs8, **configs16, **configs32; 198 199 (void) data; 200 201 TRACE; 202 203 psp = _mesa_calloc(sizeof(*psp)); 204 if (!psp) 205 return NULL; 206 207 setupLoaderExtensions(psp, extensions); 208 209 psp->num = scrn; 210 psp->extensions = emptyExtensionList; 211 212 configs8 = swrastFillInModes(psp, 8, 8, 0, 1); 213 configs16 = swrastFillInModes(psp, 16, 16, 0, 1); 214 configs32 = swrastFillInModes(psp, 32, 24, 8, 1); 215 216 configs16 = (__DRIconfig **)driConcatConfigs(configs8, configs16); 217 218 *driver_configs = driConcatConfigs(configs16, configs32); 219 220 driInitExtensions( NULL, card_extensions, GL_FALSE ); 221 222 return psp; 223} 224 225static void driDestroyScreen(__DRIscreen *psp) 226{ 227 TRACE; 228 229 if (psp) { 230 _mesa_free(psp); 231 } 232} 233 234static const __DRIextension **driGetExtensions(__DRIscreen *psp) 235{ 236 TRACE; 237 238 return psp->extensions; 239} 240 241 242/** 243 * Framebuffer and renderbuffer-related functions. 244 */ 245 246static GLuint 247choose_pixel_format(const GLvisual *v) 248{ 249 if (v->rgbMode) { 250 int bpp = v->rgbBits; 251 252 if (bpp == 32 253 && v->redMask == 0xff0000 254 && v->greenMask == 0x00ff00 255 && v->blueMask == 0x0000ff) 256 return PF_A8R8G8B8; 257 else if (bpp == 16 258 && v->redMask == 0xf800 259 && v->greenMask == 0x07e0 260 && v->blueMask == 0x001f) 261 return PF_R5G6B5; 262 else if (bpp == 8 263 && v->redMask == 0x07 264 && v->greenMask == 0x38 265 && v->blueMask == 0xc0) 266 return PF_R3G3B2; 267 } 268 else { 269 if (v->indexBits == 8) 270 return PF_CI8; 271 } 272 273 _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); 274 return 0; 275} 276 277static void 278swrast_delete_renderbuffer(struct gl_renderbuffer *rb) 279{ 280 TRACE; 281 282 _mesa_free(rb->Data); 283 _mesa_free(rb); 284} 285 286static GLboolean 287swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, 288 GLenum internalFormat, GLuint width, GLuint height) 289{ 290 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); 291 int bpp; 292 unsigned mask = PITCH_ALIGN_BITS - 1; 293 294 TRACE; 295 296 rb->Data = NULL; 297 rb->Width = width; 298 rb->Height = height; 299 300 switch (internalFormat) { 301 case GL_RGB: 302 bpp = rb->RedBits + rb->GreenBits + rb->BlueBits; 303 break; 304 case GL_RGBA: 305 bpp = rb->RedBits + rb->GreenBits + rb->BlueBits + rb->AlphaBits; 306 break; 307 case GL_COLOR_INDEX8_EXT: 308 bpp = rb->IndexBits; 309 break; 310 default: 311 _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); 312 return GL_FALSE; 313 } 314 315 /* always pad to PITCH_ALIGN_BITS */ 316 xrb->pitch = ((width * bpp + mask) & ~mask) / 8; 317 318 return GL_TRUE; 319} 320 321static GLboolean 322swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, 323 GLenum internalFormat, GLuint width, GLuint height) 324{ 325 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); 326 327 TRACE; 328 329 _mesa_free(rb->Data); 330 331 swrast_alloc_front_storage(ctx, rb, internalFormat, width, height); 332 333 rb->Data = _mesa_malloc(height * xrb->pitch); 334 335 return GL_TRUE; 336} 337 338static struct swrast_renderbuffer * 339swrast_new_renderbuffer(const GLvisual *visual, GLboolean front) 340{ 341 struct swrast_renderbuffer *xrb = _mesa_calloc(sizeof *xrb); 342 GLuint pixel_format; 343 344 TRACE; 345 346 if (!xrb) 347 return NULL; 348 349 _mesa_init_renderbuffer(&xrb->Base, 0); 350 351 pixel_format = choose_pixel_format(visual); 352 353 xrb->Base.Delete = swrast_delete_renderbuffer; 354 if (front) { 355 xrb->Base.AllocStorage = swrast_alloc_front_storage; 356 swrast_set_span_funcs_front(xrb, pixel_format); 357 } 358 else { 359 xrb->Base.AllocStorage = swrast_alloc_back_storage; 360 swrast_set_span_funcs_back(xrb, pixel_format); 361 } 362 363 switch (pixel_format) { 364 case PF_A8R8G8B8: 365 xrb->Base.InternalFormat = GL_RGBA; 366 xrb->Base._BaseFormat = GL_RGBA; 367 xrb->Base.DataType = GL_UNSIGNED_BYTE; 368 xrb->Base.RedBits = 8 * sizeof(GLubyte); 369 xrb->Base.GreenBits = 8 * sizeof(GLubyte); 370 xrb->Base.BlueBits = 8 * sizeof(GLubyte); 371 xrb->Base.AlphaBits = 8 * sizeof(GLubyte); 372 break; 373 case PF_R5G6B5: 374 xrb->Base.InternalFormat = GL_RGB; 375 xrb->Base._BaseFormat = GL_RGB; 376 xrb->Base.DataType = GL_UNSIGNED_BYTE; 377 xrb->Base.RedBits = 5 * sizeof(GLubyte); 378 xrb->Base.GreenBits = 6 * sizeof(GLubyte); 379 xrb->Base.BlueBits = 5 * sizeof(GLubyte); 380 xrb->Base.AlphaBits = 0; 381 break; 382 case PF_R3G3B2: 383 xrb->Base.InternalFormat = GL_RGB; 384 xrb->Base._BaseFormat = GL_RGB; 385 xrb->Base.DataType = GL_UNSIGNED_BYTE; 386 xrb->Base.RedBits = 3 * sizeof(GLubyte); 387 xrb->Base.GreenBits = 3 * sizeof(GLubyte); 388 xrb->Base.BlueBits = 2 * sizeof(GLubyte); 389 xrb->Base.AlphaBits = 0; 390 break; 391 case PF_CI8: 392 xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT; 393 xrb->Base._BaseFormat = GL_COLOR_INDEX; 394 xrb->Base.DataType = GL_UNSIGNED_BYTE; 395 xrb->Base.IndexBits = 8 * sizeof(GLubyte); 396 break; 397 default: 398 return NULL; 399 } 400 401 return xrb; 402} 403 404static __DRIdrawable * 405driCreateNewDrawable(__DRIscreen *screen, 406 const __DRIconfig *config, void *data) 407{ 408 __DRIdrawable *buf; 409 struct swrast_renderbuffer *frontrb, *backrb; 410 411 TRACE; 412 413 buf = _mesa_calloc(sizeof *buf); 414 if (!buf) 415 return NULL; 416 417 buf->loaderPrivate = data; 418 419 buf->driScreenPriv = screen; 420 421 buf->row = _mesa_malloc(MAX_WIDTH * 4); 422 423 /* basic framebuffer setup */ 424 _mesa_initialize_framebuffer(&buf->Base, &config->modes); 425 426 /* add front renderbuffer */ 427 frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE); 428 _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base); 429 430 /* add back renderbuffer */ 431 if (config->modes.doubleBufferMode) { 432 backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE); 433 _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base); 434 } 435 436 /* add software renderbuffers */ 437 _mesa_add_soft_renderbuffers(&buf->Base, 438 GL_FALSE, /* color */ 439 config->modes.haveDepthBuffer, 440 config->modes.haveStencilBuffer, 441 config->modes.haveAccumBuffer, 442 GL_FALSE, /* alpha */ 443 GL_FALSE /* aux bufs */); 444 445 return buf; 446} 447 448static void 449driDestroyDrawable(__DRIdrawable *buf) 450{ 451 TRACE; 452 453 if (buf) { 454 struct gl_framebuffer *fb = &buf->Base; 455 456 _mesa_free(buf->row); 457 458 fb->DeletePending = GL_TRUE; 459 _mesa_unreference_framebuffer(&fb); 460 } 461} 462 463static void driSwapBuffers(__DRIdrawable *buf) 464{ 465 GET_CURRENT_CONTEXT(ctx); 466 467 struct swrast_renderbuffer *frontrb = 468 swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 469 struct swrast_renderbuffer *backrb = 470 swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); 471 472 __DRIscreen *screen = buf->driScreenPriv; 473 474 TRACE; 475 476 /* check for signle-buffered */ 477 if (backrb == NULL) 478 return; 479 480 /* check if swapping currently bound buffer */ 481 if (ctx && ctx->DrawBuffer == &(buf->Base)) { 482 /* flush pending rendering */ 483 _mesa_notifySwapBuffers(ctx); 484 } 485 486 screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP, 487 0, 0, 488 frontrb->Base.Width, 489 frontrb->Base.Height, 490 backrb->Base.Data, 491 buf->loaderPrivate); 492} 493 494 495/** 496 * General device driver functions. 497 */ 498 499static void 500get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h ) 501{ 502 __DRIdrawable *buf = swrast_drawable(fb); 503 __DRIscreen *screen = buf->driScreenPriv; 504 int x, y; 505 506 screen->swrast_loader->getDrawableInfo(buf, 507 &x, &y, w, h, 508 buf->loaderPrivate); 509} 510 511static void 512swrast_check_and_update_window_size( GLcontext *ctx, GLframebuffer *fb ) 513{ 514 GLsizei width, height; 515 516 get_window_size(fb, &width, &height); 517 if (fb->Width != width || fb->Height != height) { 518 _mesa_resize_framebuffer(ctx, fb, width, height); 519 } 520} 521 522static const GLubyte * 523get_string(GLcontext *ctx, GLenum pname) 524{ 525 (void) ctx; 526 switch (pname) { 527 case GL_VENDOR: 528 return (const GLubyte *) "Mesa Project"; 529 case GL_RENDERER: 530 return (const GLubyte *) "Software Rasterizer"; 531 default: 532 return NULL; 533 } 534} 535 536static void 537update_state( GLcontext *ctx, GLuint new_state ) 538{ 539 /* not much to do here - pass it on */ 540 _swrast_InvalidateState( ctx, new_state ); 541 _swsetup_InvalidateState( ctx, new_state ); 542 _vbo_InvalidateState( ctx, new_state ); 543 _tnl_InvalidateState( ctx, new_state ); 544} 545 546static void 547viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) 548{ 549 GLframebuffer *draw = ctx->WinSysDrawBuffer; 550 GLframebuffer *read = ctx->WinSysReadBuffer; 551 552 swrast_check_and_update_window_size(ctx, draw); 553 swrast_check_and_update_window_size(ctx, read); 554} 555 556static void 557swrast_init_driver_functions(struct dd_function_table *driver) 558{ 559 driver->GetString = get_string; 560 driver->UpdateState = update_state; 561 driver->GetBufferSize = NULL; 562 driver->Viewport = viewport; 563} 564 565 566/** 567 * Context-related functions. 568 */ 569 570static __DRIcontext * 571driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, 572 __DRIcontext *shared, void *data) 573{ 574 __DRIcontext *ctx; 575 GLcontext *mesaCtx; 576 struct dd_function_table functions; 577 578 TRACE; 579 580 ctx = _mesa_calloc(sizeof *ctx); 581 if (!ctx) 582 return NULL; 583 584 ctx->loaderPrivate = data; 585 586 ctx->driScreenPriv = screen; 587 588 /* build table of device driver functions */ 589 _mesa_init_driver_functions(&functions); 590 swrast_init_driver_functions(&functions); 591 592 if (!_mesa_initialize_context(&ctx->Base, &config->modes, 593 shared ? &shared->Base : NULL, 594 &functions, (void *) ctx)) { 595 _mesa_free(ctx); 596 return NULL; 597 } 598 599 mesaCtx = &ctx->Base; 600 601 /* do bounds checking to prevent segfaults and server crashes! */ 602 mesaCtx->Const.CheckArrayBounds = GL_TRUE; 603 604 /* create module contexts */ 605 _swrast_CreateContext( mesaCtx ); 606 _vbo_CreateContext( mesaCtx ); 607 _tnl_CreateContext( mesaCtx ); 608 _swsetup_CreateContext( mesaCtx ); 609 _swsetup_Wakeup( mesaCtx ); 610 611 /* use default TCL pipeline */ 612 { 613 TNLcontext *tnl = TNL_CONTEXT(mesaCtx); 614 tnl->Driver.RunPipeline = _tnl_run_pipeline; 615 } 616 617 _mesa_enable_sw_extensions(mesaCtx); 618 _mesa_enable_1_3_extensions(mesaCtx); 619 _mesa_enable_1_4_extensions(mesaCtx); 620 _mesa_enable_1_5_extensions(mesaCtx); 621 _mesa_enable_2_0_extensions(mesaCtx); 622 _mesa_enable_2_1_extensions(mesaCtx); 623 624 return ctx; 625} 626 627static void 628driDestroyContext(__DRIcontext *ctx) 629{ 630 GLcontext *mesaCtx; 631 TRACE; 632 633 if (ctx) { 634 mesaCtx = &ctx->Base; 635 _swsetup_DestroyContext( mesaCtx ); 636 _swrast_DestroyContext( mesaCtx ); 637 _tnl_DestroyContext( mesaCtx ); 638 _vbo_DestroyContext( mesaCtx ); 639 _mesa_destroy_context( mesaCtx ); 640 } 641} 642 643static int 644driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) 645{ 646 TRACE; 647 648 _mesa_copy_context(&src->Base, &dst->Base, mask); 649 return GL_TRUE; 650} 651 652static int driBindContext(__DRIcontext *ctx, 653 __DRIdrawable *draw, 654 __DRIdrawable *read) 655{ 656 GLcontext *mesaCtx; 657 GLframebuffer *mesaDraw; 658 GLframebuffer *mesaRead; 659 TRACE; 660 661 if (ctx) { 662 if (!draw || !read) 663 return GL_FALSE; 664 665 mesaCtx = &ctx->Base; 666 mesaDraw = &draw->Base; 667 mesaRead = &read->Base; 668 669 /* check for same context and buffer */ 670 if (mesaCtx == _mesa_get_current_context() 671 && mesaCtx->DrawBuffer == mesaDraw 672 && mesaCtx->ReadBuffer == mesaRead) { 673 return GL_TRUE; 674 } 675 676 _glapi_check_multithread(); 677 678 swrast_check_and_update_window_size(mesaCtx, mesaDraw); 679 if (read != draw) 680 swrast_check_and_update_window_size(mesaCtx, mesaRead); 681 682 _mesa_make_current( mesaCtx, 683 mesaDraw, 684 mesaRead ); 685 } 686 else { 687 /* unbind */ 688 _mesa_make_current( NULL, NULL, NULL ); 689 } 690 691 return GL_TRUE; 692} 693 694static int driUnbindContext(__DRIcontext *ctx) 695{ 696 TRACE; 697 (void) ctx; 698 return GL_TRUE; 699} 700 701 702static const __DRIcoreExtension driCoreExtension = { 703 { __DRI_CORE, __DRI_CORE_VERSION }, 704 NULL, /* driCreateNewScreen */ 705 driDestroyScreen, 706 driGetExtensions, 707 driGetConfigAttrib, 708 driIndexConfigAttrib, 709 NULL, /* driCreateNewDrawable */ 710 driDestroyDrawable, 711 driSwapBuffers, 712 driCreateNewContext, 713 driCopyContext, 714 driDestroyContext, 715 driBindContext, 716 driUnbindContext 717}; 718 719static const __DRIswrastExtension driSWRastExtension = { 720 { __DRI_SWRAST, __DRI_SWRAST_VERSION }, 721 driCreateNewScreen, 722 driCreateNewDrawable 723}; 724 725/* This is the table of extensions that the loader will dlsym() for. */ 726PUBLIC const __DRIextension *__driDriverExtensions[] = { 727 &driCoreExtension.base, 728 &driSWRastExtension.base, 729 NULL 730}; 731