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