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