Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / swrast / swrast.c
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
81 const 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
116 static void
117 setupLoaderExtensions(__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
128 static __DRIconfig **
129 swrastFillInModes(__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
191 static __DRIscreen *
192 driCreateNewScreen(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
225 static void driDestroyScreen(__DRIscreen *psp)
226 {
227 TRACE;
228
229 if (psp) {
230 _mesa_free(psp);
231 }
232 }
233
234 static 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
246 static GLuint
247 choose_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
277 static void
278 swrast_delete_renderbuffer(struct gl_renderbuffer *rb)
279 {
280 TRACE;
281
282 _mesa_free(rb->Data);
283 _mesa_free(rb);
284 }
285
286 static GLboolean
287 swrast_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
321 static GLboolean
322 swrast_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
338 static struct swrast_renderbuffer *
339 swrast_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
404 static __DRIdrawable *
405 driCreateNewDrawable(__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
448 static void
449 driDestroyDrawable(__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
463 static 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
499 static void
500 get_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
511 static void
512 swrast_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
522 static const GLubyte *
523 get_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
536 static void
537 update_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
546 static void
547 viewport(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
556 static void
557 swrast_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
570 static __DRIcontext *
571 driCreateNewContext(__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
627 static void
628 driDestroyContext(__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
643 static int
644 driCopyContext(__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
652 static 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
694 static int driUnbindContext(__DRIcontext *ctx)
695 {
696 TRACE;
697 (void) ctx;
698 return GL_TRUE;
699 }
700
701
702 static 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
719 static 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. */
726 PUBLIC const __DRIextension *__driDriverExtensions[] = {
727 &driCoreExtension.base,
728 &driSWRastExtension.base,
729 NULL
730 };