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